Firmware SDK
twr_usb_cdc.c
1 #include <twr_usb_cdc.h>
2 #include <twr_scheduler.h>
3 #include <twr_fifo.h>
4 #include <twr_system.h>
5 
6 #include <usbd_core.h>
7 #include <usbd_cdc.h>
8 #include <usbd_cdc_if.h>
9 #include <usbd_desc.h>
10 
11 #include <stm32l0xx.h>
12 
13 static struct
14 {
15  twr_fifo_t receive_fifo;
16  uint8_t receive_buffer[1024];
17  uint8_t transmit_buffer[512];
18  size_t transmit_length;
20 
21 } _twr_usb_cdc;
22 
23 USBD_HandleTypeDef hUsbDeviceFS;
24 
25 static void _twr_usb_cdc_task_start(void *param);
26 static void _twr_usb_cdc_task(void *param);
27 static void _twr_usb_cdc_init_hsi48();
28 
29 void twr_usb_cdc_init(void)
30 {
31  memset(&_twr_usb_cdc, 0, sizeof(_twr_usb_cdc));
32 
33  _twr_usb_cdc_init_hsi48();
34 
35  twr_fifo_init(&_twr_usb_cdc.receive_fifo, _twr_usb_cdc.receive_buffer, sizeof(_twr_usb_cdc.receive_buffer));
36 
37  __HAL_RCC_GPIOA_CLK_ENABLE();
38 
39  USBD_Init(&hUsbDeviceFS, &FS_Desc, DEVICE_FS);
40  USBD_RegisterClass(&hUsbDeviceFS, &USBD_CDC);
41  USBD_CDC_RegisterInterface(&hUsbDeviceFS, &USBD_Interface_fops_FS);
42 
43  _twr_usb_cdc.task_id = twr_scheduler_register(_twr_usb_cdc_task_start, NULL, 0);
44 }
45 
46 bool twr_usb_cdc_write(const void *buffer, size_t length)
47 {
48  if (length > (sizeof(_twr_usb_cdc.transmit_buffer) - _twr_usb_cdc.transmit_length))
49  {
50  return false;
51  }
52 
53  memcpy(&_twr_usb_cdc.transmit_buffer[_twr_usb_cdc.transmit_length], buffer, length);
54 
55  _twr_usb_cdc.transmit_length += length;
56 
57  twr_scheduler_plan_now(_twr_usb_cdc.task_id);
58 
59  return true;
60 }
61 
62 size_t twr_usb_cdc_read(void *buffer, size_t length)
63 {
64  size_t bytes_read = 0;
65 
66  while (length != 0)
67  {
68  uint8_t value;
69 
70  if (twr_fifo_read(&_twr_usb_cdc.receive_fifo, &value, 1) == 1)
71  {
72  *(uint8_t *) buffer = value;
73 
74  buffer = (uint8_t *) buffer + 1;
75 
76  bytes_read++;
77  }
78  else
79  {
80  break;
81  }
82 
83  length--;
84  }
85 
86  return bytes_read;
87 }
88 
89 void twr_usb_cdc_received_data(const void *buffer, size_t length)
90 {
91  twr_fifo_irq_write(&_twr_usb_cdc.receive_fifo, (uint8_t *) buffer, length);
92 }
93 
94 static void _twr_usb_cdc_task_start(void *param)
95 {
96  (void) param;
97 
98  twr_scheduler_unregister(_twr_usb_cdc.task_id);
99 
100  _twr_usb_cdc.task_id = twr_scheduler_register(_twr_usb_cdc_task, NULL, 0);
101 
102  USBD_Start(&hUsbDeviceFS);
103 }
104 
105 static void _twr_usb_cdc_task(void *param)
106 {
107  (void) param;
108 
109  if (_twr_usb_cdc.transmit_length == 0)
110  {
111  return;
112  }
113 
114  HAL_NVIC_DisableIRQ(USB_IRQn);
115 
116  if (CDC_Transmit_FS(_twr_usb_cdc.transmit_buffer, _twr_usb_cdc.transmit_length) == USBD_OK)
117  {
118  _twr_usb_cdc.transmit_length = 0;
119  }
120 
121  HAL_NVIC_EnableIRQ(USB_IRQn);
122 
124 }
125 
126 static void _twr_usb_cdc_init_hsi48()
127 {
128  twr_system_pll_enable();
129 
130  RCC->CRRCR |= RCC_CRRCR_HSI48ON;
131  RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN;
132  SYSCFG->CFGR3 |= SYSCFG_CFGR3_ENREF_HSI48;
133 
134  while((RCC->CRRCR & RCC_CRRCR_HSI48ON) == 0)
135  {
136  continue;
137  }
138 
139  RCC->CCIPR |= RCC_USBCLKSOURCE_HSI48;
140  RCC->CFGR &= ~RCC_CFGR_STOPWUCK_Msk;
141 }
size_t twr_fifo_irq_write(twr_fifo_t *fifo, const void *buffer, size_t length)
Write data to FIFO from interrupt.
Definition: twr_fifo.c:101
size_t twr_fifo_read(twr_fifo_t *fifo, void *buffer, size_t length)
Read data from FIFO.
Definition: twr_fifo.c:63
void twr_fifo_init(twr_fifo_t *fifo, void *buffer, size_t size)
Initialize FIFO buffer.
Definition: twr_fifo.c:4
void twr_scheduler_unregister(twr_scheduler_task_id_t task_id)
Unregister specified task.
Definition: twr_scheduler.c:77
size_t twr_scheduler_task_id_t
Task ID assigned by scheduler.
Definition: twr_scheduler.h:22
void twr_scheduler_plan_now(twr_scheduler_task_id_t task_id)
Schedule specified task for immediate execution.
void twr_scheduler_plan_current_now(void)
Schedule current task for immediate execution.
twr_scheduler_task_id_t twr_scheduler_register(void(*task)(void *), void *param, twr_tick_t tick)
Register task in scheduler.
Definition: twr_scheduler.c:53
size_t twr_usb_cdc_read(void *buffer, size_t length)
Read buffer from USB CDC (non-blocking call)
Definition: twr_usb_cdc.c:62
void twr_usb_cdc_init(void)
Initialize USB CDC library.
Definition: twr_usb_cdc.c:29
bool twr_usb_cdc_write(const void *buffer, size_t length)
Write buffer to USB CDC (non-blocking call)
Definition: twr_usb_cdc.c:46
Structure of FIFO instance.
Definition: twr_fifo.h:13