DMA with UART0

キャンセル
次の結果を表示 
表示  限定  | 次の代わりに検索 
もしかして: 

DMA with UART0

1,141件の閲覧回数
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Scribe on Mon Sep 24 07:12:53 MST 2012
Hi guys,

I'm attempting to configure DMA with UART0, however, when receiving a byte, only UART interrupts are triggering to tell me I have data ready and these continue to trigger, whilst DMA interrupts aren't and there's no sign of data moving into my buffers. My DMA code is below, any suggestions where I may have gone wrong in the setup? I have enabled DMA in LPC_UART0->FCR.

typedef struct
{
uint32_t sourceEndPointer;
uint32_t destinationEndPointer;
uint32_t channelControlData;
uint32_t unused;
} DMA_ChannelControlStructure;

DMA_ChannelControlStructure dmaChannel0 __attribute__((at(0x10000400)));
DMA_ChannelControlStructure dmaChannel1 __attribute__((at(0x10000410)));

uint8_t UARTTXBuffer[256];
uint8_t UARTRXBuffer[256];

void configureDMA()
{
// Disable interrupts
NVIC_DisableIRQ( DMA_IRQn );

// Reset the DMA peripheral
LPC_SYSCON->PRESETCTRL &= ~(1 << 10);
LPC_SYSCON->PRESETCTRL |= (1 << 10);

// Enable DMA peripheral clock at the rate of the AHB clock
LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 17);

LPC_DMA->CTRL_BASE_PTR = (uint32_t)(&dmaChannel0) & 0xFFFFFF00; // Point DMA control to the dmaChannel1 structure 

uint32_t cfg = (1UL << 0) |// Enable the DMA controller
 (0UL << 5) |// Enable user access control
 (0UL << 6); // Configure as non-bufferable

LPC_DMA->CFG = cfg;

// Wait for the DMA controller to start-up
while( !(LPC_DMA->STATUS & 0x01) );

// Disable all channels and clear any bus error
LPC_DMA->CHNL_ENABLE_CLR = 0x01FFFFF;
LPC_DMA->ERR_CLR = 0x01;

// Configure DMA channel 0 (UART0 TX)
dmaChannel0.sourceEndPointer = (uint32_t)UARTTXBuffer + sizeof(UARTTXBuffer) - 1;
dmaChannel0.destinationEndPointer = 0x4000C000;
dmaChannel0.channelControlData = (1UL << 0 )  |// Use basic DMA transfer mode
 (0UL << 3 )  |// Disable next burst
 (0UL << 4 )  |// 1 DMA transfer per cycle
 (0UL << 14 ) |// Rearbitrate the DMA cycle every transfer
 (0UL << 18 ) |// No AHB read protection
 (0UL << 21 ) |// No AHB write protection
 (0UL << 24 ) |// Source data size is in bytes
 (0UL << 26 ) |// Set the source address increment by 1 byte
 (0UL << 28 ) |// Destination data size is in bytes
 (3UL << 30 );// Set the destination address to not increment
 
// Configure DMA channel 1 (UART0 RX) 
dmaChannel1.sourceEndPointer = 0x40008000;
dmaChannel1.destinationEndPointer = (uint32_t)UARTRXBuffer + sizeof(UARTRXBuffer) - 1;
dmaChannel1.channelControlData = (1UL << 0 )   |// Use basic DMA transfer mode
 (0UL << 3 )   |// Disable next burst
 (255UL << 4 ) |// 256 DMA transfers per cycle
 (3UL << 14 )  |// Rearbitrate the DMA cycle every 8 transfers
 (0UL << 18 )  |// No AHB read protection
 (0UL << 21 )  |// No AHB write protection
 (0UL << 24 )  |// Source data size is in bytes
 (3UL << 26 )  |// Set the source address to not increment
 (0UL << 28 )  |// Destination data size is in bytes
 (0UL << 30 );// Set the destination address increment by 1 byte

LPC_DMA->CHNL_ENABLE_SET = (1UL << 0) |// Enable DMA channel 1
 (1UL << 1);// Enable DMA channel 2
  
// Enable interrupts
NVIC_EnableIRQ( DMA_IRQn );

LPC_DMA->CHNL_IRQ_ENABLE = (1UL << 0) |// Enable IRQ Done for DMA channel 1
 (1UL << 1);// Enable IRQ Done for DMA channel 2
}


Many thanks for any advice.
ラベル(1)
0 件の賞賛
返信
2 返答(返信)

1,078件の閲覧回数
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Scribe on Tue Sep 25 02:03:50 MST 2012
Problem resolved,

For dmaChannel0.destinationEndPointer I used the value 0x4000C000 when it should have been 0x40008000.

For reference for anyone wishing to use DMA who doesn't like NXP's overly incumbent drivers, with this change the code works perfectly.
0 件の賞賛
返信

1,078件の閲覧回数
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Scribe on Mon Sep 24 07:18:28 MST 2012
Yuk, I'll try that again with a different tag:

<pre>
typedef struct
{
uint32_t sourceEndPointer;
uint32_t destinationEndPointer;
uint32_t channelControlData;
uint32_t unused;
} DMA_ChannelControlStructure;

DMA_ChannelControlStructure dmaChannel0 __attribute__((at(0x10000400)));
DMA_ChannelControlStructure dmaChannel1 __attribute__((at(0x10000410)));

uint8_t UARTTXBuffer[256];
uint8_t UARTRXBuffer[256];

void configureDMA()
{
// Disable interrupts
NVIC_DisableIRQ( DMA_IRQn );

// Reset the DMA peripheral
LPC_SYSCON->PRESETCTRL &= ~(1 << 10);
LPC_SYSCON->PRESETCTRL |= (1 << 10);

// Enable DMA peripheral clock at the rate of the AHB clock
LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 17);

LPC_DMA->CTRL_BASE_PTR = (uint32_t)(&dmaChannel0) & 0xFFFFFF00; // Point DMA control to the dmaChannel1 structure

uint32_t cfg = (1UL << 0) |// Enable the DMA controller
       (0UL << 5) |// Enable user access control
       (0UL << 6); // Configure as non-bufferable

LPC_DMA->CFG = cfg;

// Wait for the DMA controller to start-up
while( !(LPC_DMA->STATUS & 0x01) );

// Disable all channels and clear any bus error
LPC_DMA->CHNL_ENABLE_CLR = 0x01FFFFF;
LPC_DMA->ERR_CLR = 0x01;

// Configure DMA channel 0 (UART0 TX)
dmaChannel0.sourceEndPointer = (uint32_t)UARTTXBuffer + sizeof(UARTTXBuffer) - 1;
dmaChannel0.destinationEndPointer = 0x4000C000;
dmaChannel0.channelControlData = (1UL << 0 )  |// Use basic DMA transfer mode
(0UL << 3 )  |// Disable next burst
(0UL << 4 )  |// 1 DMA transfer per cycle
(0UL << 14 ) |// Rearbitrate the DMA cycle every transfer
(0UL << 18 ) |// No AHB read protection
(0UL << 21 ) |// No AHB write protection
(0UL << 24 ) |// Source data size is in bytes
(0UL << 26 ) |// Set the source address increment by 1 byte
(0UL << 28 ) |// Destination data size is in bytes
(3UL << 30 );// Set the destination address to not increment

// Configure DMA channel 1 (UART0 RX)
dmaChannel1.sourceEndPointer = 0x40008000;
dmaChannel1.destinationEndPointer = (uint32_t)UARTRXBuffer + sizeof(UARTRXBuffer) - 1;
dmaChannel1.channelControlData = (1UL << 0 )   |// Use basic DMA transfer mode
(0UL << 3 )   |// Disable next burst
(255UL << 4 ) |// 256 DMA transfers per cycle
(3UL << 14 )  |// Rearbitrate the DMA cycle every 8 transfers
(0UL << 18 )  |// No AHB read protection
(0UL << 21 )  |// No AHB write protection
(0UL << 24 )  |// Source data size is in bytes
(3UL << 26 )  |// Set the source address to not increment
(0UL << 28 )  |// Destination data size is in bytes
(0UL << 30 );// Set the destination address increment by 1 byte

LPC_DMA->CHNL_ENABLE_SET = (1UL << 0) |// Enable DMA channel 1
   (1UL << 1);// Enable DMA channel 2
 
// Enable interrupts
NVIC_EnableIRQ( DMA_IRQn );

LPC_DMA->CHNL_IRQ_ENABLE = (1UL << 0) |// Enable IRQ Done for DMA channel 1
   (1UL << 1);// Enable IRQ Done for DMA channel 2
}
</pre>
0 件の賞賛
返信