GadgetSeed  0.9.6
usart.c
[詳解]
1 /** @file
2  @brief STM32L152 シリアル(USARTドライバ)
3 
4  @date 2018.08.12
5  @author Takashi SHUDO
6 
7  USART2_TX PA2
8  USART2_RX PA3
9 
10  USART4_TX PC10
11  USART4_RX PC11
12 */
13 
14 #include "device.h"
15 #include "interrupt.h"
16 #include "fifo.h"
17 #include "tkprintf.h"
18 #include "device/uart_ioctl.h"
19 #include "task/event.h"
20 #include "task/syscall.h"
21 
22 #include "stm32l1xx_hal.h"
23 
24 static void init_rcc_usart2(void)
25 {
26  __GPIOA_CLK_ENABLE();
27 }
28 
29 static void init_rcc_usart4(void)
30 {
31  __GPIOC_CLK_ENABLE();
32 }
33 
34 static void init_gpio_usart2(void)
35 {
36  GPIO_InitTypeDef GPIO_InitStruct;
37 
38  __USART2_CLK_ENABLE();
39 
40  GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3;
41  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
42  GPIO_InitStruct.Pull = GPIO_PULLUP;
43  GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
44  GPIO_InitStruct.Alternate = GPIO_AF7_USART2;
45  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
46 }
47 
48 static void init_gpio_usart4(void)
49 {
50  GPIO_InitTypeDef GPIO_InitStruct;
51 
52  __USART4_CLK_ENABLE();
53 
54  GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_12;
55  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
56  GPIO_InitStruct.Pull = GPIO_PULLUP;
57  GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
58  GPIO_InitStruct.Alternate = GPIO_AF8_UART4;
59  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
60 }
61 
62 #define MAXBUFSIZE 256
63 
64 typedef struct st_usart_data {
65  struct st_fifo rfifo;
66  unsigned char rbuf[MAXBUFSIZE];
67 
68  unsigned char tbuf[2];
69 
70  struct st_event rx_evq;
71  struct st_event tx_evq;
72 
73  UART_HandleTypeDef huart;
74 } st_usart_data;
75 
76 const struct st_device usart2_device;
77 const struct st_device usart4_device;
78 
79 static st_usart_data usart_data[3];
80 
81 static void init_usart(st_usart_data *usart_dt, USART_TypeDef *usart, int irq)
82 {
83  UART_HandleTypeDef *huart = &(usart_dt->huart);
84 
85  huart->Instance = usart;
86  huart->Init.BaudRate = 115200;
87  huart->Init.WordLength = UART_WORDLENGTH_8B;
88  huart->Init.StopBits = UART_STOPBITS_1;
89  huart->Init.Parity = UART_PARITY_NONE;
90  huart->Init.Mode = UART_MODE_TX_RX;
91  huart->Init.HwFlowCtl = UART_HWCONTROL_NONE;
92  huart->Init.OverSampling = UART_OVERSAMPLING_16;
93  HAL_UART_Init(huart);
94 
95  HAL_NVIC_EnableIRQ(irq);
96  __HAL_UART_ENABLE_IT(huart, UART_IT_RXNE);
97 }
98 
99 void inthdr_usart(unsigned int intnum, void *sp)
100 {
101  unsigned char rd;
102  st_usart_data *usart_dt;
103  UART_HandleTypeDef *huart;
104  USART_TypeDef *usart;
105 
106  //tkprintf("USART int(%ld)\n", intnum);
107  if(intnum == IRQ2VECT(USART2_IRQn)) {
108  usart_dt = &usart_data[0];
109  } else if(intnum == IRQ2VECT(UART4_IRQn)) {
110  usart_dt = &usart_data[1];
111  } else {
112  return;
113  }
114  huart = &(usart_dt->huart);
115  usart = huart->Instance;
116 
117  if(usart->SR & USART_SR_RXNE) {
118  usart->SR &= ~(USART_SR_RXNE);
119  rd = usart->DR;
120  if(write_fifo(&(usart_dt->rfifo), &rd, 1) != 0) { // FIFOへ格納
121  // SYSERR_PRINT("FIFO Over Flow\n");
122  }
123 
124 #if 0 // DEBUG
125  if(usart_dt == &usart_data[1]) {
126  tkprintf("%c", rd);
127  }
128 #endif
129  event_wakeup_ISR(sp, &(usart_dt->rx_evq), 0);
130  }
131 
132  if(usart->SR & USART_SR_PE) {
133  usart->SR &= ~(USART_SR_PE);
134  // SYSERR_PRINT("USART Parity Error\n");
135  }
136 
137  if(usart->SR & USART_SR_FE) {
138  usart->SR &= ~(USART_SR_FE);
139  // SYSERR_PRINT("USART Framing Error\n");
140  }
141 
142  if(usart->SR & USART_SR_NE) {
143  usart->SR &= ~(USART_SR_NE);
144  // SYSERR_PRINT("USART Noise Error\n");
145  }
146 
147  if(usart->SR & USART_SR_ORE) {
148  usart->SR &= ~(USART_SR_ORE);
149  // SYSERR_PRINT("USART OverRun Error\n");
150  }
151 
152  if(usart->SR & USART_SR_TXE) {
153  usart->CR1 &= ~(USART_CR1_TXEIE);
154  event_wakeup_ISR(sp, &(usart_dt->tx_evq), 0);
155  }
156 }
157 
158 const static char usart_rx_eventqueue_name[2][10] = {
159  "usart2_rx", "usart4_rx"
160 };
161 
162 const static char usart_tx_eventqueue_name[2][10] = {
163  "usart2_tx", "usart4_tx"
164 };
165 
166 /*
167  USARTを初期化する
168 
169  8bit, stop bit 1, パリティ無し, 調歩同期
170 */
171 static int usart_init(struct st_device *dev, char *param)
172 {
173  st_usart_data *usart_data = (dev->private_data);
174 
175  init_fifo(&(usart_data->rfifo), usart_data->rbuf, MAXBUFSIZE);
176 
177  if(dev == &usart2_device) {
178  eventqueue_register_ISR(&(usart_data->rx_evq),
179  usart_rx_eventqueue_name[0], 0, 0, 0);
180  eventqueue_register_ISR(&(usart_data->tx_evq),
181  usart_tx_eventqueue_name[0],
182  usart_data->tbuf, sizeof(unsigned char), 2);
183  NVIC_SetPriority(USART2_IRQn, 0);
184  register_interrupt(IRQ2VECT(USART2_IRQn), inthdr_usart);
185 
186  init_rcc_usart2();
187  init_gpio_usart2();
188  init_usart(usart_data, USART2, USART2_IRQn);
189  } else if(dev == &usart4_device) {
190  eventqueue_register_ISR(&(usart_data->rx_evq),
191  usart_rx_eventqueue_name[1], 0, 0, 0);
192  eventqueue_register_ISR(&(usart_data->tx_evq),
193  usart_tx_eventqueue_name[1],
194  usart_data->tbuf, sizeof(unsigned char), 2);
195  NVIC_SetPriority(UART4_IRQn, 0);
196  register_interrupt(IRQ2VECT(UART4_IRQn), inthdr_usart);
197 
198  init_rcc_usart4();
199  init_gpio_usart4();
200  init_usart(usart_data, UART4, UART4_IRQn);
201  } else {
202  return -1;
203  }
204 
205  return 0;
206 }
207 
208 /*
209  USARTからの受信データを取得する
210 */
211 static int usart_getc(struct st_device *dev, unsigned char *rd)
212 {
213  return read_fifo(&(((st_usart_data *)(dev->private_data))->rfifo), rd, 1);
214 }
215 
216 #define USART_TC_TIMEOUT 100000
217 #define USART_TE_TIMEOUT 1000
218 //#define USART_TE_TIMEOUT 0
219 
220 /*
221  USART出力
222 */
223 static int usart_putc(struct st_device *dev, unsigned char td)
224 {
225  int timeout = USART_TC_TIMEOUT;
226  USART_TypeDef *usart = ((st_usart_data *)(dev->private_data))->huart.Instance;
227 
228  while(!(usart->SR & USART_SR_TC)) {
229  timeout --;
230  if(timeout == 0) {
231  SYSERR_PRINT("USART TC timeout\n");
232  break;
233  }
234  }
235  usart->DR = td;
236 
237 #if 1 // 送信完了割り込み使用
238  usart->CR1 |= USART_CR1_TXEIE; // 送信データエンプティ割り込み許可
239 
240  if(event_wait(&(((st_usart_data *)(dev->private_data))->tx_evq), 0, USART_TE_TIMEOUT) == 0) {
241  if(USART_TE_TIMEOUT != 0) {
242  SYSERR_PRINT("USART TXE timeout\n");
243  }
244  }
245 #endif
246 
247  return 1;
248 }
249 
250 static int usart_ioctl(struct st_device *dev, unsigned int com, unsigned int arg, void *param)
251 {
252  UART_HandleTypeDef *huart = &(((st_usart_data *)(dev->private_data))->huart);
253 
254  switch(com) {
255  case IOCMD_UART_SPEED:
256  HAL_UART_DeInit(huart);
257  huart->Init.BaudRate = arg;
258  HAL_UART_Init(huart);
259  break;
260 
261  default:
262  SYSERR_PRINT("Unknown ioctl(%08lX)\n", com);
263  return -1;
264  break;
265  }
266 
267  return 0;
268 }
269 
270 static int usart_select(struct st_device *dev, unsigned int timeout)
271 {
272  if(fifo_size(&(((st_usart_data *)(dev->private_data))->rfifo)) != 0) {
273  return timeout;
274  } else {
275  return event_wait(&(((st_usart_data *)(dev->private_data))->rx_evq),
276  0, timeout);
277  }
278 }
279 
280 
281 /*
282  usart2_low
283 */
284 
285 static UART_HandleTypeDef huart_low;
286 
287 /*
288  USARTを初期化する
289 */
290 static int usart_init_low(struct st_device *dev, char *param)
291 {
292  init_rcc_usart2();
293  init_gpio_usart2();
294 
295  huart_low.Instance = USART2;
296  huart_low.Init.BaudRate = 115200;
297  huart_low.Init.WordLength = UART_WORDLENGTH_8B;
298  huart_low.Init.StopBits = UART_STOPBITS_1;
299  huart_low.Init.Parity = UART_PARITY_NONE;
300  huart_low.Init.Mode = UART_MODE_TX_RX;
301  huart_low.Init.HwFlowCtl = UART_HWCONTROL_NONE;
302  huart_low.Init.OverSampling = UART_OVERSAMPLING_16;
303  HAL_UART_Init(&huart_low);
304 
305  return 0;
306 }
307 
308 /*
309  USARTからの受信データを取得する(割り込み無し)
310 */
311 static int usart_getc_low(struct st_device *dev, unsigned char *rd)
312 {
313  USART_TypeDef *usart = huart_low.Instance;
314 
315  if(usart->SR & USART_SR_RXNE) {
316  usart->SR &= ~(USART_SR_RXNE);
317  *rd = usart->DR;
318  return 1;
319  } else {
320  return 0;
321  }
322 }
323 
324 /*
325  USART出力(割り込み無し)
326 */
327 static int usart_putc_low(struct st_device *dev, unsigned char td)
328 {
329  int timeout = USART_TC_TIMEOUT;
330  USART_TypeDef *usart = huart_low.Instance;
331 
332  while(!(usart->SR & USART_SR_TC)) {
333  timeout --;
334  if(timeout == 0) {
335  break;
336  }
337  }
338  usart->DR = td;
339 
340  return 1;
341 }
342 
343 const struct st_device usart2_device = {
345  .explan = "STM32L1 USART2",
346  .private_data = (void *)&usart_data[0],
347  .register_dev = usart_init,
348  .getc = usart_getc,
349  .putc = usart_putc,
350  .ioctl = usart_ioctl,
351  .select = usart_select
352 };
353 
354 const struct st_device usart4_device = {
355  .name = DEF_DEV_NAME_UART "1",
356  .explan = "STM32L1 USART4",
357  .private_data = (void *)&usart_data[1],
358  .register_dev = usart_init,
359  .getc = usart_getc,
360  .putc = usart_putc,
361  .ioctl = usart_ioctl,
362  .select = usart_select
363 };
364 
365 const struct st_device usart2_low_device = {
367  .explan = "Debug/Error Console",
368  .private_data = (void *)&usart_data[2],
369  .register_dev = usart_init_low,
370  .getc = usart_getc_low,
371  .putc = usart_putc_low
372 };
#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