I'm looking for sample code to service the USCI (UART) on an MSP430 via DMA not interrupts

StackOverflow https://stackoverflow.com/questions/20505956

  •  31-08-2022
  •  | 
  •  

I have code that works "ok" for reading the USCI (UART) via interrupts, but the TI SimpliciTI stack is a CPU hog and it drops UART bytes when servicing the radio.

I assume DMA is the way to go, but I couldn't find a full example of DMA using USCI as input.

有帮助吗?

解决方案

Here's what I ended up doing. It works!

struct {
#ifndef USE_DMA
    volatile uint8_t rx_head  ;
#endif
    volatile uint8_t rx_tail  ;
    uint8_t rx_buffer[128];
} uart = { 0,0};


void UART_Init(void) 
{
#ifndef USE_DMA
   uart.rx_head = 0;
#endif
   uart.rx_tail = 0;


  WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT

  PMAPPWD = 0x02D52;                        // Get write-access to port mapping regs
  P1MAP5 = PM_UCA0RXD;                      // Map UCA0RXD output to P1.5
  P1MAP6 = PM_UCA0TXD;                      // Map UCA0TXD output to P1.6
  PMAPPWD = 0;                              // Lock port mapping registers

  P1DIR |= BIT6;                            // Set P1.6 as TX output
  P1SEL |= BIT5 + BIT6;                     // Select P1.5 & P1.6 to UART function

  UCA0CTL1 = UCSWRST;                      // **Put state machine in reset**
 #ifdef UART_9600
  UCA0CTL1 |= UCSSEL_1;                     // CLK = ACLK
  UCA0BR0 = 0x03;                           // 32kHz/9600=3.41 (see User's Guide)
  UCA0BR1 = 0x00;                           //
  UCA0MCTL = UCBRS_3+UCBRF_0;               // Modulation UCBRSx=3, UCBRFx=0
 #elif defined(UART_9600_SMCLK)
  UCA0CTL1 |= UCSSEL_2;                     // SMCLK
  UCA0BR0 = 0xE2;                           // 12MHz/12500
  UCA0BR1 = 0x04;                           //
  UCA0MCTL = UCBRS_2+UCBRF_0;               // Modulation UCBRSx=3, UCBRFx=0
 #elif defined(UART_115200)
  UCA0CTL1 |= UCSSEL_2;                     // SMCLK
  UCA0BR0 = 104;                            // 12MHz/115200
  UCA0BR1 = 0;                              //
  UCA0MCTL = UCBRS_1 + UCBRF_0;            // Modulation UCBRSx=1, UCBRFx=0
 #else
 #error Please select one of the supported baudrates.
#endif
  UCA0CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**

#ifdef USE_DMA
  memset(uart.rx_buffer,0,sizeof(uart.rx_buffer));
  DMACTL0 = DMA0TSEL_16;               // USCIA0 RX trigger
  DMA0SAL = (uint16_t)  &UCA0RXBUF;    // Source address
  DMA0DAL = (uint16_t) uart.rx_buffer; // Destination address
  DMA0SZ = sizeof(uart.rx_buffer);     // Block size. this counts down to 0, then reloads.
  DMA0CTL = DMADSTINCR_3 + DMASBDB + DMADT_4 + DMALEVEL;
  DMA0CTL |= DMAEN;
#else
  UCA0IE |= UCRXIE;                         // Enable USCI_A0 RX interrupt
#endif
}


int UART_GetChar(void)
{
#ifdef USE_DMA
  if (DMA0SZ + uart.rx_tail != sizeof(uart.rx_buffer))
#else
  if  (  uart.rx_head != uart.rx_tail )
#endif
    {
      int c;
      c = uart.rx_buffer[uart.rx_tail];
      uint8_t next = uart.rx_tail + 1;
      if (next >= sizeof(uart.rx_buffer)) next = 0;
      uart.rx_tail = next;
      return c;
    }

return -1;
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top