Datos de lectura no válidos cuando se usa DMA para SPI con flash

0

Para leer 100 bytes de SPI flash, necesito enviar comandos de 5 bytes y 100 bytes de escritura ficticia. Configuré 2 canales DMA para enviar 105 bytes y 3 canales para recibir 105 bytes respectivamente. Se incluyen la recepción de interrupción (IRQ_RX) y la transmisión (IRQ_TX). Cuando se inicializa el DMA, levanto el flash CS y, en el controlador IRQ_TX, elimino CS. El problema es que el indicador de desbordamiento USART-ORE se activa y los datos en el búfer de recepción dejan de ser válidos. A veces la basura puede estar en los primeros bytes, pero más a menudo en los últimos bytes. A veces, todo el búfer está completamente lleno con 0xFF: este es el valor de la línea RX por defecto o por algún byte desde el flash. No puedo entender lo que pasa. Pero hay una característica especial cuando ejecuto el código con puntos de interrupción que solo en IRQ_RX los datos son válidos. Además, los datos son válidos si escribo no a través de DMA, sino directamente en el registro a través de for or while y tengo una interrupción en TX deshabilitada. También me di cuenta de que IRQ_TX se llama antes de IRQ_RX y, por lo general, ya está en IRQ_TX. Veo ORE = 1. Si el DMA en ese momento no llenó todo el búfer, entonces la basura comienza desde el byte actual. ¿Qué puede causar este comportamiento del receptor?

/*=== F2MC-16FX MB96600 Series ===*/

uint8_t rx_buf[200]; //read here
uint8_t tx_buf[200]; //from here we write, the first 5 bytes of the command

void USART_read()
{
//init DMA read
if(UART2_SSR2_RDRF==0)
    UART2_ESIR2_RDRF=0; //clear RDRF

DSR_DTE3 = 0x0; //Clear possible DMA 3 request
DER_EN3 = 0x0; //DMA 3 disable
DISEL3 = _IRQ_LINR2; //< LIN USART 3 RX
DCT3 = 105;
IOA3 = (unsigned long)&UART2_RDR2;
DMACS3 = 0x10; //no IOA update, BAP update, byte transfer, IOA -> BAP
BAPH3 =  &rx_buf[0] >> 16;
BAPM3 =  &rx_buf[0] >> 8;
BAPL3 =  &rx_buf[0] & 0xFF;
DER_EN3 = 1; // DMA 3 enable
UART2_SSR2_RIE = 1; // RX interrupt enabled (for DMA)

//init DMA send
if(UART2_SSR2_TDRE==0)
    UART2_ESIR2_TDRE=0; 

DSR_DTE2 = 0x0; //Clear possible DMA 0 request
DER_EN2 = 0x0; //DMA 1 disable
DISEL2 = _IRQ_LINT2; //< LIN USART 2 TX
DCT2 = 105;
IOA3 = (unsigned long)&UART2_TDR2;
DMACS3 = 0x12; //no IOA update, BAP update, byte transfer, BAP -> IOA
BAPH3 = &tx_buf[0] >> 16;
BAPM3 = &tx_buf[0] >> 8;
BAPL3 = &tx_buf[0] & 0xFF;
DER_EN3 = 1; // DMA 2 enable
UART2_SSR2_TIE = 1; // TX interrupt enabled (for DMA)

FLASH_CS = FLASH_ON;
}

//_IRQ_LINR2
void IRQ_RX(void)
{
UART2_SSR2_RIE=0;
DSR_DTE3 = 0x0;
FLASH_CS = FLASH_OFF;

if(/**/)
    USART_read();
}

//_IRQ_LINT2
void IRQ_TX(void)
{
//clear
UART2_SSR2_TIE=0;
DSR_DTE2 = 0x0;
/*no operation instruction*/
}
    
pregunta avg33

0 respuestas

Lea otras preguntas en las etiquetas