Hi Jorge,
Thanks for the support. I have tried and I am not getting the expected result. I reduced the code to bare minimum. It is listed below. In it, I just use LPUART0 in place of I2S. It is set to 115200 BAUD. It can be easily reproduced using any Freedom boards. I am using FRDM-K22. I am using MCUxpresso V10.0.2_411 with recent SDK for K22 (SDK_2.2_MK22FN512xxx12.zip, Build Date: 2017-07-06).
Start a bare metal "Hello World" empty project. Add the subroutine code below. Add a call to the subroutine after printf("Hello World\n") in main(). Once the code is built and run, in a Terminal program, just type "0", "1", "0", "1",.... The idea is have 0x30, 0x31, 0x30, 0x31, .... separated into different blocks.
Also shown below is the memory browser of the DMA buffer. In 1st location (0x2000 0400) is 0x00000830, which is char "0". A block away at 0x2000 0440, it has 0x00001000, not the expected 0x00000831 (char "1"). Further, all other locations are 0. In other words, the DMA keeps dumping the received characters in the first location of the two blocks.
Anything you can see that I am not doing correctly??
Jei
/* TODO: insert other definitions and declarations here. */
#define DMA_SIZE 32 // DMA size
__attribute__ ((aligned( 1024 ))) int32_t m_iDmaBuf[ DMA_SIZE ]; // 32*4 = 128B
void Init_and_Start_DMA_on_LPUART0( void )
{
int i = 0 ;
for ( i = 0; i < DMA_SIZE; i++ ) m_iDmaBuf[ i ] = 0;
SIM->SOPT2 |= SIM_SOPT2_LPUARTSRC( 1 ) | SIM_SOPT2_PLLFLLSEL( 3 ); // LPUART0 uses MCGPLLCLK off IRC48M
SIM->SCGC5 |= SIM_SCGC5_PORTC_MASK | SIM_SCGC5_PORTD_MASK; // Clock to GPIO ports C & D
SIM->SCGC6 |= SIM_SCGC6_DMAMUX_MASK | SIM_SCGC6_LPUART0_MASK; // Clock to LPUART0, DMAMUX
SIM->SCGC7 |= SIM_SCGC7_DMA_MASK; // Clock to DMA
// Init LPUART0 pins (debug port)...
PORTC->PCR[ 3 ] = PORT_PCR_MUX( 7 ); // This pin as LPUART0 Rx, FRDM-K22 J1-14
PORTC->PCR[ 4 ] = PORT_PCR_MUX( 7 ); // This pin as LPUART0 Tx, FRDM-K22 J24-9
// Initialize LPUART0 for 115200 BAUD
LPUART0->BAUD &= ~LPUART_BAUD_SBR_MASK; // SBR bits is not 0 by default
LPUART0->BAUD |= LPUART_BAUD_SBR( 26 ); // 48M/115200/16 = 26.0416666
LPUART0->BAUD |= LPUART_BAUD_RDMAE_MASK; // Enable RX DMA
LPUART0->CTRL |= LPUART_CTRL_TE_MASK | LPUART_CTRL_RE_MASK; // Enable tx/rx
// Initialize DMA
DMA0->TCD[ 0 ].SADDR = (uint32_t) &LPUART0->DATA; // LPUART0's DATA register
DMA0->TCD[ 0 ].SOFF = 0; // Src addr doesn't change
DMA0->TCD[ 0 ].SLAST = 0; // Src addr doens't change
DMA0->TCD[ 0 ].ATTR = DMA_ATTR_SSIZE( 2 ) | DMA_ATTR_DSIZE( 2 ); // 32-bit src & dst
DMA0->TCD[ 0 ].DADDR = (uint32_t) &m_iDmaBuf[ 0 ]; // Dst addr
DMA0->TCD[ 0 ].DOFF = ( DMA_SIZE / 2 ) * 4; // Dst addr changed to a block away after xfer; This separate L & R data to separate blocks
DMA0->TCD[ 0 ].NBYTES_MLOFFYES = \
DMA_NBYTES_MLOFFYES_MLOFF( -( DMA_SIZE / 2 ) * 4 * 2 - 4 ) | \
DMA_NBYTES_MLOFFYES_NBYTES( 2 * 4 );
DMA0->TCD[ 0 ].CITER_ELINKNO = DMA_SIZE; // # xfer
DMA0->TCD[ 0 ].DLAST_SGA = 0; // After major loop completed (n xfers), go back to &m_iDmaBuf[ 0 ]
DMA0->TCD[ 0 ].BITER_ELINKNO = DMA_SIZE; // # xfer
DMA0->TCD[ 0 ].CSR = 0; // Leave ERQ set after done w/ DMA block; no int
DMAMUX->CHCFG[ 0 ] = DMAMUX_CHCFG_ENBL_MASK | DMAMUX_CHCFG_SOURCE( 58 ); // DMA_CH_REQ_LPUART0_RX
DMA0->ERQ |= DMA_ERQ_ERQ0_MASK; // Enable DMA CH0; DMA never stop
}
