Other Parts Discussed in Thread: CC2530
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