Appiko
SDK_EVAL_Com_UART_DMA_TX.c
1 
24 /* Includes ------------------------------------------------------------------*/
25 #include "SDK_EVAL_Com.h"
26 #include "SDK_EVAL_Config.h"
27 #include <yfuns.h>
28 #include <stdint.h>
29 #define stdout _LLIO_STDOUT
30 
31 
49 #define RECEIVE_QUEUE_SIZE NUCLEO_UARTx_RX_QUEUE_SIZE
50 #define TRANSMIT_QUEUE_SIZE NUCLEO_UARTx_TX_QUEUE_SIZE
51 
52 #define UART_ENTER_CRITICAL() __disable_irq()
53 #define UART_EXIT_CRITICAL() __enable_irq()
54 
55 uint8_t rxQ[RECEIVE_QUEUE_SIZE];
56 uint16_t rxHead = 0;
57 uint16_t rxTail = 0;
58 volatile uint16_t rxUsed = 0;
59 UART_HandleTypeDef huart;
60 DMA_HandleTypeDef dma_handle_rx,dma_handle_tx;
61 
62 uint8_t txQ[TRANSMIT_QUEUE_SIZE];
63 uint16_t txHead = 0;
64 uint16_t txTail = 0;
65 volatile uint16_t txUsed = 0,txLastRequest=0;
66 uint8_t dmaTransmitting = 0;
67 
68 
69 
81 static void prepareDmaTx(void);
82 
88 void SdkEvalComInit(void)
89 {
90  GPIO_InitTypeDef GPIO_InitStructure;
91 
92  NUCLEO_UARTx_GPIO_CLK_ENABLE();
93  NUCLEO_UARTx_CLK_ENABLE();
94  NUCLEO_UARTx_DMA_CLK_ENABLE();
95 
96 
97 #ifdef USE_STM32F4XX_NUCLEO
98  dma_handle_rx.Instance = NUCLEO_UARTx_RX_DMA_STREAM;
99  dma_handle_rx.Init.Channel = NUCLEO_UARTx_RX_DMA_CHANNEL;
100 #else
101  dma_handle_rx.Instance = NUCLEO_UARTx_RX_DMA_CHANNEL;
102 #endif
103 
104 
105 #ifdef USE_STM32L0XX_NUCLEO
106  dma_handle_rx.Init.Request=NUCLEO_UARTx_RX_DMA_REQUEST;
107 #endif
108  dma_handle_rx.Init.Direction=DMA_PERIPH_TO_MEMORY;
109  dma_handle_rx.Init.PeriphInc=DMA_PINC_DISABLE;
110  dma_handle_rx.Init.MemInc=DMA_MINC_ENABLE;
111  dma_handle_rx.Init.PeriphDataAlignment=DMA_PDATAALIGN_BYTE;
112  dma_handle_rx.Init.MemDataAlignment=DMA_MDATAALIGN_BYTE;
113  dma_handle_rx.Init.Mode=DMA_CIRCULAR;
114  dma_handle_rx.Init.Priority=DMA_PRIORITY_LOW;
115  HAL_DMA_Init(&dma_handle_rx);
116 
117  GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
118  GPIO_InitStructure.Pull = GPIO_PULLUP;
119  GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
120 
121  GPIO_InitStructure.Pin = NUCLEO_UARTx_RX_PIN;
122  GPIO_InitStructure.Alternate = NUCLEO_UARTx_AF;
123  HAL_GPIO_Init(NUCLEO_UARTx_PORT, &GPIO_InitStructure);
124 
125  GPIO_InitStructure.Pin = NUCLEO_UARTx_TX_PIN;
126  GPIO_InitStructure.Alternate = NUCLEO_UARTx_AF;
127  HAL_GPIO_Init(NUCLEO_UARTx_PORT, &GPIO_InitStructure);
128 
129 
130  huart.Init.BaudRate=SDK_EVAL_UART_BAUDRATE;
131  huart.Init.WordLength=UART_WORDLENGTH_8B;
132  huart.Init.StopBits=UART_STOPBITS_1;
133  huart.Init.Parity=UART_PARITY_NONE;
134  huart.Init.HwFlowCtl=UART_HWCONTROL_NONE;
135  huart.Init.Mode=UART_MODE_TX_RX;
136  __HAL_LINKDMA(&huart, hdmarx, dma_handle_rx);
137 
138 #ifdef USE_STM32F4XX_NUCLEO
139  dma_handle_tx.Instance = NUCLEO_UARTx_TX_DMA_STREAM;
140  dma_handle_tx.Init.Channel = NUCLEO_UARTx_TX_DMA_CHANNEL;
141 #else
142  dma_handle_tx.Instance = NUCLEO_UARTx_TX_DMA_CHANNEL;
143 #endif
144 
145 
146 #ifdef USE_STM32L0XX_NUCLEO
147  dma_handle_tx.Init.Request=NUCLEO_UARTx_TX_DMA_REQUEST;
148 #endif
149  dma_handle_tx.Init.Direction=DMA_MEMORY_TO_PERIPH;
150  dma_handle_tx.Init.PeriphInc=DMA_PINC_DISABLE;
151  dma_handle_tx.Init.MemInc=DMA_MINC_ENABLE;
152  dma_handle_tx.Init.PeriphDataAlignment=DMA_PDATAALIGN_BYTE;
153  dma_handle_tx.Init.MemDataAlignment=DMA_MDATAALIGN_BYTE;
154  dma_handle_tx.Init.Mode=DMA_NORMAL;
155  dma_handle_tx.Init.Priority=DMA_PRIORITY_HIGH;
156  HAL_DMA_Init(&dma_handle_tx);
157 
158  __HAL_LINKDMA(&huart, hdmatx, dma_handle_tx);
159 
160  huart.Instance=NUCLEO_UARTx;
161 
162  HAL_UART_Init(&huart);
163 
164  HAL_NVIC_EnableIRQ(NUCLEO_UARTx_TX_DMA_CHANNEL_IRQn);
165  HAL_NVIC_SetPriority(NUCLEO_UARTx_TX_DMA_CHANNEL_IRQn, NUCLEO_UARTx_PRIORITY, 0);
166 
167 
168  HAL_UART_Receive_DMA(&huart,rxQ,RECEIVE_QUEUE_SIZE);
169 
170  HAL_NVIC_SetPriority(NUCLEO_UARTx_IRQn, NUCLEO_UARTx_PRIORITY-1, 0);
171  HAL_NVIC_EnableIRQ(NUCLEO_UARTx_IRQn);
172 
173 }
174 
175 
176 void SdkEvalComTriggerTx(void)
177 {
178  prepareDmaTx();
179 }
180 
181 void updatetxQ(void)
182 {
183  UART_ENTER_CRITICAL();
184 #ifdef USE_STM32F4XX_NUCLEO
185  uint16_t dmaResidual=huart.hdmatx->Instance->NDTR;
186 #else
187  uint16_t dmaResidual=huart.hdmatx->Instance->CNDTR;
188 #endif
189  txTail=(txTail+(txLastRequest-dmaResidual))%TRANSMIT_QUEUE_SIZE;
190  txUsed-=(txLastRequest-dmaResidual);
191  txLastRequest=dmaResidual;
192  UART_EXIT_CRITICAL();
193 }
194 
195 
196 void enqueueTxChars(const unsigned char * buffer, uint16_t size)
197 {
198 
199  while ( size > 0 ) {
200 
201  while(txUsed>TRANSMIT_QUEUE_SIZE-size)
202  {
203  updatetxQ();
204  }
205 
206  UART_ENTER_CRITICAL();
207  txQ[txHead] = *buffer++;
208  txUsed++;
209  txHead = (txHead+1) % TRANSMIT_QUEUE_SIZE;
210  size--;
211  UART_EXIT_CRITICAL();
212  }
213 
214 
215 }
216 
217 void SdkEvalComBaudrate(uint32_t baudrate)
218 {
219  huart.Init.BaudRate=baudrate;
220  __HAL_UART_DISABLE(&huart);
221  HAL_UART_Init(&huart);
222  __HAL_UART_ENABLE(&huart);
223 }
224 
225 
226 
227 void prepareDmaTx(void)
228 {
229  if(!dmaTransmitting && txUsed!=0)
230  {
231  UART_ENTER_CRITICAL();
232  dmaTransmitting=1;
233 
234  if(txTail+txUsed<TRANSMIT_QUEUE_SIZE)
235  {
236  txLastRequest=txUsed;
237  }
238  else
239  {
240  txLastRequest=(TRANSMIT_QUEUE_SIZE-txTail);
241  }
242 
243  if(HAL_UART_Transmit_DMA(&huart,&txQ[txTail],txLastRequest)==HAL_OK)
244  {
245 
246  }
247 
248  UART_EXIT_CRITICAL();
249  }
250 
251 }
252 
253 
254 // IAR Standard library hook for serial output
255 size_t __write(int handle, const unsigned char * buffer, size_t size)
256 {
257 
258  /* This template only writes to "standard out" and "standard err",
259  * for all other file handles it returns failure. */
260  if (handle != _LLIO_STDOUT && handle != _LLIO_STDERR) {
261  return _LLIO_ERROR;
262  }
263  if (buffer == 0) {
264  uint8_t c=0;
265  enqueueTxChars(&c,1);
266  return 0;
267  }
268 
269 
270  updatetxQ();
271  enqueueTxChars(buffer,size);
272 
273 
274  return size;
275 }
276 
277 size_t fflush(int handle)
278 {
279  return __write(_LLIO_STDOUT, NULL, 0);
280 }
281 
282 
283 void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
284 {
285  txTail=(txTail+txLastRequest)%TRANSMIT_QUEUE_SIZE;
286  txUsed-=txLastRequest;
287  txLastRequest=0;
288  dmaTransmitting=0;
289 
290 
291  prepareDmaTx();
292 }
293 
294 void USART2_IRQHandler(void)
295 {
296  HAL_UART_IRQHandler(&huart);
297 }
298 
299 void NUCLEO_UARTx_TX_DMA_CHANNEL_IRQHandler(void)
300 {
301  HAL_DMA_IRQHandler(huart.hdmatx);
302 
303 #if defined(USE_STM32L0XX_NUCLEO) || defined(USE_STM32F0XX_NUCLEO)
304  HAL_DMA_IRQHandler(huart.hdmarx);
305 #endif
306 }
307 
308 
309 // IAR Standard library hook for serial input
310 size_t __read(int handle, unsigned char * buffer, size_t size)
311 {
312  int nChars = 0;
313 
314  /* This template only reads from "standard in", for all other file
315  * handles it returns failure. */
316  if (handle != _LLIO_STDIN)
317  {
318  return _LLIO_ERROR;
319  }
320 
321  if(huart.hdmarx)
322  {
323 #ifdef USE_STM32F4XX_NUCLEO
324  rxHead=(RECEIVE_QUEUE_SIZE-huart.hdmarx->Instance->NDTR)%RECEIVE_QUEUE_SIZE;
325 #else
326  rxHead=(RECEIVE_QUEUE_SIZE-huart.hdmarx->Instance->CNDTR)%RECEIVE_QUEUE_SIZE;
327 #endif
328 
329  if(rxHead>=rxTail)
330  rxUsed=rxHead-rxTail;
331  else
332  rxUsed=RECEIVE_QUEUE_SIZE-rxTail+rxHead;
333 
334  }
335 
336  for(nChars = 0; (rxUsed>0) && (nChars < size); nChars++) {
337  *buffer++ = rxQ[rxTail];
338  rxTail = (rxTail+1) % RECEIVE_QUEUE_SIZE;
339  rxUsed--;
340  }
341 
342  return nChars;
343 }
344 
345 void enqueueRxChars(unsigned char * buffer, uint16_t size)
346 {
347  while (( size > 0 ) && (rxUsed < (RECEIVE_QUEUE_SIZE-1))) {
348  rxQ[rxHead] = *buffer++;
349  rxHead = (rxHead+1) % RECEIVE_QUEUE_SIZE;
350  rxUsed++;
351  size--;
352  }
353 }
354 
355 uint8_t __io_getcharNonBlocking(uint8_t *data)
356 {
357  if (__read(_LLIO_STDIN,data,1))
358  return 1;
359  else
360  return 0;
361 }
362 
363 void __io_putchar( char c )
364 {
365  __write(_LLIO_STDOUT, (unsigned char *)&c, 1);
366 }
367 
368 int __io_getchar()
369 {
370  unsigned char c;
371  __read(_LLIO_STDIN, &c, 1);
372  return (int)(c);
373 }
374 
375 void __io_flush( void )
376 {
377  __write(_LLIO_STDOUT, NULL, 0);
378 }
379 
380 uint8_t append_to_buf(void)
381 {
382  uint8_t c;
383 
384  HAL_UART_Receive(&huart, &c, 1, 100);
385  rxQ[rxHead] = c;
386  rxHead=(rxHead+1)%RECEIVE_QUEUE_SIZE;
387  rxUsed++;
388 
389  if(c=='\n' || c=='\r')
390  return 1;
391 
392  return 0;
393 
394 }
410 /******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/
This file contains SDK EVAL configuration and useful defines.
void SdkEvalComInit(void)
Configures UART port in DMA mode for both RX and TX.
This file contains definitions for Software Development Kit eval board COM ports.