Uso DMA para leer con SPI flash usando USART. MCU - maestro, flash - esclavo. Leí 1029 bytes por transacción. Algoritmo de intercambio:
- Activo el flash (CS = 0)
- Configuré el canal DMA para recibir 1029 bytes. Permitir la interrupción de lectura de IRQ_RX
- Configuré otro canal DMA para transmitir 1029 bytes. Permitir la interrupción de IRQ_TX, habilitar el canal, en este momento enviar / recibir
- En el controlador IRQ_TX, borre el indicador de habilitación de interrupción
- En el controlador IRQ_RX, borro el indicador de activación de interrupción + desactivo el flash (CS = 1)
Funciona. Pero muy raramente hay un error cuando envío 1029 bytes, pero solo se recibe 1028. En el depurador, veo que el contador de DMA enviado bytes es 0 (enviado 1029), y el contador leído es 1 (hasta 1028). Como DMA no recibió el último byte, la interrupción de RX no se produce y no puedo ingresar al controlador de interrupciones de RX. Se llama al manejador de interrupciones TX, es decir, 1029 bytes se envían con precisión. Las banderas de error son cero. Este error ocurre raramente. ¿Por qué no recibo el último byte, qué podría estar mal?
MCU - Serie F2MC-16FX MB96600. IDE Softune Workbench
void USART_start_DMA_read(void)
{
/* correct size_pic and address */
//INIT DMA FOR READ
if(UART2_SSR2_RDRF==0)
UART2_ESIR2_RDRF=0; //clear RDRF - Reception data register full
DSR_DTE2 = 0x0; //Clear possible DMA 2 request
DER_EN2 = 0x0; //DMA 2 channel disable
DISEL2 = _IRQ_LINR2; //< LIN USART 2 RX
DCT2 = 1029; //how much to read
IOA2 = (unsigned long)&UART2_RDR2;
DMACS2 = 0x10; //no IOA update, BAP update, byte transfer, IOA -> BAP
BAPH2 = (unsigned long) &graph_buf[beg_byte] >> 16;
BAPM2 = (unsigned long) &graph_buf[beg_byte] >> 8;
BAPL2 = (unsigned long) &graph_buf[beg_byte] & 0xFF;
DER_EN2 = 1; // DMA 2 channel enable
UART2_SSR2_RIE = 1; //enable irq RX - at this point the channel is ready to receive bytes
FLASH_CS = FLASH_ON; //enable flash
//INIT DMA FOR SEND
if(UART2_SSR2_TDRE==0)
UART2_ESIR2_TDRE=0; //clear TDRF - Transmit data register full
DSR_DTE3 = 0x0; //Clear possible DMA 3 request
DER_EN3 = 0x0; //DMA 3 channel disable
DISEL3 = _IRQ_LINT2; //< LIN USART 2 TX
DCT3 = DCT2; //how much to send
IOA3 = (unsigned long)&UART2_TDR2;
DMACS3 = 0x12; //no IOA update, BAP update, byte transfer, BAP -> IOA
BAPH3 = (unsigned long) &read_flash_cmd[0] >> 16;
BAPM3 = (unsigned long) &read_flash_cmd[0] >> 8;
BAPL3 = ((unsigned long) &read_flash_cmd[0] & 0xFF);
DER_EN3 = 1; // DMA 3 channel enable
UART2_SSR2_TIE = 1; //enable irq TX - at this point the transmission / reading starts
}
void IRQ_USART2_TX()
{
//after transferring 1029 bytes
UART2_SSR2_TIE=0; //disable irq TX
DSR_DTE3 = 0x0; //clear DMA channel request
__wait_nop();
__wait_nop();
__wait_nop();
__wait_nop();
__wait_nop();
}
void IRQ_USART2_RX(void)
{
//after reading 1029 bytes
FLASH_CS = FLASH_OFF; //disable flash
UART2_SSR2_RIE = 0; //disable irq RX
DSR_DTE2 = 0x0; //clear DMA channel request
//if not the entire object is read - read the following data block
if(size_pic)
{
USART_start_DMA_read();
}
}
Actualizado. Se produce un error si ejecuto el firmware a través del depurador. Si corro sin depurador, todo funciona sin fallos. ¿Qué piensas, puede el depurador afectar el trabajo?