GadgetSeed  0.9.6
usart.c
[詳解]
1 /** @file
2  @brief STM32 シリアル(USARTドライバ)
3 
4  @date 2015.08.09
5  @author Takashi SHUDO
6 
7  NUCLEO-F411RE Virtual COM port
8  USART2_TX PA2
9  USART2_RX PA3
10 
11  USART6_TX PA11
12  USART6_RX PA12
13 
14  32F469IDISCOVERY Virtual COM port
15  USART3_TX PB10
16  USART3_RX PB11
17 */
18 
19 #include "sysconfig.h"
20 #include "device.h"
21 #include "interrupt.h"
22 #include "fifo.h"
23 #include "tkprintf.h"
24 #include "device/uart_ioctl.h"
25 #include "task/event.h"
26 #include "task/syscall.h"
27 
28 #include "stm32f4xx_hal.h"
29 
30 #ifdef GSC_TARGET_SYSTEM_NUCLEO_F411RE // $gsc ターゲットシステムはNUCLEO_F411RE
31 static void init_rcc_usart2(void)
32 {
33  __GPIOA_CLK_ENABLE();
34 }
35 
36 static void init_gpio_usart2(void)
37 {
38  GPIO_InitTypeDef GPIO_InitStruct;
39 
40  __USART2_CLK_ENABLE();
41 
42  GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3;
43  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
44  GPIO_InitStruct.Pull = GPIO_PULLUP;
45  GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
46  GPIO_InitStruct.Alternate = GPIO_AF7_USART2;
47  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
48 }
49 
50 const struct st_device usart2_device;
51 #endif
52 
53 #ifdef GSC_TARGET_SYSTEM_32F469IDISCOVERY // $gsc ターゲットシステムは32F469IDISCOVERY
54 static void init_rcc_usart3(void)
55 {
56  __GPIOB_CLK_ENABLE();
57 }
58 
59 static void init_gpio_usart3(void)
60 {
61  GPIO_InitTypeDef GPIO_InitStruct;
62 
63  __USART3_CLK_ENABLE();
64 
65  GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11;
66  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
67  GPIO_InitStruct.Pull = GPIO_PULLUP;
68  GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
69  GPIO_InitStruct.Alternate = GPIO_AF7_USART3;
70  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
71 }
72 
73 const struct st_device usart3_device;
74 #endif
75 
76 static void init_rcc_usart6(void)
77 {
78  __GPIOC_CLK_ENABLE();
79 }
80 
81 static void init_gpio_usart6(void)
82 {
83  GPIO_InitTypeDef GPIO_InitStruct;
84 
85  __USART6_CLK_ENABLE();
86 
87  GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_12;
88  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
89  GPIO_InitStruct.Pull = GPIO_PULLUP;
90  GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
91  GPIO_InitStruct.Alternate = GPIO_AF8_USART6;
92  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
93 }
94 
95 #define MAXBUFSIZE 256
96 
97 typedef struct st_usart_data {
98  struct st_fifo rfifo;
99  unsigned char rbuf[MAXBUFSIZE];
100 
101  unsigned char tbuf[2];
102 
103  struct st_event rx_evq;
104  struct st_event tx_evq;
105 
106  UART_HandleTypeDef huart;
107 } st_usart_data;
108 
109 const struct st_device usart6_device;
110 
111 static st_usart_data usart_data[3];
112 
113 static void init_usart(st_usart_data *usart_dt, USART_TypeDef *usart, int irq)
114 {
115  UART_HandleTypeDef *huart = &(usart_dt->huart);
116 
117  huart->Instance = usart;
118  huart->Init.BaudRate = 115200;
119  huart->Init.WordLength = UART_WORDLENGTH_8B;
120  huart->Init.StopBits = UART_STOPBITS_1;
121  huart->Init.Parity = UART_PARITY_NONE;
122  huart->Init.Mode = UART_MODE_TX_RX;
123  huart->Init.HwFlowCtl = UART_HWCONTROL_NONE;
124  huart->Init.OverSampling = UART_OVERSAMPLING_16;
125  HAL_UART_Init(huart);
126 
127  HAL_NVIC_EnableIRQ(irq);
128  __HAL_UART_ENABLE_IT(huart, UART_IT_RXNE);
129 }
130 
131 void inthdr_usart(unsigned int intnum, void *sp)
132 {
133  unsigned char rd;
134  st_usart_data *usart_dt;
135  UART_HandleTypeDef *huart;
136  USART_TypeDef *usart;
137 
138  //tkprintf("USART int(%ld)\n", intnum);
139 #ifdef GSC_TARGET_SYSTEM_NUCLEO_F411RE
140  if(intnum == IRQ2VECT(USART2_IRQn)) {
141  usart_dt = &usart_data[0];
142  }
143 #endif
144 #ifdef GSC_TARGET_SYSTEM_32F469IDISCOVERY
145  if(intnum == IRQ2VECT(USART3_IRQn)) {
146  usart_dt = &usart_data[0];
147  }
148 #endif
149  else if(intnum == IRQ2VECT(USART6_IRQn)) {
150  usart_dt = &usart_data[1];
151  } else {
152  return;
153  }
154  huart = &(usart_dt->huart);
155  usart = huart->Instance;
156 
157  if(usart->SR & USART_SR_RXNE) {
158  usart->SR &= ~(USART_SR_RXNE);
159  rd = usart->DR;
160  if(write_fifo(&(usart_dt->rfifo), &rd, 1) != 0) { // FIFOへ格納
161  // SYSERR_PRINT("FIFO Over Flow\n");
162  }
163 
164 #if 0 // DEBUG
165  if(usart_dt == &usart_data[1]) {
166  tkprintf("%c", rd);
167  }
168 #endif
169  event_wakeup_ISR(sp, &(usart_dt->rx_evq), 0);
170  }
171 
172  if(usart->SR & USART_SR_PE) {
173  usart->SR &= ~(USART_SR_PE);
174  // SYSERR_PRINT("USART Parity Error\n");
175  }
176 
177  if(usart->SR & USART_SR_FE) {
178  usart->SR &= ~(USART_SR_FE);
179  // SYSERR_PRINT("USART Framing Error\n");
180  }
181 
182  if(usart->SR & USART_SR_NE) {
183  usart->SR &= ~(USART_SR_NE);
184  // SYSERR_PRINT("USART Noise Error\n");
185  }
186 
187  if(usart->SR & USART_SR_ORE) {
188  usart->SR &= ~(USART_SR_ORE);
189  // SYSERR_PRINT("USART OverRun Error\n");
190  }
191 
192  if(usart->SR & USART_SR_TXE) {
193  usart->CR1 &= ~(USART_CR1_TXEIE);
194  event_wakeup_ISR(sp, &(usart_dt->tx_evq), 0);
195  }
196 }
197 
198 const static char usart_rx_eventqueue_name[2][10] = {
199 #ifdef GSC_TARGET_SYSTEM_NUCLEO_F411RE
200  "usart2_rx",
201 #endif
202 #ifdef GSC_TARGET_SYSTEM_32F469IDISCOVERY
203  "usart3_rx",
204 #endif
205  "usart6_rx"
206 };
207 
208 const static char usart_tx_eventqueue_name[2][10] = {
209 #ifdef GSC_TARGET_SYSTEM_NUCLEO_F411RE
210  "usart2_tx",
211 #endif
212 #ifdef GSC_TARGET_SYSTEM_32F469IDISCOVERY
213  "usart3_tx",
214 #endif
215  "usart6_tx"
216 };
217 
218 /*
219  USARTを初期化する
220 
221  8bit, stop bit 1, パリティ無し, 調歩同期
222 */
223 static int usart_init(struct st_device *dev, char *param)
224 {
225  st_usart_data *usart_data = (dev->private_data);
226 
227  init_fifo(&(usart_data->rfifo), usart_data->rbuf, MAXBUFSIZE);
228 
229 #ifdef GSC_TARGET_SYSTEM_NUCLEO_F411RE
230  if(dev == &usart2_device) {
231  eventqueue_register_ISR(&(usart_data->rx_evq),
232  usart_rx_eventqueue_name[0], 0, 0, 0);
233  eventqueue_register_ISR(&(usart_data->tx_evq),
234  usart_tx_eventqueue_name[0],
235  usart_data->tbuf, sizeof(unsigned char), 2);
236  register_interrupt(IRQ2VECT(USART2_IRQn), inthdr_usart);
237 
238  init_rcc_usart2();
239  init_gpio_usart2();
240  init_usart(usart_data, USART2, USART2_IRQn);
241  }
242 #endif
243 #ifdef GSC_TARGET_SYSTEM_32F469IDISCOVERY
244  if(dev == &usart3_device) {
245  eventqueue_register_ISR(&(usart_data->rx_evq),
246  usart_rx_eventqueue_name[0], 0, 0, 0);
247  eventqueue_register_ISR(&(usart_data->tx_evq),
248  usart_tx_eventqueue_name[0],
249  usart_data->tbuf, sizeof(unsigned char), 2);
250  register_interrupt(IRQ2VECT(USART3_IRQn), inthdr_usart);
251 
252  init_rcc_usart3();
253  init_gpio_usart3();
254  init_usart(usart_data, USART3, USART3_IRQn);
255  }
256 #endif
257  else if(dev == &usart6_device) {
258  eventqueue_register_ISR(&(usart_data->rx_evq),
259  usart_rx_eventqueue_name[1], 0, 0, 0);
260  eventqueue_register_ISR(&(usart_data->tx_evq),
261  usart_tx_eventqueue_name[1],
262  usart_data->tbuf, sizeof(unsigned char), 2);
263  register_interrupt(IRQ2VECT(USART6_IRQn), inthdr_usart);
264 
265  init_rcc_usart6();
266  init_gpio_usart6();
267  init_usart(usart_data, USART6, USART6_IRQn);
268  } else {
269  return -1;
270  }
271 
272  return 0;
273 }
274 
275 /*
276  USARTからの受信データを取得する
277 */
278 static int usart_getc(struct st_device *dev, unsigned char *rd)
279 {
280  return read_fifo(&(((st_usart_data *)(dev->private_data))->rfifo), rd, 1);
281 }
282 
283 #define USART_TC_TIMEOUT 100000
284 #define USART_TE_TIMEOUT 1000
285 //#define USART_TE_TIMEOUT 0
286 
287 /*
288  USART出力
289 */
290 static int usart_putc(struct st_device *dev, unsigned char td)
291 {
292  int timeout = USART_TC_TIMEOUT;
293  USART_TypeDef *usart = ((st_usart_data *)(dev->private_data))->huart.Instance;
294 
295  while(!(usart->SR & USART_SR_TC)) {
296  timeout --;
297  if(timeout == 0) {
298  SYSERR_PRINT("USART TC timeout\n");
299  break;
300  }
301  }
302  usart->DR = td;
303 
304 #if 1 // 送信完了割り込み使用
305  usart->CR1 |= USART_CR1_TXEIE; // 送信データエンプティ割り込み許可
306 
307  if(event_wait(&(((st_usart_data *)(dev->private_data))->tx_evq), 0, USART_TE_TIMEOUT) == 0) {
308  if(USART_TE_TIMEOUT != 0) {
309  SYSERR_PRINT("USART TXE timeout\n");
310  }
311  }
312 #endif
313 
314  return 1;
315 }
316 
317 static int usart_ioctl(struct st_device *dev, unsigned int com, unsigned int arg, void *param)
318 {
319  UART_HandleTypeDef *huart = &(((st_usart_data *)(dev->private_data))->huart);
320 
321  switch(com) {
322  case IOCMD_UART_SPEED:
323  HAL_UART_DeInit(huart);
324  huart->Init.BaudRate = arg;
325  HAL_UART_Init(huart);
326  break;
327 
328  default:
329  SYSERR_PRINT("Unknown ioctl(%08lX)\n", com);
330  return -1;
331  break;
332  }
333 
334  return 0;
335 }
336 
337 static int usart_select(struct st_device *dev, unsigned int timeout)
338 {
339  if(fifo_size(&(((st_usart_data *)(dev->private_data))->rfifo)) != 0) {
340  return timeout;
341  } else {
342  return event_wait(&(((st_usart_data *)(dev->private_data))->rx_evq),
343  0, timeout);
344  }
345 }
346 
347 
348 /*
349  usart2_low
350  or
351  usart3_low
352 */
353 
354 static UART_HandleTypeDef huart_low;
355 
356 /*
357  USARTを初期化する
358 */
359 static int usart_init_low(struct st_device *dev, char *param)
360 {
361 #ifdef GSC_TARGET_SYSTEM_NUCLEO_F411RE
362  init_rcc_usart2();
363  init_gpio_usart2();
364  huart_low.Instance = USART2;
365 #endif
366 #ifdef GSC_TARGET_SYSTEM_32F469IDISCOVERY
367  init_rcc_usart3();
368  init_gpio_usart3();
369  huart_low.Instance = USART3;
370 #endif
371 
372  huart_low.Init.BaudRate = 115200;
373  huart_low.Init.WordLength = UART_WORDLENGTH_8B;
374  huart_low.Init.StopBits = UART_STOPBITS_1;
375  huart_low.Init.Parity = UART_PARITY_NONE;
376  huart_low.Init.Mode = UART_MODE_TX_RX;
377  huart_low.Init.HwFlowCtl = UART_HWCONTROL_NONE;
378  huart_low.Init.OverSampling = UART_OVERSAMPLING_16;
379  HAL_UART_Init(&huart_low);
380 
381  return 0;
382 }
383 
384 /*
385  USARTからの受信データを取得する(割り込み無し)
386 */
387 static int usart_getc_low(struct st_device *dev, unsigned char *rd)
388 {
389  USART_TypeDef *usart = huart_low.Instance;
390 
391  if(usart->SR & USART_SR_RXNE) {
392  usart->SR &= ~(USART_SR_RXNE);
393  *rd = usart->DR;
394  return 1;
395  } else {
396  return 0;
397  }
398 }
399 
400 /*
401  USART出力(割り込み無し)
402 */
403 static int usart_putc_low(struct st_device *dev, unsigned char td)
404 {
405  int timeout = USART_TC_TIMEOUT;
406  USART_TypeDef *usart = huart_low.Instance;
407 
408  while(!(usart->SR & USART_SR_TC)) {
409  timeout --;
410  if(timeout == 0) {
411  break;
412  }
413  }
414  usart->DR = td;
415 
416  return 1;
417 }
418 
419 #ifdef GSC_TARGET_SYSTEM_NUCLEO_F411RE
420 const struct st_device usart2_device = {
422  .explan = "STM32F4 USART2",
423  .private_data = (void *)&usart_data[0],
424  .register_dev = usart_init,
425  .getc = usart_getc,
426  .putc = usart_putc,
427  .ioctl = usart_ioctl,
428  .select = usart_select
429 };
430 
431 const struct st_device usart2_low_device = {
433  .explan = "Debug/Error Console",
434  .private_data = (void *)&usart_data[2],
435  .register_dev = usart_init_low,
436  .getc = usart_getc_low,
437  .putc = usart_putc_low
438 };
439 #endif
440 #ifdef GSC_TARGET_SYSTEM_32F469IDISCOVERY
441 const struct st_device usart3_device = {
443  .explan = "STM32F4 USART3",
444  .private_data = (void *)&usart_data[0],
445  .register_dev = usart_init,
446  .getc = usart_getc,
447  .putc = usart_putc,
448  .ioctl = usart_ioctl,
449  .select = usart_select
450 };
451 
452 const struct st_device usart3_low_device = {
454  .explan = "Debug/Error Console",
455  .private_data = (void *)&usart_data[2],
456  .register_dev = usart_init_low,
457  .getc = usart_getc_low,
458  .putc = usart_putc_low
459 };
460 #endif
461 
462 const struct st_device usart6_device = {
463  .name = DEF_DEV_NAME_UART "1",
464  .explan = "STM32F4 USART6",
465  .private_data = (void *)&usart_data[1],
466  .register_dev = usart_init,
467  .getc = usart_getc,
468  .putc = usart_putc,
469  .ioctl = usart_ioctl,
470  .select = usart_select
471 };
#define DEF_DEV_NAME_DEBUG
標準エラー出力用UARTデバイス名
Definition: uart_ioctl.h:15
int read_fifo(struct st_fifo *fp, unsigned char *data, unsigned int length)
fifoからデータを読み出す
Definition: fifo.c:74
汎用FIFO
Definition: fifo.h:12
void * private_data
ドライバ固有データポインタ
Definition: device.h:29
UARTドライバ ioctl 用マクロ定義
void eventqueue_register_ISR(struct st_event *evtque, const char *name, void *args, unsigned int arg_size, int arg_count)
イベントキューを登録する
Definition: event.c:36
#define DEF_DEV_NAME_UART
標準入出力用UARTデバイス名
Definition: uart_ioctl.h:16
void event_wakeup_ISR(void *sp, struct st_event *evtque, void *arg)
イベントキューにイベントを登録し、イベント待ちタスクを起動する
Definition: task.c:923
int tkprintf(const char *fmt,...)
非タスクコンテキスト実行用メッセージ出力
Definition: tkprintf.c:100
カーネル用機能限定printf
unsigned int fifo_size(struct st_fifo *fp)
fifoに書き込まれているデータのサイズを返す
Definition: fifo.c:116
int write_fifo(struct st_fifo *fp, unsigned char *data, unsigned int length)
fifoにデータを書き込む
Definition: fifo.c:37
#define IOCMD_UART_SPEED
通信速度設定 arg:設定する通信速度(bps)
Definition: uart_ioctl.h:19
イベント
Definition: event.h:15
システムコール
割り込みハンドラ
汎用リングバッファ
イベント待ちタスクキューの操作
void init_fifo(struct st_fifo *fp, unsigned char *buf, unsigned int size)
fifoを初期化する
Definition: fifo.c:20
デバイスドライバAPI
デバイスドライバ構造体
Definition: device.h:25
char name[MAX_DEVNAMELRN]
デバイス名文字列
Definition: device.h:26
int event_wait(struct st_event *evtque, void *argp, unsigned int timeout)
タスクをイベント待ち状態にする
Definition: syscall_api.c:364