Hello,
I'm developing test codes for custom CC2530 PCB and I faced problems with configuring UART to work in DMA configuration. I used directly DN112 document example (with small modifications). Pooling and ISR works fine but I cannot get DMA working.
Below I attached a complete source code:
typedef struct { unsigned char START : 1; unsigned char STOP : 1; unsigned char SPB : 1; unsigned char PARITY : 1; unsigned char BIT9 : 1; unsigned char D9 : 1; unsigned char FLOW : 1; unsigned char ORDER : 1; } UART_PROT_CONFIG; typedef struct { unsigned char SRCADDRH; unsigned char SRCADDRL; unsigned char DESTADDRH; unsigned char DESTADDRL; unsigned char VLEN : 3; unsigned char LENH : 5; unsigned char LENL : 8; unsigned char WORDSIZE : 1; unsigned char TMODE : 2; unsigned char TRIG : 5; unsigned char SRCINC : 2; unsigned char DESTINC : 2; unsigned char IRQMASK : 1; unsigned char M8 : 1; unsigned char PRIORITY : 2; } DMA_DESC; void uartMapPort(unsigned char uartPortAlt, unsigned char uartNum) { if (uartPortAlt == 1) { if (uartNum == 0) { PERCFG &= ~0x01; P0SEL |= 0x3C; P1SEL &= ~0x3C; } else { PERCFG &= ~0x02; P0SEL |= 0x3C; P1SEL &= ~0xF0; } } else { if (uartNum == 0) { PERCFG |= 0x01; P1SEL |= 0x3C; P0SEL &= ~0x3C; } else { PERCFG |= 0x02; P1SEL |= 0xF0; P0SEL &= ~0x3C; } } } void uartInitBitrate(unsigned char uartBaudM, unsigned char uartBaudE) { unsigned int i; SLEEPCMD &= ~OSC_PD; /* turn on 16MHz RC and 32MHz XOSC */ \ while (!(SLEEPSTA & XOSC_STB)); /* wait for 32MHz XOSC stable */ \ asm("NOP"); /* chip bug workaround */ \ for (i=0; i<504; i++) asm("NOP"); /* Require 63us delay for all revs */ \ CLKCONCMD = (CLKCONCMD_32MHZ | OSC_32KHZ); /* Select 32MHz XOSC and the source for 32K clock */ \ while (CLKCONSTA != (CLKCONCMD_32MHZ | OSC_32KHZ)); /* Wait for the change to be effective */ \ SLEEPCMD |= OSC_PD; /* turn off 16MHz RC */ U0BAUD = uartBaudM; U0GCR = (U0GCR & ~0x1F) | uartBaudE; U1BAUD = uartBaudM; U1GCR = (U1GCR & ~0x1F) | uartBaudE; } void uartConfig(unsigned char uartNum, UART_PROT_CONFIG config) { if (uartNum == 0) { U0CSR |= 0x80; U0UCR = (U0UCR & ~0x01) | config.START; U0UCR = (U0UCR & ~0x02) | (config.STOP << 1); U0UCR = (U0UCR & ~0x04) | (config.SPB << 2); U0UCR = (U0UCR & ~0x08) | (config.PARITY << 3); U0UCR = (U0UCR & ~0x10) | (config.BIT9 << 4); U0UCR = (U0UCR & ~0x20) | (config.D9 << 5); U0UCR = (U0UCR & ~0x40) | (config.FLOW << 6); U0GCR = (U0GCR & ~0x20) | (config.ORDER << 5); } else { U1CSR |= 0x80; U1UCR = (U1UCR & ~0x01) | config.START; U1UCR = (U1UCR & ~0x02) | (config.STOP << 1); U1UCR = (U1UCR & ~0x04) | (config.SPB << 2); U1UCR = (U1UCR & ~0x08) | (config.PARITY << 3); U1UCR = (U1UCR & ~0x10) | (config.BIT9 << 4); U1UCR = (U1UCR & ~0x20) | (config.D9 << 5); U1UCR = (U1UCR & ~0x40) | (config.FLOW << 6); U1GCR = (U1GCR & ~0x20) | (config.ORDER << 5); } } void uartStartRxForDma(unsigned char uartNum, DMA_DESC * uartDmaRxDescr, unsigned char uartDmaRxChan, unsigned short __xdata * uartRxBuf, unsigned char uartRxBufSize) { uartDmaRxDescr->SRCADDRH = 0xDF; uartDmaRxDescr->SRCADDRL = (uartNum == 0) ? 0xC1 : 0xF9; uartDmaRxDescr->DESTADDRH = (unsigned short) uartRxBuf >> 8; uartDmaRxDescr->DESTADDRL = (unsigned short) uartRxBuf; uartDmaRxDescr->LENH = (uartRxBufSize >> 8) & 0xFF; uartDmaRxDescr->LENL = uartRxBufSize & 0xFF; uartDmaRxDescr->VLEN = 0x00; uartDmaRxDescr->WORDSIZE = 0x00; uartDmaRxDescr->TMODE = 0x00; uartDmaRxDescr->TRIG = 14 + (2 * uartNum); uartDmaRxDescr->SRCINC = 0x00; uartDmaRxDescr->DESTINC = 0x00; uartDmaRxDescr->IRQMASK = 0x01; uartDmaRxDescr->M8 = 0x00; uartDmaRxDescr->PRIORITY = 0x02; if (uartDmaRxChan == 0) { DMA0CFGH = (unsigned char) ((unsigned short) uartDmaRxDescr >> 8); DMA0CFGL = (unsigned char) ((unsigned short) uartDmaRxDescr & 0x00FF); } else { DMA1CFGH = (unsigned char) ((unsigned short) uartDmaRxDescr >> 8); DMA1CFGL = (unsigned char) ((unsigned short) uartDmaRxDescr & 0x00FF); } DMAARM = ((1 << uartDmaRxChan) & 0x1F); asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP"); asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP"); asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP"); asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP"); asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP"); asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP"); asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP"); asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP"); asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP"); IEN0 |= 0x80; IEN1 |= 0x01; IRCON &= ~0x01; if (uartNum == 0) { U0CSR |= 0x40; } else { U1CSR |= 0x40; } } DMA_DESC uartDmaRxTxCh0[1]; DMA_DESC uartDmaRxTxCh1[4]; unsigned char byte1 = 'a'; unsigned char byte2 = 'b'; unsigned short __xdata data[2]; #pragma vector=DMA_VECTOR __interrupt void DMA_ISR(void) { IRCON &= ~0x01; if (DMAIRQ & 0x01) { DMAIRQ &= ~0x01; DMAARM |= 0x01; } } int main(void) { unsigned int delay; unsigned int delay2; // Set P1.0 of CC2530 as output // Set P1.1 of CC2530 as output P1DIR |= 0x03; // Green diode ON P1_0 ^= 1; //------------------------------------------------- // Baud rate: 9600 // Data: 8-bit // Parity: none // Stop: 1-bit // Flow control: NONE //------------------------------------------------- UART_PROT_CONFIG config; config.START = 0; config.STOP = 1; config.SPB = 0; config.PARITY = 0; config.BIT9 = 0; config.D9 = 0; config.FLOW = 0; config.ORDER = 0; uartInitBitrate(59, 8); // Configure UART 1 // UART 1 Alt.1 location // RX: P0.2 // TX: P0.3 uartMapPort(1, 0); uartConfig(0, config); P2SEL &= ~(1 << 6); // UART 1 priority over UART 2 P2SEL &= ~(1 << 3); // UART 1 priority over Timer 1 // Configure UART 2 // RX: P0.5 // TX: P0.4 // UART 2 Alt.1 location uartMapPort(1, 1); uartConfig(1, config); P2SEL &= ~(1 << 5); // UART 2 priority over Timer 3 // Priority: UART0 > UART 1 > TImer 1 P2DIR &= ~(0x01 << 7); P2DIR &= ~(0x01 << 6); EA = 1; uartStartRxForDma(0, uartDmaRxTxCh0, 0, data, 1); uartStartRxForDma(1, uartDmaRxTxCh1, 1, data + 1, 1); while (1) { // Negate diodes state P1_0 ^= 1; P1_1 ^= 1; // Send one byte1 over UART 1 U0DBUF = data[0]; while (!UTX0IF); UTX0IF = 0; // Send one byte2 over UART 2 U1DBUF = data[1]; while (!UTX1IF); UTX1IF = 0; for ( delay = 0; delay < 2; delay++) for ( delay2 = 0; delay2 < 50000; delay2++); } }
Could anyone tell me what I'm doing wrong? I want to make this code running in both ways... TX (without DMA) and RX (with DMA) but I tried almost everything. DOcumentation or DN112 document don't help me anymore.
Any help will be appreciated!
Thank you in advance.
Best regards,
Lukasz Spas