GadgetSeed  0.9.6
uart.c
[詳解]
1 /** @file
2  @brief STM32F7 シリアル(UARTドライバ)
3 
4  @date 2017.01.03
5  @author Takashi SHUDO
6 
7  STM32F769I-Discovery
8  UART1_TX PA9
9  UART1_RX PA10
10 
11  UART6_TX PC6
12  UART6_RX PC7
13 
14  STM32F756G-Discovery
15  UART1_TX PA9
16  UART1_RX PB7
17 
18  UART6_TX PC6
19  UART6_RX PC7
20 */
21 
22 #include "sysconfig.h"
23 #include "device.h"
24 #include "interrupt.h"
25 #include "fifo.h"
26 #include "tkprintf.h"
27 #include "device/uart_ioctl.h"
28 #include "task/event.h"
29 #include "task/syscall.h"
30 
31 #include "stm32f7xx_hal.h"
32 #include "stm32f7xx_hal_uart.h"
33 #include "stm32f7xx_hal_uart_ex.h"
34 
35 #if defined(GSC_TARGET_SYSTEM_STM32F769IDISCOVERY)
36  #define USART_TxPin GPIO_PIN_9
37  #define USART_RxPin GPIO_PIN_10
38  #define USART_TxPort GPIOA
39  #define USART_RxPort GPIOA
40 #elif defined(GSC_TARGET_SYSTEM_STM32F746GDISCOVERY)
41  #define USART_TxPin GPIO_PIN_9
42  #define USART_RxPin GPIO_PIN_7
43  #define USART_TxPort GPIOA
44  #define USART_RxPort GPIOB
45 #endif
46 
47 static void init_rcc_uart1(void)
48 {
49  __HAL_RCC_GPIOA_CLK_ENABLE();
50 #if defined(GSC_TARGET_SYSTEM_STM32F746GDISCOVERY)
51  __HAL_RCC_GPIOB_CLK_ENABLE();
52 #endif
53 }
54 
55 static void init_rcc_uart6(void)
56 {
57  __HAL_RCC_GPIOC_CLK_ENABLE();
58 }
59 
60 static void init_gpio_uart1(void)
61 {
62  GPIO_InitTypeDef GPIO_InitStruct;
63 
64  __HAL_RCC_USART1_CLK_ENABLE();
65 
66  GPIO_InitStruct.Pin = USART_TxPin;
67  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
68  GPIO_InitStruct.Pull = GPIO_PULLUP;
69  GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
70  GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
71  HAL_GPIO_Init(USART_TxPort, &GPIO_InitStruct);
72 
73  GPIO_InitStruct.Pin = USART_RxPin;
74  HAL_GPIO_Init(USART_RxPort, &GPIO_InitStruct);
75 
76  /* Peripheral interrupt init */
77  HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);
78  HAL_NVIC_EnableIRQ(USART1_IRQn);
79 }
80 
81 static void init_gpio_uart6(void)
82 {
83  GPIO_InitTypeDef GPIO_InitStruct;
84 
85  __HAL_RCC_USART6_CLK_ENABLE();
86 
87  GPIO_InitStruct.Pin = GPIO_PIN_6 | GPIO_PIN_7;
88  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
89  GPIO_InitStruct.Pull = GPIO_PULLUP;
90  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
91  GPIO_InitStruct.Alternate = GPIO_AF8_USART6;
92  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
93 
94  /* Peripheral interrupt init */
95  HAL_NVIC_SetPriority(USART6_IRQn, 0, 0);
96  HAL_NVIC_EnableIRQ(USART6_IRQn);
97 }
98 
99 #define MAXBUFSIZE 256
100 
101 struct st_uart_data {
102  struct st_fifo rfifo;
103  unsigned char rbuf[MAXBUFSIZE];
104 
105  unsigned char tbuf[2];
106 
107  struct st_event rx_evq;
108  struct st_event tx_evq;
109 
110  UART_HandleTypeDef huart;
111 };
112 
113 const struct st_device uart1_device;
114 const struct st_device uart6_device;
115 
116 static struct st_uart_data uart_data[3];
117 
118 static void init_uart(struct st_uart_data *uart_dt, USART_TypeDef *uart, int speed)
119 {
120  UART_HandleTypeDef *huart = &(uart_dt->huart);
121 
122  huart->Instance = uart;
123  huart->Init.BaudRate = speed;
124  huart->Init.WordLength = UART_WORDLENGTH_8B;
125  huart->Init.StopBits = UART_STOPBITS_1;
126  huart->Init.Parity = UART_PARITY_NONE;
127  huart->Init.Mode = UART_MODE_TX_RX;
128  huart->Init.HwFlowCtl = UART_HWCONTROL_NONE;
129  huart->Init.OverSampling = UART_OVERSAMPLING_16;
130  huart->Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
131  huart->AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
132  if(HAL_UART_Init(huart) != HAL_OK) {
133  SYSERR_PRINT("HAL UART Init error.\n");
134  }
135 
136  __HAL_UART_ENABLE_IT(huart, UART_IT_RXNE);
137 }
138 
139 void inthdr_uart(unsigned int intnum, void *sp)
140 {
141  unsigned char rd;
142  struct st_uart_data *uart_dt;
143  UART_HandleTypeDef *huart;
144  USART_TypeDef *uart;
145 
146  //tkprintf("UART int(%ld)\n", intnum);
147  if(intnum == IRQ2VECT(USART1_IRQn)) {
148  uart_dt = &uart_data[0];
149  } else if(intnum == IRQ2VECT(USART6_IRQn)) {
150  uart_dt = &uart_data[1];
151  } else {
152  return;
153  }
154  huart = &(uart_dt->huart);
155  uart = huart->Instance;
156 
157  if(uart->ISR & USART_ISR_RXNE) {
158  uart->ICR = USART_ICR_ORECF | USART_ICR_NCF | USART_ICR_FECF | USART_ICR_PECF;
159  rd = uart->RDR;
160  if(write_fifo(&(uart_dt->rfifo), &rd, 1) == 0) { // FIFOへ格納
161  // SYSERR_PRINT("FIFO Over Flow\n");
162  }
163 
164 #if 0 // DEBUG
165  if(uart_dt == &uart_data[1]) {
166  tkprintf("%c", rd);
167  }
168 #endif
169  event_wakeup_ISR(sp, &(uart_dt->rx_evq), 0);
170  }
171 
172  if(uart->ISR & USART_ISR_PE) {
173  uart->ISR &= ~(USART_ISR_PE);
174  // SYSERR_PRINT("USART Parity Error\n");
175  }
176 
177  if(uart->ISR & USART_ISR_FE) {
178  uart->ISR &= ~(USART_ISR_FE);
179  // SYSERR_PRINT("USART Framing Error\n");
180  }
181 
182  if(uart->ISR & USART_ISR_NE) {
183  uart->ISR &= ~(USART_ISR_NE);
184  // SYSERR_PRINT("USART Noise Error\n");
185  }
186 
187  if(uart->ISR & USART_ISR_ORE) {
188  uart->ISR &= ~(USART_ISR_ORE);
189  // SYSERR_PRINT("USART OverRun Error\n");
190  }
191 
192  if(uart->ISR & USART_ISR_TXE) {
193  uart->CR1 &= ~(USART_CR1_TXEIE);
194  event_wakeup_ISR(sp, &(uart_dt->tx_evq), 0);
195  }
196 }
197 
198 /*
199  @brief USARTを初期化する
200  8bit, stop bit 1, パリティ無し, 調歩同期
201 */
202 const static char uart_rx_eventqueue_name[2][10] = {
203  "uart1_rx", "uart6_rx"
204 };
205 
206 const static char uart_tx_eventqueue_name[2][10] = {
207  "uart1_tx", "uart6_tx"
208 };
209 
210 static int uart_init(struct st_device *dev, char *param)
211 {
212  struct st_uart_data *uart_data = (dev->private_data);
213 
214  init_fifo(&(uart_data->rfifo), uart_data->rbuf, MAXBUFSIZE);
215 
216  if(dev == &uart1_device) {
217  eventqueue_register_ISR(&(uart_data->rx_evq),
218  uart_rx_eventqueue_name[0], 0, 0, 0);
219  eventqueue_register_ISR(&(uart_data->tx_evq),
220  uart_tx_eventqueue_name[0],
221  uart_data->tbuf, sizeof(unsigned char), 2);
222  register_interrupt(IRQ2VECT(USART1_IRQn), inthdr_uart);
223 
224  init_rcc_uart1();
225  init_gpio_uart1();
226  init_uart(uart_data, USART1, 115200);
227  } else if(dev == &uart6_device) {
228  eventqueue_register_ISR(&(uart_data->rx_evq),
229  uart_rx_eventqueue_name[1], 0, 0, 0);
230  eventqueue_register_ISR(&(uart_data->tx_evq),
231  uart_tx_eventqueue_name[1],
232  uart_data->tbuf, sizeof(unsigned char), 2);
233  register_interrupt(IRQ2VECT(USART6_IRQn), inthdr_uart);
234 
235  init_rcc_uart6();
236  init_gpio_uart6();
237  init_uart(uart_data, USART6, 115200);
238  } else {
239  return -1;
240  }
241 
242  return 0;
243 }
244 
245 /*
246  @brief UARTからの受信データを取得する
247  @param[out] rd 受信データポインタ
248  @return !=0:データあり 0:データ無し
249 */
250 static int uart_getc(struct st_device *dev, unsigned char *rd)
251 {
252  return read_fifo(&(((struct st_uart_data *)(dev->private_data))->rfifo), rd, 1);
253 }
254 
255 /*
256  @brief UART出力
257  @param[in] td 送信データ
258 */
259 #define UART_TC_TIMEOUT 100000
260 #define UART_TE_TIMEOUT 1000
261 //#define UART_TE_TIMEOUT 0
262 
263 static int uart_putc(struct st_device *dev, unsigned char td)
264 {
265  int timeout = UART_TC_TIMEOUT;
266  USART_TypeDef *uart = ((struct st_uart_data *)(dev->private_data))->huart.Instance;
267 
268  while(!(uart->ISR & USART_ISR_TC)) {
269  timeout --;
270  if(timeout == 0) {
271  SYSERR_PRINT("UART TC timeout\n");
272  break;
273  }
274  }
275  uart->TDR = td;
276 
277 #if 1 // 送信完了割り込み使用
278  uart->CR1 |= USART_CR1_TXEIE; // 送信データエンプティ割り込み許可
279 
280  if(event_wait(&(((struct st_uart_data *)(dev->private_data))->tx_evq), 0, UART_TE_TIMEOUT) == 0) {
281  if(UART_TE_TIMEOUT != 0) {
282  SYSERR_PRINT("UART TXE timeout\n");
283  }
284  }
285 #endif
286 
287  return 1;
288 }
289 
290 static int uart_ioctl(struct st_device *dev, unsigned int com, unsigned int arg, void *param)
291 {
292  struct st_uart_data *uart_data = (dev->private_data);
293 
294  switch(com) {
295  case IOCMD_UART_SPEED:
296  {
297  UART_HandleTypeDef *huart = &(uart_data->huart);
298  init_uart(uart_data, huart->Instance, arg);
299  }
300  break;
301 
302  default:
303  SYSERR_PRINT("Unknown ioctl(%08lX)\n", com);
304  return -1;
305  break;
306  }
307 
308  return 0;
309 }
310 
311 static int uart_select(struct st_device *dev, unsigned int timeout)
312 {
313  if(fifo_size(&(((struct st_uart_data *)(dev->private_data))->rfifo)) != 0) {
314  return timeout;
315  } else {
316  return event_wait(&(((struct st_uart_data *)(dev->private_data))->rx_evq),
317  0, timeout);
318  }
319 }
320 
321 
322 /*
323  uart1_low
324 */
325 
326 static UART_HandleTypeDef huart_low;
327 
328 /*
329  @brief UARTを初期化する
330 */
331 static int uart_init_low(struct st_device *dev, char *param)
332 {
333  init_rcc_uart1();
334  init_gpio_uart1();
335 
336  huart_low.Instance = USART1;
337  huart_low.Init.BaudRate = 115200;
338  huart_low.Init.WordLength = UART_WORDLENGTH_8B;
339  huart_low.Init.StopBits = UART_STOPBITS_1;
340  huart_low.Init.Parity = UART_PARITY_NONE;
341  huart_low.Init.Mode = UART_MODE_TX_RX;
342  huart_low.Init.HwFlowCtl = UART_HWCONTROL_NONE;
343  huart_low.Init.OverSampling = UART_OVERSAMPLING_16;
344  HAL_UART_Init(&huart_low);
345 
346  return 0;
347 }
348 
349 /*
350  @brief UARTからの受信データを取得する(割り込み無し)
351  @param[out] rd 受信データポインタ
352  @return !=0:データあり 0:データ無し
353 */
354 static int uart_getc_low(struct st_device *dev, unsigned char *rd)
355 {
356  USART_TypeDef *uart = huart_low.Instance;
357 
358  if(uart->ISR & USART_ISR_RXNE) {
359  uart->ISR &= ~(USART_ISR_RXNE);
360  *rd = uart->RDR;
361  return 1;
362  } else {
363  return 0;
364  }
365 }
366 
367 /*
368  @brief UART出力(割り込み無し)
369  @param[in] td 送信データ
370 */
371 static int uart_putc_low(struct st_device *dev, unsigned char td)
372 {
373  int timeout = UART_TC_TIMEOUT;
374  USART_TypeDef *uart = huart_low.Instance;
375 
376  while(!(uart->ISR & USART_ISR_TC)) {
377  timeout --;
378  if(timeout == 0) {
379  break;
380  }
381  }
382  uart->TDR = td;
383 
384 #if 1 // 送信完了待ち
385  while(!(uart->ISR & USART_ISR_TC)) {
386  timeout --;
387  if(timeout == 0) {
388  break;
389  }
390  }
391 #endif
392  return 1;
393 }
394 
395 const struct st_device uart1_device = {
397  .explan = "STM32F7 UART1",
398  .private_data = (void *)&uart_data[0],
399  .register_dev = uart_init,
400  .getc = uart_getc,
401  .putc = uart_putc,
402  .ioctl = uart_ioctl,
403  .select = uart_select
404 };
405 
406 const struct st_device uart6_device = {
407  .name = DEF_DEV_NAME_UART "1",
408  .explan = "STM32F7 UART6",
409  .private_data = (void *)&uart_data[1],
410  .register_dev = uart_init,
411  .getc = uart_getc,
412  .putc = uart_putc,
413  .ioctl = uart_ioctl,
414  .select = uart_select
415 };
416 
417 const struct st_device uart1_low_device = {
419  .explan = "Debug/Error Console",
420  .private_data = (void *)&uart_data[2],
421  .register_dev = uart_init_low,
422  .getc = uart_getc_low,
423  .putc = uart_putc_low
424 };
#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