d_usartDMA.c
Go to the documentation of this file.
1 /*
2 MIT LICENSE
3 
4 Copyright 2014-2019 Inertial Sense, Inc. - http://inertialsense.com
5 
6 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions :
7 
8 The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
9 
10 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT, IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
11 */
12 
13 
14 #include <asf.h>
15 #include <string.h>
16 #include <stdio.h>
17 
18 #include "d_usartDMA.h"
19 
20 #ifdef CONF_BOARD_SPI_UINS
21  #include "spiTouINS.h"
22 #endif
23 
24 #include "d_dma.h"
25 #include "usart.h"
26 #include "../../src/ISComm.h"
27 #include "board_opt.h"
28 #include "globals.h"
29 
30 
31 //Structures for driver
32 #define DMA_LLD_COUNT 32 //Must be 2^x in size
33 #define DMA_LLD_MASK (DMA_LLD_COUNT - 1)
34 
35 typedef struct
36 {
37  volatile XdmacChid *dmaChId; // Pointer to XDMA channel id
38  volatile uint8_t dmaChNumber; // DMA channel number
39  volatile uint32_t size; // DMA total buffer size
40 
41  // DMA buffer pointers:
42  volatile uint8_t *buf; // start
43  volatile uint8_t *end; // end
44  volatile uint8_t *ptr; // current location
45 
46  //Pointers for the lld_view0 array
47  volatile uint32_t lld_fptr;
48  volatile uint32_t lld_bptr;
49 
50  // DMA linked list descriptor used for reload
51  COMPILER_WORD_ALIGNED volatile lld_view0 lld[DMA_LLD_COUNT];
52 
53  // Items for SPI mode
54  COMPILER_WORD_ALIGNED volatile lld_view0 lld_spi_noData[DMA_LLD_COUNT];
55 
57 
58 typedef struct
59 {
60  volatile XdmacChid *dmaChId; // Pointer to XDMA channel id
61  volatile uint8_t dmaChNumber; // DMA channel number
62  volatile uint32_t size; // DMA total buffer size
63  volatile uint32_t lastUsedRx; // Track last used rx
64  volatile uint32_t timestampRx; // Timestamp of last data read
65 
66  // DMA buffer pointers:
67  volatile uint8_t *buf; // start
68  volatile uint8_t *end; // end
69  volatile uint8_t *ptr; // current location
70 
71  // DMA linked list descriptor used for reload
72  COMPILER_WORD_ALIGNED volatile lld_view0 lld;
74 
75 typedef struct
76 {
77  uint32_t ul_id;
78  uint32_t usartTxTHR;
79  uint32_t usartRxRHR;
80  uint32_t xdmacUsartTxPerId; // XDMAC channel "HW Interface Number (XDMAC_CC.PERID)". Refer to datasheet.
82  uint8_t isUsartNotUart;
83  uint8_t isSpiUsart;
84 } usart_info_t;
85 
86 typedef struct
87 {
88  volatile void *usart;
93 } usartDMA_t;
94 
95 //Helper macros for port settings
96 #define CONCAT(A,B) A ## B
97 #define ARGN(N, LIST) CONCAT(ARG_, N) LIST
98 #define ARG_0(A0, ...) A0
99 #define ARG_1(A0, A1, ...) A1
100 #define ARG_2(A0, A1, A2, ...) A2
101 #define ARG_3(A0, A1, A2, A3, ...) A3
102 #define ARG_4(A0, A1, A2, A3, A4, ...) A4
103 
104 //Buffers for serial ports
105 #if MAX_NUMBER_SERIAL_PORTS >= 1
106  COMPILER_ALIGNED(32) static uint8_t g_serTxDmaBuf_port0[ARGN(2, PORT0_CONFIG)];
107  COMPILER_ALIGNED(32) static uint8_t g_serRxDmaBuf_port0[ARGN(4, PORT0_CONFIG)];
108 #endif
109 
110 #if MAX_NUMBER_SERIAL_PORTS >= 2
111  COMPILER_ALIGNED(32) static uint8_t g_serTxDmaBuf_port1[ARGN(2, PORT1_CONFIG)];
112  COMPILER_ALIGNED(32) static uint8_t g_serRxDmaBuf_port1[ARGN(4, PORT1_CONFIG)];
113 #endif
114 
115 #if MAX_NUMBER_SERIAL_PORTS >= 3
116  COMPILER_ALIGNED(32) static uint8_t g_serTxDmaBuf_port2[ARGN(2, PORT2_CONFIG)];
117  COMPILER_ALIGNED(32) static uint8_t g_serRxDmaBuf_port2[ARGN(4, PORT2_CONFIG)];
118 #endif
119 
120 #if MAX_NUMBER_SERIAL_PORTS >= 4
121  COMPILER_ALIGNED(32) static uint8_t g_serTxDmaBuf_port3[ARGN(2, PORT3_CONFIG)];
122  COMPILER_ALIGNED(32) static uint8_t g_serRxDmaBuf_port3[ARGN(4, PORT3_CONFIG)];
123 #endif
124 
125 #if MAX_NUMBER_SERIAL_PORTS >= 5
126  COMPILER_ALIGNED(32) static uint8_t g_serTxDmaBuf_port4[ARGN(2, PORT4_CONFIG)];
127  COMPILER_ALIGNED(32) static uint8_t g_serRxDmaBuf_port4[ARGN(4, PORT4_CONFIG)];
128 #endif
129 
130 #if MAX_NUMBER_SERIAL_PORTS >= 6
131  COMPILER_ALIGNED(32) static uint8_t g_serTxDmaBuf_port5[ARGN(2, PORT5_CONFIG)];
132  COMPILER_ALIGNED(32) static uint8_t g_serRxDmaBuf_port5[ARGN(4, PORT5_CONFIG)];
133 #endif
134 
135 #if MAX_NUMBER_SERIAL_PORTS >= 7
136  COMPILER_ALIGNED(32) static uint8_t g_serTxDmaBuf_port6[ARGN(2, PORT6_CONFIG)];
137  COMPILER_ALIGNED(32) static uint8_t g_serRxDmaBuf_port6[ARGN(4, PORT6_CONFIG)];
138 #endif
139 
140 #if MAX_NUMBER_SERIAL_PORTS >= 8
141  COMPILER_ALIGNED(32) static uint8_t g_serTxDmaBuf_port7[ARGN(2, PORT7_CONFIG)];
142  COMPILER_ALIGNED(32) static uint8_t g_serRxDmaBuf_port7[ARGN(4, PORT7_CONFIG)];
143 #endif
144 
145 #if MAX_NUMBER_SERIAL_PORTS >= 9
146  #error "Need to add more support"
147 #endif
148 
149 //Variables for general use
150 COMPILER_ALIGNED(32) static uint8_t noData_indicator[1] = {0};
152 static uint32_t *s_overrunStatus=NULLPTR;
154 
155 
156 
157 /********************************* USB CDC ********************************************************************************************************/
158 static bool usb_cdc_open = false;
159 
161 {
162  usb_cdc_open = true;
163  return true;
164 }
165 
167 {
168  usb_cdc_open = false;
169 }
170 
172 {
173 #ifdef USB_PORT_NUM
174  dmaBuffer_tx_t *dma = (dmaBuffer_tx_t*)&g_usartDMA[USB_PORT_NUM].dmaTx;
175 
176  if(dma->ptr != dma->end)
177  {
178  //Get how much data is buffered
179  int data_avail;
180  if(dma->ptr >= dma->end)
181  data_avail = dma->ptr - dma->end;
182  else
183  data_avail = dma->ptr - dma->end + dma->size;
184 
185  //Prevent race conditions with interrupt
187 
188  //Get how much USB can take
189  int usb_avail = udi_cdc_get_free_tx_buffer();
190  if(usb_avail)
191  {
192  int bytesToEnd = dma->buf + dma->size - dma->end;
193  int bytesToSend = Min(data_avail, usb_avail);
194 
195  if(bytesToSend < bytesToEnd)
196  {
197  udi_cdc_write_buf((void*)dma->end, bytesToSend);
198  dma->end += bytesToSend;
199  }
200  else
201  {
202  udi_cdc_write_buf((void*)dma->end, bytesToEnd);
203  dma->end = dma->buf;
204  }
205  }
206 
207  NVIC_EnableIRQ((IRQn_Type) ID_USBHS);
208  }
209 #endif
210 }
211 
212 
213 /********************************* INTERNAL BUFFER FUCTIONS ***************************************************************************************************/
214 static inline const uint8_t* getCurrentTxDmaAddress( dmaBuffer_tx_t *dma )
215 {
216  //Check to see if we are using the no data array
217  if(dma->dmaChId->XDMAC_CSA >= (uint32_t)noData_indicator && dma->dmaChId->XDMAC_CSA <= ((uint32_t)noData_indicator+sizeof(noData_indicator)))
218  {
219  //We are not sending data. Send back pointer location.
220  return (const uint8_t*)dma->ptr;
221  }
222 
223  return (const uint8_t*)_CLAMP(dma->dmaChId->XDMAC_CSA, (uint32_t)dma->buf, (uint32_t)dma->end);
224 }
225 
226 static inline const uint8_t* getCurrentRxDmaAddress( dmaBuffer_rx_t *dma )
227 {
228  return (const uint8_t*)_CLAMP(dma->dmaChId->XDMAC_CDA, (uint32_t)dma->buf, (uint32_t)dma->end);
229 }
230 
231 static inline dmaBuffer_tx_t * getTxDma( uint32_t serialNum )
232 {
233  // Get the DMA buffer pointer
234  if (serialNum >= MAX_NUMBER_SERIAL_PORTS || !g_usartDMA[serialNum].usart)
235  return 0;
236 
237  return (dmaBuffer_tx_t*)&(g_usartDMA[serialNum].dmaTx);
238 }
239 
240 static inline dmaBuffer_rx_t * getRxDma( uint32_t serialNum )
241 {
242  // Get the DMA buffer pointer
243  if (serialNum >= MAX_NUMBER_SERIAL_PORTS || !g_usartDMA[serialNum].usart)
244  return 0;
245 
246  return (dmaBuffer_rx_t*)&(g_usartDMA[serialNum].dmaRx);
247 }
248 
249 static inline int serTxUsedDma( dmaBuffer_tx_t *dma)
250 {
251  const uint8_t* curDmaAddr = getCurrentTxDmaAddress(dma);
252 
253  // not using int with abs value because we want full 32 bit memory addresses
254  if (dma->ptr < curDmaAddr)
255  {
256  // handle wrap
257  return (int)(dma->size - (curDmaAddr - dma->ptr));
258  }
259  return (int)(dma->ptr - curDmaAddr);
260 }
261 
262 static inline int serRxUsedDma( dmaBuffer_rx_t *dma )
263 {
264  const uint8_t* curDmaAddr = getCurrentRxDmaAddress(dma);
265 
266  // not using int with abs value because we want full 32 bit memory addresses
267  if (curDmaAddr < dma->ptr)
268  {
269  // handle wrap
270  return (int)(dma->size - (dma->ptr - curDmaAddr));
271  }
272  return (int)(curDmaAddr - dma->ptr);
273 }
274 
275 static inline int serTxFreeDma( dmaBuffer_tx_t *dma )
276 {
277  return dma->size - serTxUsedDma(dma);
278 }
279 
280 static inline int serRxFreeDma( dmaBuffer_rx_t *dma )
281 {
282  return dma->size - serRxUsedDma(dma);
283 }
284 
285 /********************************* EXTERNAL FUCTIONS ***************************************************************************************************/
289 int serTxUsed( int serialNum )
290 {
291  // Get the DMA buffer pointer
292  dmaBuffer_tx_t *dma = getTxDma(serialNum);
293  if( !dma ) return 0;
294 
295  return serTxUsedDma(dma);
296 }
297 
301 int serRxUsed( int serialNum )
302 {
303  // Get the DMA buffer pointer
304  dmaBuffer_rx_t *dma = getRxDma(serialNum);
305  if( !dma ) return 0;
306 
307  return serRxUsedDma(dma);
308 }
309 
313 int serTxFree( int serialNum )
314 {
315 #ifdef USB_PORT_NUM
316  if(serialNum == USB_PORT_NUM)
317  {
319  }
320 #endif
321 
322  // Get the DMA buffer pointer
323  dmaBuffer_tx_t *dma = getTxDma(serialNum);
324  if( !dma ) return 0;
325 
326  return serTxFreeDma(dma);
327 }
328 
332 int serRxFree( int serialNum )
333 {
334  // Get the DMA buffer pointer
335  dmaBuffer_rx_t *dma = getRxDma(serialNum);
336  if( !dma ) return 0;
337 
338  return serRxFreeDma(dma);
339 }
340 
344 int serTxClear( int serialNum )
345 {
346  // Get the DMA buffer pointer
347  dmaBuffer_tx_t *dma = getTxDma(serialNum);
348  if( !dma ) return 0;
349 
350  // disable channel
353 
354  // save how much data we are discarding to return from function
355  int used = serTxUsedDma(dma);
356 
357  // Clear all
358  dma->ptr = dma->buf;
359  dma->lld_fptr = 0;
360  dma->lld_bptr = 0;
361 
362  //Check to see if we are in SPI mode
363  usartDMA_t *ser = (usartDMA_t*)&g_usartDMA[serialNum];
364  if (ser->uinfo.isSpiUsart)
365  {
366  xdmac_channel_config_t cfg = {0};
367  cfg.mbr_sa = (uint32_t)noData_indicator;
368  cfg.mbr_da = (uint32_t)ser->uinfo.usartTxTHR;
379  cfg.mbr_ubc = 0;
381 
382  ser->dmaTx.lld_spi_noData[0].mbr_nda = (uint32_t)&(ser->dmaTx.lld_spi_noData[0]);
383 
386  dma->lld_fptr = 1;
387 
388  // Flush cached memory changes out to main memory
390 
391  // Re-enable DMA
393  }
394 
395  return used;
396 }
397 
398 int serRxClear( int serialNum, int size)
399 {
400  // Get the DMA buffer pointer
401  dmaBuffer_rx_t *dma = getRxDma(serialNum);
402  if( !dma ) return 0;
403 
404  int used = serRxUsedDma(dma);
405 
406  // Flush FIFO, content of the FIFO is written to memory
408 
409  // Disable transfer
411 
412  // Reset
413  dma->ptr = dma->buf;
414 
415  // Configure Rx linked list descriptor (only uses one)
416  dma->lld.mbr_ta = (uint32_t)dma->buf;
417  dma->lld.mbr_nda = (uint32_t)&(dma->lld); // point to self
418  dma->lld.mbr_ubc =
422  dma->size;
423 
429 
430  xdmac_channel_set_descriptor_addr(XDMAC, dma->dmaChNumber, (uint32_t)&(dma->lld), 0);
431 
432 // DBGPIO_START(DBG_TX_DCACHE_CLEAN_PIN);
434 // DBGPIO_END(DBG_TX_DCACHE_CLEAN_PIN);
435 
437 
438  return used;
439 }
440 
441 // We assume worst case scenario, USART is writing data...
442 // Add new data to buffer that is not being written from.
443 int serWrite(int serialNum, const unsigned char *buf, int size)
444 {
445  if (size <= 0 || serialNum < 0 || serialNum >= MAX_NUMBER_SERIAL_PORTS)
446  {
447  return 0;
448  }
449 
450 #ifdef USB_PORT_NUM
451  if(serialNum == USB_PORT_NUM)
452  {
453  if (usb_cdc_open)
454  {
455  dmaBuffer_tx_t *dma = (dmaBuffer_tx_t*)&g_usartDMA[USB_PORT_NUM].dmaTx;
456 
457  //NOTE: We are not preventing overflow at this time, it will just happen and data will be lost/corrupted
458  // (It shouldn't happen as USB moves data pretty fast.)
459 
460  //Prevent loading more data than buffer size
461  if ((uint32_t)size > dma->size)
462  {
463  if (s_overrunStatus)
464  { // Buffer overrun
465  *s_overrunStatus |= HDW_STATUS_ERR_COM_TX_LIMITED;
466  }
467  return 0;
468  }
469 
471 
472  //Check for data in buffer, if nothing buffered, USB is ready, and data fits, don't double buffer
473  if(dma->ptr == dma->end && ((uint32_t)size <= udi_cdc_get_free_tx_buffer()))
474  {
475  udi_cdc_write_buf(buf, size);
476  }
477  else //We are sending more data than USB buffer will hold or there is already data in external buffer.
478  {
479  //Store data in the external buffer
480  int bytesToEnd = dma->buf + dma->size - dma->ptr;
481  if (size <= bytesToEnd)
482  {
483  // Don't need to wrap
484  memcpy((void*)dma->ptr, buf, size);
485 
486  // Increment buffer pointer
487  dma->ptr += size;
488  }
489  else // Need to wrap
490  {
491  // Bytes to write at buffer start
492  int bytesWrapped = size - bytesToEnd;
493 
494  //Write out data needed to fill the end of the buffer
495  if (bytesToEnd)
496  {
497  // Not already at buffer end. Fill buffer to end.
498  memcpy((void*)dma->ptr, buf, bytesToEnd);
499  }
500 
501  // Copy data into DMA buffer start & update pointer
502  memcpy((void*)dma->buf, buf + bytesToEnd, bytesWrapped);
503 
504  // Increment buffer pointer
505  dma->ptr = dma->buf + bytesWrapped;
506  }
507 
508  //Send what fits to USB immediately (also makes sure external buffer didn't empty while we were in here)
510  }
511 
513 
514  g_portMonitorHelper[serialNum].txByteCount += size;
515  return size;
516  }
517  return 0;
518  }
519 #endif // #ifdef USB_PORT_NUM
520 
521  // Get the DMA buffer pointer
522  dmaBuffer_tx_t *dma = getTxDma(serialNum);
523  if (!dma || (uint32_t)size > dma->size) return 0;
524 
525  // Bytes free in DMA buffer
526  int dmaFreeBytes = serTxFreeDma(dma);
527 
528  // Limit size
529  if (size > dmaFreeBytes || ((dma->lld_fptr + 1) & DMA_LLD_MASK) == dma->lld_bptr )
530  {
531  // tx overrun
532  serTxClear(serialNum);
533  if (s_overrunStatus)
534  {
535  *s_overrunStatus |= HDW_STATUS_ERR_COM_TX_LIMITED;
536  }
537 #ifndef __INERTIAL_SENSE_EVB_2__
538  g_internal_diagnostic.txOverflowCount[serialNum]++;
539 #endif
540  }
541 
543  // Copy into DMA buffer
544 
545  // Get ser struct to see if we are in SPI mode
546  usartDMA_t *ser = (usartDMA_t*)&g_usartDMA[serialNum];
547 
549 
550  // Bytes before end of DMA buffer
551  int bytesToEnd = dma->end - dma->ptr;
552 
553  // Add data to ring buffer
554  if (size <= bytesToEnd)
555  {
556  // Don't need to wrap
557  // Copy data into DMA buffer
558  MEMCPY_DCACHE_CLEAN(dma->ptr, buf, size);
559 
560  // Setup DMA
561  dma->lld[dma->lld_fptr].mbr_ta = (uint32_t)dma->ptr;
562  if (ser->uinfo.isSpiUsart)
563  {
565  dma->lld[dma->lld_fptr].mbr_nda = (uint32_t)&(ser->dmaTx.lld_spi_noData[dma->lld_fptr]); //Data lld points to noData lld
566  dma->lld_spi_noData[dma->lld_fptr].mbr_nda = (uint32_t)&(ser->dmaTx.lld_spi_noData[dma->lld_fptr]); //noData lld wraps around on itself
567  }
568  else
569  {
570  dma->lld[dma->lld_fptr].mbr_ubc = XDMAC_UBC_UBLEN(size);
571  }
572 
573  // Increment buffer pointer
574  dma->ptr = dma->ptr + size;
575 
576  // Move to next lld
577  dma->lld_fptr = (dma->lld_fptr + 1) & DMA_LLD_MASK;
578  }
579  else // Need to wrap
580  {
581  // Bytes to write at buffer start
582  int bytesWrapped = size - bytesToEnd;
583  uint32_t bufptr = dma->lld_fptr;
584  int count = 1;
585 
586  //Write out data needed to fill the end of the buffer
587  if (bytesToEnd)
588  {
589  // Not already at buffer end. Fill buffer to end.
590  // Copy data into DMA buffer & update transfer size
591  MEMCPY_DCACHE_CLEAN(dma->ptr, buf, bytesToEnd);
592 
593  // Setup DMA for end
594  dma->lld[bufptr].mbr_ta = (uint32_t)dma->ptr;
595  if (ser->uinfo.isSpiUsart)
596  {
598  dma->lld[bufptr].mbr_nda = (uint32_t)&(ser->dmaTx.lld[(bufptr + 1) & DMA_LLD_MASK]); //Data lld points to next data lld
599  }
600  else
601  {
602  dma->lld[bufptr].mbr_ubc = XDMAC_UBC_UBLEN(bytesToEnd);
603  }
604 
605  // Move to next lld
606  bufptr = (bufptr + 1) & DMA_LLD_MASK;
607  count++;
608  }
609 
610  // Copy data into DMA buffer start & update pointer
611  MEMCPY_DCACHE_CLEAN(dma->buf, buf + bytesToEnd, bytesWrapped);
612 
613  // Setup DMA for beginning
614  dma->lld[bufptr].mbr_ta = (uint32_t)dma->buf;
615  if (ser->uinfo.isSpiUsart)
616  {
618  dma->lld[bufptr].mbr_nda = (uint32_t)&(ser->dmaTx.lld_spi_noData[bufptr]); //Data lld points to noData lld
619  dma->lld_spi_noData[bufptr].mbr_nda = (uint32_t)&(ser->dmaTx.lld_spi_noData[bufptr]); //noData lld wraps around on itself
620  }
621  else
622  {
623  dma->lld[bufptr].mbr_ubc = XDMAC_UBC_UBLEN(bytesWrapped);
624  }
625 
626  // Increment buffer pointer
627  dma->ptr = dma->buf + bytesWrapped;
628 
629  // Move to next lld
630  dma->lld_fptr = (dma->lld_fptr + count) & DMA_LLD_MASK;
631  }
632 
634  // Transfer out of DMA buffer
635 
636  // Indicate Transmit
637  SER_INDICATE_TX();
638 
639  if (ser->uinfo.isSpiUsart)
640  {
641 #if CONF_BOARD_USART_SPI_DATAREADY_ENABLE == 1
642  //Block interrupt handler from running while we add data so there isn't a race condition on the data ready pin
644 #endif
645 
646  //Connect up the new lld nodes
647  uint32_t newLld = (dma->lld_bptr + 1) & DMA_LLD_MASK;
648  ser->dmaTx.lld_spi_noData[dma->lld_bptr].mbr_nda = (uint32_t)&(ser->dmaTx.lld[newLld]);
649 
650  //Move back pointer manually in SPI mode
651  dma->lld_bptr = (dma->lld_fptr - 1) & DMA_LLD_MASK;
652 
653  //Write data out to main memory
654  SCB_CLEAN_DCACHE_BY_ADDR_32BYTE_ALIGNED(dma->lld, sizeof(dma->lld));
656 
657 #if CONF_BOARD_USART_SPI_DATAREADY_ENABLE == 1
658  // Enable DMA interrupt
661 
662  //Set data ready pin for SPI mode
663  ioport_set_pin_level(SPI_DATAREADY_GPIO, IOPORT_PIN_LEVEL_HIGH);
664 
665  //Enable interrupt on completion of linked list node so we can watch for the end of the data
667 #endif
668  }
669  else
670  {
671  //Block interrupt handler from running and causing a double configure
673 
674  //Enable DMA if it isn't running
675  if((XDMAC->XDMAC_GS & (XDMAC_GS_ST0 << (dma->dmaChNumber))) == 0)
676  {
677  if(dma->lld_bptr != dma->lld_fptr)
678  {
679  //Setup TX DMA
682 
683  //Move pointer
684  dma->lld_bptr = (dma->lld_bptr + 1) & DMA_LLD_MASK;
685 
686  // Enable DMA interrupt
689 
690  //Enable - cache should have already been cleaned
691  XDMAC->XDMAC_GE = (XDMAC_GE_EN0 << (dma->dmaChNumber));
692  }
693  }
694 
696  }
697 
699 
700  g_portMonitorHelper[serialNum].txByteCount += size;
701  return size;
702 }
703 
704 void XDMAC_Handler(void)
705 {
706 #ifdef CONF_BOARD_SPI_UINS
707  //Forward for spiTouINS
709 #endif
710 
711  static volatile int xdmacSPICount = 0;
712 
713  for(int i=0;i<MAX_NUMBER_SERIAL_PORTS;i++)
714  {
715  //Make sure port is valid
716  if(g_usartDMA[i].usart == 0)
717  continue;
718 
719  volatile dmaBuffer_tx_t *dma = &(g_usartDMA[i].dmaTx);
720 
721  //See if interrupt is active on this channel
722  if ((dma->dmaChId->XDMAC_CIS & XDMAC_CIS_BIS) && (dma->dmaChId->XDMAC_CIM & XDMAC_CIM_BIM))
723  {
724 #if CONF_BOARD_USART_SPI_DATAREADY_ENABLE == 1
725  //See if we are in SPI mode on this USART
726  if (g_usartDMA[i].uinfo.isSpiUsart)
727  {
728  //See if we are at the end of the list
729  if((uint32_t)(dma->lld_spi_noData[dma->lld_bptr].mbr_nda) == dma->dmaChId->XDMAC_CNDA)
730  {
731  //See if we are transmitting the no data indicator
732  if(dma->dmaChId->XDMAC_CSA >= (uint32_t)noData_indicator && dma->dmaChId->XDMAC_CSA <= (uint32_t)(noData_indicator+sizeof(noData_indicator)))
733  {
734  //Delay number of "no data" transmissions (characters) to get the last bytes out of the port before lowering the data ready indicator.
735  if(2 <= xdmacSPICount)
736  {
737  ioport_set_pin_level(SPI_DATAREADY_GPIO, IOPORT_PIN_LEVEL_LOW);
739  }
740  else
741  {
742  xdmacSPICount++;
743  }
744  }
745  else
746  {
747  xdmacSPICount = 0;
748  }
749  }
750  else
751  {
752  xdmacSPICount = 0;
753  }
754  }
755  else //This "else" makes the following "if" an "else if"
756 #endif
757  //Check to see if DMA is finished (as indicated by channel becoming disabled
758  if ((XDMAC->XDMAC_GS & (XDMAC_GS_ST0 << (dma->dmaChNumber))) == 0)
759  {
760  if(dma->lld_bptr != dma->lld_fptr)
761  {
762  //Setup TX DMA
765 
766  //Move pointer
767  dma->lld_bptr = (dma->lld_bptr + 1) & DMA_LLD_MASK;
768 
769  //Enable - We don't need to clean cache as DMA data is already flushed to main memory
770  XDMAC->XDMAC_GE = (XDMAC_GE_EN0 << (dma->dmaChNumber));
771  }
772  else
773  {
774  //Turn off interrupt when done
776  }
777  }
778  }
779  }
780 }
781 
782 int serRead(int serialNum, unsigned char *buf, int size)
783 {
784  if (size <= 0 || serialNum < 0 || serialNum >= MAX_NUMBER_SERIAL_PORTS)
785  {
786  return 0;
787  }
788 
789 #ifdef USB_PORT_NUM
790  if(serialNum == USB_PORT_NUM)
791  {
792  if(usb_cdc_open)
793  {
794  return udi_cdc_read_no_polling(buf, size);
795  }
796  else
797  {
798  return 0;
799  }
800  }
801 #endif
802 
803  // Get the DMA buffer pointer
804  dmaBuffer_rx_t *dma = getRxDma(serialNum);
805  if (!dma) return 0;
806 
807  // Flush FIFO, content of the FIFO is written to memory
809 
810  // Bytes in DMA buffer
811  uint32_t dmaUsed = serRxUsedDma(dma);
812 
813  if (dmaUsed < dma->lastUsedRx)
814  {
815  // rx overrun
816  serRxClear(serialNum, -1);
817  dma->lastUsedRx = 0;
818  if (s_overrunStatus)
819  {
820  *s_overrunStatus |= HDW_STATUS_ERR_COM_RX_OVERRUN;
821  }
822 #ifndef __INERTIAL_SENSE_EVB_2__
823  g_internal_diagnostic.rxOverflowCount[serialNum]++;
824 #endif
825  size = 0;
826  }
827  else
828  {
829  // Limit to bytes available
830  size = Min((uint32_t)size, dmaUsed);
831 
832  if (size > 0)
833  {
834  // Bytes before end of DMA buffer
835  int bytesToEnd = dma->end - dma->ptr;
836 
837  if (size >= bytesToEnd)
838  {
839  // Handle wrapping
840  // Copy data into DMA buffer & update transfer size
841  DCACHE_CLEAN_INVALIDATE_MEMCPY(buf, dma->ptr, bytesToEnd);
842 
843  int bytesWrapped = size - bytesToEnd;
844  if (bytesWrapped)
845  {
846  // Copy data into DMA buffer
847  DCACHE_CLEAN_INVALIDATE_MEMCPY(&buf[bytesToEnd], dma->buf, bytesWrapped);
848  }
849  dma->ptr = dma->buf + bytesWrapped;
850  }
851  else
852  {
853  // Not wrapping
854  // Copy data into DMA buffer
855  DCACHE_CLEAN_INVALIDATE_MEMCPY(buf, dma->ptr, size);
856  dma->ptr += size;
857  }
858 
859  // Indicate Read
860  SER_INDICATE_RX();
861  }
862 
863  dma->lastUsedRx = dmaUsed - size;
864  }
865 
866 #ifndef __INERTIAL_SENSE_EVB_2__
867  if (size > 0)
868  {
869  uint32_t currentTime = time_msec();
870  uint32_t gap = UINT32_TIME_DIFF(currentTime, dma->timestampRx);
871  if (gap > 500)
872  {
873  g_internal_diagnostic.gapCountSerialDriver[serialNum]++;
874  }
875  dma->timestampRx = currentTime;
876  }
877 #endif
878 
879  // Increment port monitor count
880  g_portMonitorHelper[serialNum].rxByteCount += size;
881  return size;
882 }
883 
884 int serFindCharacter( int serialNum, uint8_t ch)
885 {
886 #ifdef USB_PORT_NUM
887 
888  //No support for USB port at this time
889  if(serialNum == USB_PORT_NUM)
890  return 0;
891 
892 #endif
893 
894  // Get the DMA buffer pointer
895  dmaBuffer_rx_t *dma = getRxDma(serialNum);
896  if (!dma) return 0;
897 
898  // Bytes in DMA buffer
899  uint32_t dmaUsed = serRxUsedDma(dma);
900 
901  // Return if no data is available
902  if(dmaUsed == 0) return 0;
903 
904  // Flush FIFO, content of the FIFO is written to memory
906 
907  // Clean & invalidate memory so we can see what is there
909 
910  //Look for character
911  uint32_t chCount = 0;
912  volatile uint8_t *ptr = dma->ptr;
913  while(++chCount <= dmaUsed)
914  {
915  if(*ptr == ch)
916  return (int)chCount;
917 
918  //move pointer
919  ptr++;
920  if(ptr >= dma->end) //Roll over to beginning if we reach the end
921  ptr = dma->buf;
922  }
923 
924  //Not found, return zero
925  return 0;
926 }
927 
928 static int serEnable(int serialNum)
929 {
930  usartDMA_t *ser = (usartDMA_t*)&g_usartDMA[serialNum];
931 
932  // Re-init UART
933  if (ser->uinfo.isUsartNotUart)
934  { // Initialize USART
935  if (ser->uinfo.isSpiUsart)
936  {
937  // Initialize the USART in SPI slave mode.
938  usart_spi_opt_t opt = {
939  .baudrate = 3000000, // ignored when configuring for slave mode
940  .char_length = US_MR_CHRL_8_BIT,
941  .spi_mode = SPI_MODE_3,
942  .channel_mode = US_MR_CHMODE_NORMAL
943  };
944  usart_init_spi_slave((Usart*)ser->usart, &opt);
945  }
946  else
947  {
948  // Initialize the USART in RS232 mode.
950  }
951 
952  // Enable the receiver and transmitter.
953  usart_enable_tx((Usart*)ser->usart);
954  usart_enable_rx((Usart*)ser->usart);
955  }
956  else
957  { // Initialize UART
958  sam_uart_opt_t p_uart_opt =
959  {
961  .ul_baudrate = ser->usart_options.baudrate, // baudrate = sysclk / (16 * UART_BRGR). Example: 150000000 Hz / (16 * 10) = 937500 bps
962  .ul_mode = // Mode register:
963  UART_MR_PAR_NO | // No parity.
964  UART_MR_FILTER_DISABLED | // Don't filter Rx line.
965  UART_MR_BRSRCCK_PERIPH_CLK | // Use peripheral clock. Not PMC clock.
966  UART_MR_CHMODE_NORMAL // Normal channel mode. No loopback.
967  };
968 
969  // Initialize the UART in normal mode.
970  uart_init((Uart*)ser->usart, &p_uart_opt);
971 
972  // Enable the receiver and transmitter.
973  uart_enable((Uart*)ser->usart);
974  }
975 
976  return 0;
977 }
978 
979 #ifndef __INERTIAL_SENSE_EVB_2__
980 int validateBaudRate(unsigned int baudRate)
981 {
982  // Valid baudrates for InertialSense hardware
983  for (size_t i = 0; i < _ARRAY_ELEMENT_COUNT(g_validBaudRates); i++)
984  {
985  if (g_validBaudRates[i] == baudRate)
986  {
987  return 0;
988  }
989  }
990  return -1;
991 }
992 #endif
993 
994 // 0 on success, -1 on failure
995 int serSetBaudRate( int serialNum, int baudrate )
996 {
997  usartDMA_t *ser = (usartDMA_t*)&g_usartDMA[serialNum];
998  if( !ser->usart ) return -1;
999 
1000  // If we are not SPI, update baudrate
1001  if (ser->uinfo.isSpiUsart == 0)
1002  {
1003  // Update baudrate setting
1004 #ifndef __INERTIAL_SENSE_EVB_2__
1005  if (0 == validateBaudRate(baudrate))
1006 #endif
1007  ser->usart_options.baudrate = baudrate;
1008  }
1009 
1010  return serEnable(serialNum);
1011 }
1012 
1016 int serGetBaudRate( int serialNum )
1017 {
1018  usartDMA_t *ser = (usartDMA_t*)&g_usartDMA[serialNum];
1019  if( !ser ) return -1;
1020 
1021  // Baudrate setting
1022  return ser->usart_options.baudrate;
1023 }
1024 
1025 /********************************* INITIALIZATION ROUTINES ***************************************************************************************************/
1026 //The optimizer seems to allow the use of the lld array before it is completely configured. No optimization prevents that from happening.
1027 __attribute__((optimize("O0")))
1028 static void serDmaRxInit(usartDMA_t *ser)
1029 {
1030  xdmac_channel_config_t cfg = {0};
1031  cfg.mbr_sa = (uint32_t)ser->uinfo.usartRxRHR;
1032  cfg.mbr_da = (uint32_t)ser->dmaRx.buf;
1042  XDMAC_CC_PERID(ser->uinfo.xdmacUsartRxPerId);
1043  cfg.mbr_ubc = ser->dmaRx.size;
1044  xdmac_configure_transfer(XDMAC, ser->dmaRx.dmaChNumber, &cfg);
1045 
1046  // Configure linked list descriptor (only uses one)
1047  ser->dmaRx.lld.mbr_ta = (uint32_t)ser->dmaRx.buf;
1048  ser->dmaRx.lld.mbr_nda = (uint32_t)&(ser->dmaRx.lld); // point to self
1049  ser->dmaRx.lld.mbr_ubc =
1053  ser->dmaRx.size;
1054 
1055  // Set initial descriptor control
1056  xdmac_channel_set_descriptor_control(XDMAC, ser->dmaRx.dmaChNumber, //Updates CNDC register
1060  xdmac_channel_set_descriptor_addr(XDMAC, ser->dmaRx.dmaChNumber, (uint32_t)&(ser->dmaRx.lld), 0); //Updates CNDA register
1061 }
1062 
1063 //The optimizer seems to allow the use of the lld array before it is completely configured. No optimization prevents that from happening.
1064 __attribute__((optimize("O0")))
1065 static void serDmaTxInit(usartDMA_t *ser)
1066 {
1067  xdmac_channel_config_t cfg = {0};
1068  cfg.mbr_sa = (uint32_t)noData_indicator;
1069  cfg.mbr_da = (uint32_t)ser->uinfo.usartTxTHR;
1079  XDMAC_CC_PERID(ser->uinfo.xdmacUsartTxPerId);
1080  cfg.mbr_ubc = 0;
1081  xdmac_configure_transfer(XDMAC, ser->dmaTx.dmaChNumber, &cfg);
1082 
1083  //Setup pointers to lld array
1084  ser->dmaTx.lld_fptr = 0;
1085  ser->dmaTx.lld_bptr = 0;
1086 
1087  if (ser->uinfo.isSpiUsart)
1088  {
1089  // The datasheet says that when a transfer happens and there is no data in the TX buffer, it will send a 0xFF. Its true right after reset, it will send 0xFF.
1090  // But that appears to be not true after data has been sent. If the last bit sent was high, the line stays high and will send a 0xFF, if the last bit was low, it will stay low and send 0x00.
1091  // But... can we guarantee that will hold true if they do a chip rev? Maybe not, so we will just guarantee it by keeping the TX DMA running
1092  // This is done by having the lld loop back on itself with 0x00 data.
1093 
1094  for(int i=0; i<DMA_LLD_COUNT; i++)
1095  {
1096  // Data nodes point to empty indicator so when they finish sending the empty indicator gets sent
1097  ser->dmaTx.lld[i].mbr_nda = (uint32_t)&(ser->dmaTx.lld_spi_noData[i]);
1098 
1099  // Configure the DMA descriptors that handle transmission when there is no data to be sent. These will be configured to loop back on themselves.
1100  ser->dmaTx.lld_spi_noData[i].mbr_nda = (uint32_t)&(ser->dmaTx.lld_spi_noData[i]);
1101 
1102  // The data to send comes from the noData_indicator array
1103  ser->dmaTx.lld_spi_noData[i].mbr_ta = (uint32_t)noData_indicator;
1104 
1105  //Setup microblock control member - this will never change for the no data indicators.
1106  ser->dmaTx.lld_spi_noData[i].mbr_ubc = XDMAC_UBC_NVIEW_NDV0 | XDMAC_UBC_NDE_FETCH_EN | XDMAC_UBC_NSEN_UPDATED | sizeof(noData_indicator);
1107  }
1108 
1109  // Set initial descriptor control
1111  xdmac_channel_set_descriptor_addr(XDMAC, ser->dmaTx.dmaChNumber, (uint32_t)&(ser->dmaTx.lld_spi_noData[0]), 0);
1112  ser->dmaTx.lld_fptr = 1;
1113 
1114 #if CONF_BOARD_USART_SPI_DATAREADY_ENABLE == 1
1115  //Setup interrupts for data ready pin for SPI mode
1117  NVIC_SetPriority(XDMAC_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY); //Must not be higher than RTOS allows
1119 #endif
1120  }
1121  else
1122  {
1123  //Setup interrupts for DMA for UART mode (gets multiple setups as this routine is called for multiple USARTs)
1125  NVIC_SetPriority(XDMAC_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY); //Must not be higher than RTOS allows
1127  }
1128 }
1129 
1130 
1131 #if (ENABLE_COMM_LOOPBACK_DRIVER > 0)
1132 static void serLoopback(int portNum)
1133 {
1134  if (CONF_LOOPBACK_PORT != portNum)
1135  return;
1136 
1137 #define RX_BUF_SIZE 256
1138  static unsigned char rxBuf[RX_BUF_SIZE] = {0};
1139  int bytesRead = 0;
1140  int timeout = 0;
1141 
1142 #if ENABLE_COMM_LOOPBACK_DRIVER==1 // Loop back test - simple
1143  while (1)
1144  {
1145  // Read data
1146 // bytesRead = serRead(portNum, rxBuf, 1, 0);
1147  bytesRead = serRead(portNum, rxBuf, RX_BUF_SIZE, 0);
1148 
1149  // Write data
1150  if (bytesRead)
1151  {
1152  if (g_usartDMA[portNum].uinfo.isSpiUsart)
1153  {
1154  //we need to omit zero data for the test
1155  int i, cnt = 0;
1156  for(i=0;i<bytesRead;i++)
1157  if(rxBuf[i] != 0)
1158  rxBuf[cnt++] = rxBuf[i];
1159 
1160  serWrite(portNum, rxBuf, cnt, 0);
1161  }
1162  else
1163  {
1164  serWrite(portNum, rxBuf, bytesRead, 0);
1165  }
1166  LEDS_ALL_TOGGLE();
1167  }
1168 
1169 #ifndef __INERTIAL_SENSE_EVB_2__
1170  watchdog_maintenance_force(); // ensure watch dog does not kill us
1171 #endif
1172  }
1173 #endif // ENABLE_COMM_LOOPBACK_DRIVER==1
1174 
1175 #if ENABLE_COMM_LOOPBACK_DRIVER==2 // Loop back test - multiple reads before multiple writes
1176  LEDS_ALL_OFF();
1177 
1178  while (1)
1179  {
1180  // Aggregate data
1181  if (serRead(portNum, &(rxBuf[bytesRead]), 1, 0))
1182  {
1183  if (g_usartDMA[portNum].uinfo.isSpiUsart)
1184  {
1185  if(rxBuf[bytesRead] != 0)
1186  ++bytesRead;
1187  }
1188  else
1189  {
1190  ++bytesRead;
1191  }
1192 
1193  // Toggle LED for Rx
1194  LED_TOGGLE(LED_GRN);
1195 
1196  timeout = 0;
1197  }
1198 
1199  // Wait until we have number of bytes to read or we timeout
1200  if (bytesRead>=10 || ++timeout >= 100000)
1201  {
1202  if(bytesRead)
1203  {
1204  int bytesSend1 = bytesRead/2; // split transmission into two serWrite calls
1205  int bytesSend2 = bytesRead - bytesSend1;
1206  serWrite(portNum, rxBuf, bytesSend1, 0);
1207  serWrite(portNum, &rxBuf[bytesSend1], bytesSend2, 0);
1208  bytesRead = 0;
1209 
1210  // Toggle LED for Tx
1211  LED_TOGGLE(LED_RED);
1212  }
1213 
1214  timeout = 0;
1215  }
1216 
1217  watchdog_maintenance_force(); // ensure watch dog does not kill us
1218  }
1219 #endif // ENABLE_COMM_LOOPBACK_DRIVER==2
1220 
1221 #if ENABLE_COMM_LOOPBACK_DRIVER == 3 // Raw read/write test
1222  //Turn off DMA
1223  usartDMA_t *ser = (usartDMA_t*)&g_usartDMA[portNum];
1226 
1227  // For SPI mode, preload data for transmit
1228  if (ser->uinfo.isSpiUsart)
1229  {
1230  ((Usart*)ser->usart)->US_THR = 0;
1231  }
1232 
1233  while(1)
1234  {
1235  uint32_t status = usart_get_status((Usart*)ser->usart);
1236 
1237  if(status & US_CSR_RXRDY && status & US_CSR_TXRDY)
1238  {
1239  ((Usart*)ser->usart)->US_THR = ((Usart*)ser->usart)->US_RHR;
1240  }
1241 
1242  watchdog_maintenance_force(); // ensure watch dog does not kill us
1243  }
1244 #endif // ENABLE_COMM_LOOPBACK_DRIVER==3
1245 
1246 #if ENABLE_COMM_LOOPBACK_DRIVER==4 //Assembles a packet before sending back
1247  LEDS_ALL_OFF();
1248  ((Usart*)g_usartDMA[portNum].usart)->US_THR = 0;
1249 
1250  while (1)
1251  {
1252  bool inpacket = false;
1253  bytesRead = 0;
1254 
1255  while(1)
1256  {
1257  if (serRead(portNum, &(rxBuf[bytesRead]), 1, 0))
1258  {
1259  if(inpacket)
1260  {
1261  ++bytesRead;
1262 
1263  if(0xFE == rxBuf[bytesRead - 1])
1264  break;
1265  }
1266  else
1267  {
1268  if( 0xFF == rxBuf[bytesRead])
1269  {
1270  ++bytesRead;
1271  inpacket = true;
1272  }
1273  }
1274 
1275  // Toggle LED for Rx
1276  LED_TOGGLE(LED_GRN);
1277  }
1278 
1279  watchdog_maintenance_force(); // ensure watch dog does not kill us
1280  }
1281 
1282  if(bytesRead)
1283  {
1284  for(int j=2;j<bytesRead-1;j++)
1285  {
1286  if(rxBuf[j-1] + 1 != rxBuf[j])
1287  rxBuf[j] = 200;
1288  }
1289  serWrite(portNum, rxBuf, bytesRead, 0);
1290  bytesRead = 0;
1291 
1292  // Toggle LED for Tx
1293  LED_TOGGLE(LED_RED);
1294  }
1295  }
1296 #endif // ENABLE_COMM_LOOPBACK_DRIVER==4
1297 
1298 } // serLoopback
1299 #endif // ENABLE_COMM_LOOPBACK_DRIVER > 0
1300 
1301 static int setup_usart_info(usartDMA_t *ser, int serialNumber, uint32_t baudRate, sam_usart_opt_t *options)
1302 {
1303  // Setup Baud Rate
1304  if(baudRate == 0)
1305  {
1307  }
1308  else if(options != NULL)
1309  {
1310  if(options->baudrate == 0)
1312  else
1313  ser->usart_options.baudrate = options->baudrate;
1314  }
1315  else
1316  {
1317  ser->usart_options.baudrate = baudRate;
1318  }
1319 
1320  // Setup other port options
1321  if(options == NULL)
1322  {
1323  //Use defaults
1328  }
1329  else
1330  {
1331  //Use custom settings
1332  ser->usart_options.char_length = options->char_length;
1333  ser->usart_options.parity_type = options->parity_type;
1334  ser->usart_options.stop_bits = options->stop_bits;
1335  ser->usart_options.channel_mode = options->channel_mode;
1336  }
1337 
1338  return 0;
1339 }
1340 
1341 static int serBufferInit(usartDMA_t *ser, int serialNumber)
1342 {
1343  //Configure DMA & Buffer
1344  switch(serialNumber)
1345  {
1346  default:
1347  break;
1348 #if MAX_NUMBER_SERIAL_PORTS >= 1
1349  case 0:
1350  ser->usart = ARGN(0, PORT0_CONFIG);
1351  ser->dmaTx.size = ARGN(2, PORT0_CONFIG);
1352  ser->dmaRx.size = ARGN(4, PORT0_CONFIG);
1353  ser->dmaTx.dmaChNumber = ARGN(1, PORT0_CONFIG);
1354  ser->dmaRx.dmaChNumber = ARGN(3, PORT0_CONFIG);
1355  ser->dmaTx.buf = g_serTxDmaBuf_port0;
1356  ser->dmaRx.buf = g_serRxDmaBuf_port0;
1357  break;
1358 #endif
1359 #if MAX_NUMBER_SERIAL_PORTS >= 2
1360  case 1:
1361  ser->usart = ARGN(0, PORT1_CONFIG);
1362  ser->dmaTx.size = ARGN(2, PORT1_CONFIG);
1363  ser->dmaRx.size = ARGN(4, PORT1_CONFIG);
1364  ser->dmaTx.dmaChNumber = ARGN(1, PORT1_CONFIG);
1365  ser->dmaRx.dmaChNumber = ARGN(3, PORT1_CONFIG);
1366  ser->dmaTx.buf = g_serTxDmaBuf_port1;
1367  ser->dmaRx.buf = g_serRxDmaBuf_port1;
1368  break;
1369 #endif
1370 #if MAX_NUMBER_SERIAL_PORTS >= 3
1371  case 2:
1372  ser->usart = ARGN(0, PORT2_CONFIG);
1373  ser->dmaTx.size = ARGN(2, PORT2_CONFIG);
1374  ser->dmaRx.size = ARGN(4, PORT2_CONFIG);
1375  ser->dmaTx.dmaChNumber = ARGN(1, PORT2_CONFIG);
1376  ser->dmaRx.dmaChNumber = ARGN(3, PORT2_CONFIG);
1377  ser->dmaTx.buf = g_serTxDmaBuf_port2;
1378  ser->dmaRx.buf = g_serRxDmaBuf_port2;
1379  break;
1380 #endif
1381 #if MAX_NUMBER_SERIAL_PORTS >= 4
1382  case 3:
1383  ser->usart = ARGN(0, PORT3_CONFIG);
1384  ser->dmaTx.size = ARGN(2, PORT3_CONFIG);
1385  ser->dmaRx.size = ARGN(4, PORT3_CONFIG);
1386  ser->dmaTx.dmaChNumber = ARGN(1, PORT3_CONFIG);
1387  ser->dmaRx.dmaChNumber = ARGN(3, PORT3_CONFIG);
1388  ser->dmaTx.buf = g_serTxDmaBuf_port3;
1389  ser->dmaRx.buf = g_serRxDmaBuf_port3;
1390  break;
1391 #endif
1392 #if MAX_NUMBER_SERIAL_PORTS >= 5
1393  case 4:
1394  ser->usart = ARGN(0, PORT4_CONFIG);
1395  ser->dmaTx.size = ARGN(2, PORT4_CONFIG);
1396  ser->dmaRx.size = ARGN(4, PORT4_CONFIG);
1397  ser->dmaTx.dmaChNumber = ARGN(1, PORT4_CONFIG);
1398  ser->dmaRx.dmaChNumber = ARGN(3, PORT4_CONFIG);
1399  ser->dmaTx.buf = g_serTxDmaBuf_port4;
1400  ser->dmaRx.buf = g_serRxDmaBuf_port4;
1401  break;
1402 #endif
1403 #if MAX_NUMBER_SERIAL_PORTS >= 6
1404  case 5:
1405  ser->usart = ARGN(0, PORT5_CONFIG);
1406  ser->dmaTx.size = ARGN(2, PORT5_CONFIG);
1407  ser->dmaRx.size = ARGN(4, PORT5_CONFIG);
1408  ser->dmaTx.dmaChNumber = ARGN(1, PORT5_CONFIG);
1409  ser->dmaRx.dmaChNumber = ARGN(3, PORT5_CONFIG);
1410  ser->dmaTx.buf = g_serTxDmaBuf_port5;
1411  ser->dmaRx.buf = g_serRxDmaBuf_port5;
1412  break;
1413 #endif
1414 #if MAX_NUMBER_SERIAL_PORTS >= 7
1415  case 6:
1416  ser->usart = ARGN(0, PORT6_CONFIG);
1417  ser->dmaTx.size = ARGN(2, PORT6_CONFIG);
1418  ser->dmaRx.size = ARGN(4, PORT6_CONFIG);
1419  ser->dmaTx.dmaChNumber = ARGN(1, PORT6_CONFIG);
1420  ser->dmaRx.dmaChNumber = ARGN(3, PORT6_CONFIG);
1421  ser->dmaTx.buf = g_serTxDmaBuf_port6;
1422  ser->dmaRx.buf = g_serRxDmaBuf_port6;
1423  break;
1424 #endif
1425 #if MAX_NUMBER_SERIAL_PORTS >= 8
1426  case 7:
1427  ser->usart = ARGN(0, PORT7_CONFIG);
1428  ser->dmaTx.size = ARGN(2, PORT7_CONFIG);
1429  ser->dmaRx.size = ARGN(4, PORT7_CONFIG);
1430  ser->dmaTx.dmaChNumber = ARGN(1, PORT7_CONFIG);
1431  ser->dmaRx.dmaChNumber = ARGN(3, PORT7_CONFIG);
1432  ser->dmaTx.buf = g_serTxDmaBuf_port7;
1433  ser->dmaRx.buf = g_serRxDmaBuf_port7;
1434  break;
1435 #endif
1436  }
1437 
1438  // Setup hardware specific items
1439  if( ser->usart == USART0 )
1440  {
1441  ser->uinfo.ul_id = ID_USART0;
1442  ser->uinfo.usartTxTHR = (uint32_t)&(USART0->US_THR);
1443  ser->uinfo.usartRxRHR = (uint32_t)&(USART0->US_RHR);
1446  ser->uinfo.isUsartNotUart = true;
1447  ser->uinfo.isSpiUsart = false;
1448  }
1449  else if( ser->usart == USART1 )
1450  {
1451  ser->uinfo.ul_id = ID_USART1;
1452  ser->uinfo.usartTxTHR = (uint32_t)&(USART1->US_THR);
1453  ser->uinfo.usartRxRHR = (uint32_t)&(USART1->US_RHR);
1456  ser->uinfo.isUsartNotUart = true;
1457  ser->uinfo.isSpiUsart = false;
1458  }
1459  else if( ser->usart == USART2 )
1460  {
1461  ser->uinfo.ul_id = ID_USART2;
1462  ser->uinfo.usartTxTHR = (uint32_t)&(USART2->US_THR);
1463  ser->uinfo.usartRxRHR = (uint32_t)&(USART2->US_RHR);
1466  ser->uinfo.isUsartNotUart = true;
1467 #if CONF_BOARD_USART_SPI == 1
1468  ser->uinfo.isSpiUsart = g_spi_comm_select;
1469 #else
1470  ser->uinfo.isSpiUsart = false;
1471 #endif
1472  }
1473  else if( ser->usart == UART0 )
1474  {
1475  ser->uinfo.ul_id = ID_UART0;
1476  ser->uinfo.usartTxTHR = (uint32_t)&(UART0->UART_THR);
1477  ser->uinfo.usartRxRHR = (uint32_t)&(UART0->UART_RHR);
1480  ser->uinfo.isUsartNotUart = false;
1481  ser->uinfo.isSpiUsart = false;
1482  }
1483  else if( ser->usart == UART1 )
1484  {
1485  ser->uinfo.ul_id = ID_UART1;
1486  ser->uinfo.usartTxTHR = (uint32_t)&(UART1->UART_THR);
1487  ser->uinfo.usartRxRHR = (uint32_t)&(UART1->UART_RHR);
1490  ser->uinfo.isUsartNotUart = false;
1491  ser->uinfo.isSpiUsart = false;
1492  }
1493  else if( ser->usart == UART2 )
1494  {
1495  ser->uinfo.ul_id = ID_UART2;
1496  ser->uinfo.usartTxTHR = (uint32_t)&(UART2->UART_THR);
1497  ser->uinfo.usartRxRHR = (uint32_t)&(UART2->UART_RHR);
1500  ser->uinfo.isUsartNotUart = false;
1501  ser->uinfo.isSpiUsart = false;
1502  }
1503  else if( ser->usart == UART3 )
1504  {
1505  ser->uinfo.ul_id = ID_UART3;
1506  ser->uinfo.usartTxTHR = (uint32_t)&(UART3->UART_THR);
1507  ser->uinfo.usartRxRHR = (uint32_t)&(UART3->UART_RHR);
1510  ser->uinfo.isUsartNotUart = false;
1511  ser->uinfo.isSpiUsart = false;
1512  }
1513  else if( ser->usart == UART4 )
1514  {
1515  ser->uinfo.ul_id = ID_UART4;
1516  ser->uinfo.usartTxTHR = (uint32_t)&(UART4->UART_THR);
1517  ser->uinfo.usartRxRHR = (uint32_t)&(UART4->UART_RHR);
1520  ser->uinfo.isUsartNotUart = false;
1521  ser->uinfo.isSpiUsart = false;
1522  }
1523  else
1524  {
1525 #ifdef USB_PORT_NUM
1526  if( serialNumber != USB_PORT_NUM )
1527 #endif
1528  {
1529  // "Invalid USART selected!!!"
1530  return -1;
1531  }
1532  }
1533 
1534  if (ser->dmaTx.buf == NULL || ser->dmaRx.buf == NULL || !IS_32B_ALIGNED(ser->dmaTx.buf) || !IS_32B_ALIGNED(ser->dmaRx.buf))
1535  {
1536 // #ifndef __INERTIAL_SENSE_EVB_2__
1537 // extern void soft_reset_backup_register(uint32_t value, uint32_t subValue);
1538 // soft_reset_backup_register(CRASH_INFO_INVALID_CODE_OPERATION, 0);
1539 // #endif
1540  }
1541 
1542  // Set pointer to start of buffer
1543  ser->dmaTx.ptr = ser->dmaTx.buf;
1544  ser->dmaRx.ptr = ser->dmaRx.buf;
1545 
1546  // Set pointer to end of buffer
1547  ser->dmaTx.end = ser->dmaTx.buf + ser->dmaTx.size;
1548  ser->dmaRx.end = ser->dmaRx.buf + ser->dmaRx.size;
1549 
1550 #ifdef USB_PORT_NUM
1551  if( serialNumber == USB_PORT_NUM )
1552  {
1553  ser->dmaTx.end = ser->dmaTx.ptr;
1554  }
1555 #endif
1556 
1557  return 0;
1558 }
1559 
1560 int serInit(int serialNum, uint32_t baudRate, sam_usart_opt_t *options, uint32_t* overrunStatus)
1561 {
1562 #ifdef USB_PORT_NUM
1563  if(serialNum == USB_PORT_NUM)
1564  {
1565  // Setup pointers for additional USB buffer
1566  if (serBufferInit((usartDMA_t *)&g_usartDMA[USB_PORT_NUM], serialNum) != 0)
1567  return -1;
1568 
1569  udc_start();
1570 
1571  #if (ENABLE_COMM_LOOPBACK_DRIVER==1 || ENABLE_COMM_LOOPBACK_DRIVER==2)
1572  serLoopback(serialNum);
1573  #endif // ENABLE_COMM_LOOPBACK_DRIVER == 1 || 2
1574 
1575  return 0;
1576  }
1577 #endif
1578 
1579  if(overrunStatus)
1580  { // Set buffer overrun status pointer
1581  s_overrunStatus = overrunStatus;
1582  }
1583 
1584  // Validate port number
1585  while( serialNum >= MAX_NUMBER_SERIAL_PORTS ) { /* Invalid port number */ }
1586 
1587  usartDMA_t *ser = (usartDMA_t *)&g_usartDMA[serialNum];
1588 
1589  // Setup UART
1590  if (setup_usart_info(ser, serialNum, baudRate, options) != 0)
1591  while(1);
1592 
1593  // Setup buffers
1594  if (serBufferInit(ser, serialNum) != 0)
1595  return -1;
1596 
1597  // Enable the peripheral clock in the PMC
1599 
1600  // Re-init UART
1601  serSetBaudRate(serialNum, ser->usart_options.baudrate);
1602 
1603  // Enable interrupt for errors
1605  NVIC_EnableIRQ(ser->uinfo.ul_id);
1606 
1607  /* Initialize and enable DMA controller */
1609 
1610  /* Get pointer to XDMA channel id */
1611  Assert(XDMAC);
1614  ser->dmaTx.dmaChId = &(XDMAC->XDMAC_CHID[ser->dmaTx.dmaChNumber]);
1615  ser->dmaRx.dmaChId = &(XDMAC->XDMAC_CHID[ser->dmaRx.dmaChNumber]);
1616 
1617  serDmaTxInit(ser);
1618  serDmaRxInit(ser);
1619 
1620  // Enable Rx, only enable Tx when ready to transmit data.
1621  // flush descriptors, etc. so that dma enable reads fresh values
1622 #if CONF_BOARD_ENABLE_DCACHE == 1
1624 #endif
1625  XDMAC->XDMAC_GE = (XDMAC_GE_EN0 << (ser->dmaRx.dmaChNumber));
1626 
1627  // For SPI mode, TX DMA needs to run all the time
1628  if (ser->uinfo.isSpiUsart)
1629  {
1630  XDMAC->XDMAC_GE = (XDMAC_GE_EN0 << (ser->dmaTx.dmaChNumber));
1631  }
1632 
1633 #if (ENABLE_COMM_LOOPBACK_DRIVER > 0)
1634  serLoopback(serialNum);
1635 #endif
1636 
1637  return 0;
1638 }
1639 
1640 //Interrupts get enabled for errors. Clear error in interrupt.
1641 void UART0_Handler(void) { UART0->UART_CR = UART_CR_RSTSTA; }
1642 void UART1_Handler(void) { UART1->UART_CR = UART_CR_RSTSTA; }
1643 void UART2_Handler(void) { UART2->UART_CR = UART_CR_RSTSTA; }
1644 void UART3_Handler(void) { UART3->UART_CR = UART_CR_RSTSTA; }
1645 void UART4_Handler(void) { UART4->UART_CR = UART_CR_RSTSTA; }
1646 void USART0_Handler(void) { USART0->US_CR = US_CR_RSTSTA; }
1647 void USART1_Handler(void) { USART1->US_CR = US_CR_RSTSTA; }
1648 void USART2_Handler(void) { USART2->US_CR = US_CR_RSTSTA; }
void usart_enable_rx(Usart *p_usart)
Enable USART receiver.
Definition: usart.c:1426
#define XDMAC_PERID_UART4_TX
Definition: d_dma.h:79
#define UART_MR_PAR_NO
(UART_MR) No parity
#define XDMAC_PERID_UART3_TX
Definition: d_dma.h:77
#define XDMAC_PERID_UART1_RX
Definition: d_dma.h:74
#define LEDS_ALL_OFF()
Definition: user_board.h:273
int serTxUsed(int serialNum)
Returns number of bytes used in Tx buffer.
Definition: d_usartDMA.c:289
volatile uint32_t size
Definition: d_usartDMA.c:62
#define XDMAC_CC_DSYNC_MEM2PER
(XDMAC_CC) Memory to Peripheral transfer
#define PORT6_CONFIG
#define UART_MR_BRSRCCK_PERIPH_CLK
(UART_MR) The baud rate is driven by the peripheral clock
void d_usartDMA_callback_cdc_tx_empty_notify(void)
Definition: d_usartDMA.c:171
volatile uint8_t * buf
Definition: d_usartDMA.c:67
int serSetBaudRate(int serialNum, int baudrate)
Change USART baudrate. 0 on success, -1 on failure.
Definition: d_usartDMA.c:995
#define ID_USART1
USART 1 (USART1)
Definition: same70j19.h:419
#define MEMCPY_DCACHE_CLEAN(dst, src, size)
Definition: d_dma.h:26
uint32_t time_msec(void)
Definition: d_time.c:95
#define UART_IER_PARE
(UART_IER) Enable Parity Error Interrupt
static void xdmac_channel_set_descriptor_control(Xdmac *xdmac, uint32_t channel_num, uint32_t config)
Set next descriptor&#39;s configuration for the relevant channel of given XDMA.
static int serTxFreeDma(dmaBuffer_tx_t *dma)
Definition: d_usartDMA.c:275
static dmaBuffer_rx_t * getRxDma(uint32_t serialNum)
Definition: d_usartDMA.c:240
#define ID_XDMAC
DMA (XDMAC)
Definition: same70j19.h:443
__I uint32_t XDMAC_CIS
(XdmacChid Offset: 0xC) Channel Interrupt Status Register
static void ioport_set_pin_level(ioport_pin_t pin, bool level)
Set an IOPORT pin to a specified logical value.
Definition: ioport.h:275
#define XDMAC_CC_TYPE_PER_TRAN
(XDMAC_CC) Synchronized mode (Peripheral to Memory or Memory to Peripheral Transfer).
uint32_t used
Definition: USBD.h:95
#define US_MR_NBSTOP_1_BIT
(US_MR) 1 stop bit
#define taskEXIT_CRITICAL()
Definition: task.h:194
#define MAX_NUMBER_SERIAL_PORTS
#define SCB_CLEAN_DCACHE_BY_ADDR_32BYTE_ALIGNED(addr, size)
static const uint8_t * getCurrentRxDmaAddress(dmaBuffer_rx_t *dma)
Definition: d_usartDMA.c:226
#define XDMAC_CC_SAM_FIXED_AM
(XDMAC_CC) The address remains unchanged.
uint32_t usart_init_spi_slave(Usart *p_usart, const usart_spi_opt_t *p_usart_opt)
Configure USART to work in SPI mode and act as a slave.
Definition: usart.c:782
static void xdmac_disable_interrupt(Xdmac *xdmac, uint32_t channel_num)
Disables XDMAC global interrupt.
#define XDMAC_CNDC_NDVIEW_NDV0
(XDMAC_CNDC) Next Descriptor View 0
int serGetBaudRate(int serialNum)
Read USART baudrate. Return value is the baudrate or -1 on failure.
Definition: d_usartDMA.c:1016
#define XDMAC_CNDC_NDDUP_DST_PARAMS_UPDATED
(XDMAC_CNDC) Destination parameters are updated when the descriptor is retrieved. ...
int serInit(int serialNum, uint32_t baudRate, sam_usart_opt_t *options, uint32_t *overrunStatus)
Initialize serial port with specific USART/UART and DMA settings. If not NULL, the overrun status wil...
Definition: d_usartDMA.c:1560
void USART1_Handler(void)
Definition: d_usartDMA.c:1647
Usart hardware registers.
void d_usartDMA_callback_cdc_disable(void)
Definition: d_usartDMA.c:166
#define Min(a, b)
Takes the minimal value of a and b.
Definition: compiler.h:786
void usart_enable_interrupt(Usart *p_usart, uint32_t ul_sources)
Enable USART interrupts.
Definition: usart.c:1469
static bool usb_cdc_open
Definition: d_usartDMA.c:158
if(udd_ctrl_interrupt())
Definition: usbhs_device.c:688
bool d_usartDMA_callback_cdc_enable(void)
Definition: d_usartDMA.c:160
#define XDMAC
(XDMAC ) Base Address
Definition: same70j19.h:520
static int serTxUsedDma(dmaBuffer_tx_t *dma)
Definition: d_usartDMA.c:249
volatile uint8_t dmaChNumber
Definition: d_usartDMA.c:61
static void xdmac_channel_software_flush_request(Xdmac *xdmac, uint32_t channel_num)
Set software flush request on the relevant channel.
size_t count(InputIterator first, InputIterator last, T const &item)
Definition: catch.hpp:3206
__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
Set Interrupt Priority.
Definition: core_cm7.h:1766
static dmaBuffer_tx_t * getTxDma(uint32_t serialNum)
Definition: d_usartDMA.c:231
__I uint32_t XDMAC_CIM
(XdmacChid Offset: 0x8) Channel Interrupt Mask Register
#define ID_USBHS
USB Host / Device Controller (USBHS)
Definition: same70j19.h:432
void UART0_Handler(void)
Definition: d_usartDMA.c:1641
#define UART3
(UART3 ) Base Address
Definition: same70n19.h:584
static void xdmac_channel_set_descriptor_addr(Xdmac *xdmac, uint32_t channel_num, uint32_t desc_addr, uint8_t ndaif)
Set next descriptor&#39;s address & interface for the relevant channel of given XDMA. ...
#define PORT1_CONFIG
uint32_t pmc_enable_periph_clk(uint32_t ul_id)
Enable the specified peripheral clock.
Definition: pmc.c:682
#define PORT7_CONFIG
#define NULL
Definition: nm_bsp.h:52
#define ARGN(N, LIST)
Definition: d_usartDMA.c:97
volatile uint8_t dmaChNumber
Definition: d_usartDMA.c:38
#define UART_IER_OVRE
(UART_IER) Enable Overrun Error Interrupt
int serRead(int serialNum, unsigned char *buf, int size)
Read data on USART. Returns number of bytes read. With use of the PDCA ring buffer, buffer overrun may occur if bytes are received is greater than bytes read plus buffer size.
Definition: d_usartDMA.c:782
#define XDMAC_CNDC_NDSUP_SRC_PARAMS_UPDATED
(XDMAC_CNDC) Source parameters are updated when the descriptor is retrieved.
#define XDMAC_PERID_USART1_TX
Definition: d_dma.h:67
#define XDMAC_UBC_NDE_FETCH_EN
uint32_t ul_id
Definition: d_usartDMA.c:77
Uart hardware registers.
volatile uint8_t * buf
Definition: d_usartDMA.c:42
#define XDMAC_CC_MEMSET_NORMAL_MODE
(XDMAC_CC) Memset is not activated
#define XDMAC_PERID_UART2_TX
Definition: d_dma.h:75
#define US_MR_PAR_NO
(US_MR) No parity
#define US_MR_CHMODE_NORMAL
(US_MR) Normal mode
#define XDMAC_UBC_UBLEN(value)
#define ID_UART3
UART 3 (UART3)
Definition: same70n19.h:468
#define XDMAC_PERID_USART0_TX
Definition: d_dma.h:65
uint32_t xdmacUsartTxPerId
Definition: d_usartDMA.c:80
#define XDMAC_PERID_UART2_RX
Definition: d_dma.h:76
#define UART1
(UART1 ) Base Address
Definition: same70j19.h:527
#define USART0
(USART0) Base Address
Definition: same70j19.h:505
#define XDMAC_CC_DAM_FIXED_AM
(XDMAC_CC) The address remains unchanged.
void uart_enable(Uart *p_uart)
Enable UART receiver and transmitter.
Definition: uart.c:181
iram_size_t udi_cdc_get_free_tx_buffer(void)
Gets the number of free byte in TX buffer.
Definition: udi_cdc.c:1035
#define ID_UART0
UART 0 (UART0)
Definition: same70j19.h:414
static int serBufferInit(usartDMA_t *ser, int serialNumber)
Definition: d_usartDMA.c:1341
#define USART1
(USART1) Base Address
Definition: same70j19.h:506
uint32_t usart_get_status(Usart *p_usart)
Get current status.
Definition: usart.c:1504
void UART1_Handler(void)
Definition: d_usartDMA.c:1642
uint32_t uart_init(Uart *p_uart, const sam_uart_opt_t *p_uart_opt)
Configure UART with the specified parameters.
Definition: uart.c:81
static void xdmac_channel_set_source_addr(Xdmac *xdmac, uint32_t channel_num, uint32_t src_addr)
Set source address for the relevant channel of given XDMA.
iram_size_t udi_cdc_write_buf(const void *buf, iram_size_t size)
Writes a RAM buffer on CDC line.
Definition: udi_cdc.c:1146
volatile uint32_t lld_bptr
Definition: d_usartDMA.c:48
void udc_start(void)
Start the USB Device stack.
Definition: udc.c:351
#define NULLPTR
Definition: ISConstants.h:426
#define SER_INDICATE_TX()
#define XDMAC_CIE_BIE
(XDMAC_CIE) End of Block Interrupt Enable Bit
XdmacChid hardware registers.
#define UART_IER_FRAME
(UART_IER) Enable Framing Error Interrupt
#define PORT4_CONFIG
#define PORT5_CONFIG
#define XDMAC_CC_DAM_INCREMENTED_AM
(XDMAC_CC) The addressing mode is incremented (the increment size is set to the data size)...
__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn)
Disable External Interrupt.
Definition: core_cm7.h:1696
#define XDMAC_CC_SIF_AHB_IF1
(XDMAC_CC) The data is read through the system bus interface 1
#define XDMAC_CNDC_NDE_DSCR_FETCH_EN
(XDMAC_CNDC) Descriptor fetch is enabled
volatile XdmacChid * dmaChId
Definition: d_usartDMA.c:60
static uint32_t sysclk_get_peripheral_hz(void)
Retrieves the current rate in Hz of the peripheral clocks.
volatile XdmacChid * dmaChId
Definition: d_usartDMA.c:37
__IO uint32_t XDMAC_CDA
(XdmacChid Offset: 0x14) Channel Destination Address Register
static void xdmac_channel_set_microblock_control(Xdmac *xdmac, uint32_t channel_num, uint32_t ublen)
Set microblock length for the relevant channel of given XDMA.
static int setup_usart_info(usartDMA_t *ser, int serialNumber, uint32_t baudRate, sam_usart_opt_t *options)
Definition: d_usartDMA.c:1301
int serFindCharacter(int serialNum, uint8_t ch)
Returns number of characters in buffer before specified character.
Definition: d_usartDMA.c:884
#define XDMAC_PERID_UART4_RX
Definition: d_dma.h:80
__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn)
Enable External Interrupt.
Definition: core_cm7.h:1683
__IO uint32_t XDMAC_CSA
(XdmacChid Offset: 0x10) Channel Source Address Register
#define UART_MR_CHMODE_NORMAL
(UART_MR) Normal mode
iram_size_t udi_cdc_read_no_polling(void *buf, iram_size_t size)
Non polling reads of a up to &#39;size&#39; data from CDC line.
Definition: udi_cdc.c:996
uint32_t usart_init_rs232(Usart *p_usart, const sam_usart_opt_t *p_usart_opt, uint32_t ul_mck)
Configure USART to work in RS232 mode.
Definition: usart.c:274
int serRxFree(int serialNum)
Returns number of bytes available in Rx buffer.
Definition: d_usartDMA.c:332
void XDMAC_spiTouINS_Handler(void)
static void xdmac_channel_disable_interrupt(Xdmac *xdmac, uint32_t channel_num, uint32_t mask)
Disable interrupt with mask on the relevant channel of given XDMA.
static void xdmac_enable_interrupt(Xdmac *xdmac, uint32_t channel_num)
Enables XDMAC global interrupt.
volatile uint32_t lld_fptr
Definition: d_usartDMA.c:47
__attribute__((optimize("O0")))
Definition: d_usartDMA.c:1027
__STATIC_INLINE void SCB_CleanInvalidateDCache(void)
Clean & Invalidate D-Cache.
Definition: core_cm7.h:2069
static const uint8_t * getCurrentTxDmaAddress(dmaBuffer_tx_t *dma)
Definition: d_usartDMA.c:214
static void xdmac_channel_disable(Xdmac *xdmac, uint32_t channel_num)
Disables the relevant channel of given XDMAC.
volatile uint32_t size
Definition: d_usartDMA.c:39
void UART2_Handler(void)
Definition: d_usartDMA.c:1643
int serTxFree(int serialNum)
Returns number of bytes available in Tx buffer.
Definition: d_usartDMA.c:313
#define XDMAC_UBC_NSEN_UPDATED
#define XDMAC_UBC_NDEN_UPDATED
#define XDMAC_PERID_USART2_RX
Definition: d_dma.h:70
#define XDMAC_PERID_USART0_RX
Definition: d_dma.h:66
static void xdmac_channel_enable_interrupt(Xdmac *xdmac, uint32_t channel_num, uint32_t mask)
Enable interrupt with mask on the relevant channel of given XDMA.
#define XDMAC_PERID_USART1_RX
Definition: d_dma.h:68
volatile void * usart
Definition: d_usartDMA.c:88
#define US_MR_CHRL_8_BIT
(US_MR) Character length is 8 bits
#define ID_UART1
UART 1 (UART1)
Definition: same70j19.h:415
int serTxClear(int serialNum)
Clear the entire Tx buffer.
Definition: d_usartDMA.c:344
const unsigned int g_validBaudRates[IS_BAUDRATE_COUNT]
Definition: ISComm.c:84
#define IS_32B_ALIGNED(_addr_)
Definition: d_dma.h:84
int serRxClear(int serialNum, int size)
Removes removes data from USART Rx buffer. Returns number of bytes removed. Length of -1 removes all ...
Definition: d_usartDMA.c:398
#define DMA_LLD_MASK
Definition: d_usartDMA.c:33
void xdmac_configure_transfer(Xdmac *xdmac, uint32_t channel_num, xdmac_channel_config_t *cfg)
Configure DMA for a transfer.
Definition: xdmac.c:46
#define XDMAC_CC_DIF_AHB_IF1
(XDMAC_CC) The data is written though the system bus interface 1
void XDMAC_Handler(void)
Definition: d_usartDMA.c:704
#define XDMAC_PERID_UART0_TX
Definition: d_dma.h:71
dmaBuffer_tx_t dmaTx
Definition: d_usartDMA.c:90
#define US_CSR_RXRDY
(US_CSR) Receiver Ready (cleared by reading US_RHR)
__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn)
Clear Pending Interrupt.
Definition: core_cm7.h:1736
#define ID_UART2
UART 2 (UART2)
Definition: same70j19.h:437
COMPILER_WORD_ALIGNED volatile lld_view0 lld[DMA_LLD_COUNT]
Definition: d_usartDMA.c:51
#define _CLAMP(v, minV, maxV)
Definition: ISConstants.h:302
volatile uint8_t * ptr
Definition: d_usartDMA.c:69
#define UART_MR_FILTER_DISABLED
(UART_MR) UART does not filter the receive line.
void USART0_Handler(void)
Definition: d_usartDMA.c:1646
void USART2_Handler(void)
Definition: d_usartDMA.c:1648
#define USB_PORT_NUM
Definition: user_board.h:192
static void xdmac_channel_enable_no_cache(Xdmac *xdmac, uint32_t channel_num)
enables the relevant channel of given XDMAC without invalidating data cache.
#define XDMAC_CC_DSYNC_PER2MEM
(XDMAC_CC) Peripheral to Memory transfer
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY
#define SCB_CLEANINVALIDATE_DCACHE_BY_ADDR_32BYTE_ALIGNED(addr, size)
Option list for UART peripheral initialization.
#define UINT32_TIME_DIFF(current, prev)
Definition: ISConstants.h:439
#define DMA_LLD_COUNT
Definition: d_usartDMA.c:32
#define UART_CR_RSTSTA
(UART_CR) Reset Status
#define LEDS_ALL_TOGGLE()
Definition: user_board.h:274
static int serRxUsedDma(dmaBuffer_rx_t *dma)
Definition: d_usartDMA.c:262
Structure for storing parameters for DMA view0 that can be performed by the DMA Master transfer...
volatile uint8_t * ptr
Definition: d_usartDMA.c:44
#define SPI_MODE_3
SPI mode 3.
#define PORT2_CONFIG
#define US_CSR_TXRDY
(US_CSR) Transmitter Ready (cleared by writing US_THR)
uint8_t isSpiUsart
Definition: d_usartDMA.c:83
#define taskENTER_CRITICAL()
Definition: task.h:179
#define SER_INDICATE_RX()
#define LED_TOGGLE(led)
Definition: user_board.h:237
enum IRQn IRQn_Type
sam_usart_opt_t usart_options
Definition: d_usartDMA.c:89
#define ID_USART0
USART 0 (USART0)
Definition: same70j19.h:418
port_monitor_helper_t g_portMonitorHelper[MAX_NUMBER_SERIAL_PORTS]
Definition: d_usartDMA.c:153
COMPILER_WORD_ALIGNED volatile lld_view0 lld
Definition: d_usartDMA.c:72
#define XDMAC_CIS_BIS
(XDMAC_CIS) End of Block Interrupt Status Bit
uint32_t xdmacUsartRxPerId
Definition: d_usartDMA.c:81
#define DEFAULT_BAUDRATE
static uint32_t * s_overrunStatus
Definition: d_usartDMA.c:152
uint32_t usartRxRHR
Definition: d_usartDMA.c:79
#define XDMACCHID_NUMBER
Xdmac hardware registers.
#define XDMAC_CC_SAM_INCREMENTED_AM
(XDMAC_CC) The addressing mode is incremented (the increment size is set to the data size)...
static volatile usartDMA_t g_usartDMA[MAX_NUMBER_SERIAL_PORTS]
Definition: d_usartDMA.c:150
#define PORT0_CONFIG
int validateBaudRate(unsigned int baudRate)
Returns -1 if the baudrate is not a standard baudrate.
Definition: d_usartDMA.c:980
usart_info_t uinfo
Definition: d_usartDMA.c:92
void usart_enable_tx(Usart *p_usart)
Enable USART transmitter.
Definition: usart.c:1384
#define CONF_LOOPBACK_PORT
static void sysclk_enable_peripheral_clock(uint32_t ul_id)
Enable a peripheral&#39;s clock.
Autogenerated API include file for the Atmel Software Framework (ASF)
COMPILER_ALIGNED(32)
Definition: d_usartDMA.c:150
#define XDMAC_GS_ST0
(XDMAC_GS) XDMAC Channel 0 Status Bit
void UART3_Handler(void)
Definition: d_usartDMA.c:1644
#define XDMAC_PERID_USART2_TX
Definition: d_dma.h:69
static int serRxFreeDma(dmaBuffer_rx_t *dma)
Definition: d_usartDMA.c:280
#define _ARRAY_ELEMENT_COUNT(a)
Definition: ISConstants.h:326
static int serEnable(int serialNum)
Definition: d_usartDMA.c:928
#define PORT3_CONFIG
#define UART0
(UART0 ) Base Address
Definition: same70j19.h:525
#define USART2
(USART2) Base Address
Definition: same70n19.h:548
volatile uint32_t lastUsedRx
Definition: d_usartDMA.c:63
#define XDMAC_GE_EN0
(XDMAC_GE) XDMAC Channel 0 Enable Bit
volatile uint8_t * end
Definition: d_usartDMA.c:43
COMPILER_WORD_ALIGNED volatile lld_view0 lld_spi_noData[DMA_LLD_COUNT]
Definition: d_usartDMA.c:54
#define XDMAC_UBC_NVIEW_NDV0
dmaBuffer_rx_t dmaRx
Definition: d_usartDMA.c:91
uint32_t usartTxTHR
Definition: d_usartDMA.c:78
#define XDMAC_PERID_UART0_RX
Definition: d_dma.h:72
#define XDMAC_CC_MBSIZE_SINGLE
(XDMAC_CC) The memory burst size is set to one.
#define UART4
(UART4 ) Base Address
Definition: same70n19.h:585
int serRxUsed(int serialNum)
Returns number of bytes used in Rx buffer.
Definition: d_usartDMA.c:301
#define DCACHE_CLEAN_INVALIDATE_MEMCPY(dst, src, size)
Definition: d_dma.h:40
#define Assert(expr)
This macro is used to test fatal errors.
Definition: compiler.h:196
#define XDMAC_CIM_BIM
(XDMAC_CIM) End of Block Interrupt Mask Bit
#define XDMAC_PERID_UART3_RX
Definition: d_dma.h:78
#define XDMAC_CC_DWIDTH_BYTE
(XDMAC_CC) The data size is set to 8 bits
volatile uint8_t * end
Definition: d_usartDMA.c:68
__IO uint32_t XDMAC_CNDA
(XdmacChid Offset: 0x18) Channel Next Descriptor Address Register
uint8_t isUsartNotUart
Definition: d_usartDMA.c:82
void UART4_Handler(void)
Definition: d_usartDMA.c:1645
#define XDMAC_PERID_UART1_TX
Definition: d_dma.h:73
#define US_CR_RSTSTA
(US_CR) Reset Status Bits
#define ID_USART2
USART 2 (USART2)
Definition: same70n19.h:445
volatile uint32_t timestampRx
Definition: d_usartDMA.c:64
#define UART2
(UART2 ) Base Address
Definition: same70j19.h:539
int serWrite(int serialNum, const unsigned char *buf, int size)
Write data on USART. Returns number of bytes written.
Definition: d_usartDMA.c:443
#define ID_UART4
UART 4 (UART4)
Definition: same70n19.h:469


inertial_sense_ros
Author(s):
autogenerated on Sun Feb 28 2021 03:17:57