0

I have code written by someone else (for a dsPIC33FJ128MC706A) - which initializes UART1 & PWMs and uses a busy wait in the U1Rx interrupt to get 14 bytes, and timer1 interrupts to update PWM registers if new data arrives (debugged - it enters the _U1RXInterrupt when data is sent)

I tried modifying it to use DMA instead of busy wait. I changed nothing in the initialization, but called the following function after initialization of UART:

unsigned char    received_data1 [0x0f] __attribute__((space(dma)));
unsigned char    received_data2 [0x0f] __attribute__((space(dma)));
void dma_init(void)
{
    DMA0REQ = 0x000b; // IRQSEL = 0b0001011 (UART1RX))
    DMA0PAD = (volatile unsigned int) &U1RXREG;
    

    DMA0STA = __builtin_dmaoffset(received_data1);
    DMA0STB = __builtin_dmaoffset(received_data2);
    DMA0CNT = 0xe;//15 bytes in
    DMA0CON = 0x0002; //continuous ping-pong + post-increment
    IFS0bits.DMA0IF = 0;
    IEC0bits.DMA0IE = 1;
    DMA0CONbits.CHEN = 1;
    
}

This is based on example 22-10 in the FRM with a few slight changes (UART1 receiver instead of UART2). I can't seem to find other examples that don't use library functions (which I didn't even know existed up until I came across those examples). (Also, to be consistent with the code I got, I put in _ISR after void instead of making interrupt an attribute, but that didn't change anything)

In the example, there was no interrupt for the UART1 receiver - but according to the FRM, it should be enabled. Made sense to me that I don't need to clear the interrupt flag myself (it would kind-of defeat the purpose of DMA if I needed to use the CPU for it).

And yet, when I send data, the breakpoint on DMA0Interrupt doesn't trigger, but the one on the default interrupt does, and I have PWMIF=1 and U1RXIF=1. I also tried commenting out the default ISR and adding a _U1ErrInterrupt even though examining the flags I didn't notice any error flags being raised, just the normal U1RXIF.

I don't understand why this would happen. I haven't changed the PWM code at all, and the PWM flag isn't raised in the original code when I place a breakpoint in the _U1RxInterrupt. I don't even understand how a DMA set-up could cause a PWM error.

The U1RXIF flag seems to be telling me the DMA didn't handle the incoming byte (I assume it's the DMA that clears the flag), which once again relates to the question "what did I do wrong in this DMA setup"

UART initialization code:

in a general initialization function (called by main())

    TRISFbits.TRISF2      = 1;            /* U1RX */
    TRISFbits.TRISF3      = 0;            /* U2TX */

also called by main:

void UART1_init_USB (void)
    {
        /* Fcy 7.3728 MHZ  */
    
        U1MODE      = 0x8400;       /* U1ATX Transmit status and control register */
        U1STA       = 0x2040;       /* Receve status and control register Transmit disabled*/
        U1BRG       = 0x000f;       /* Baund rate control register  115200 bps */
        
        IPC2bits.U1RXIP      = 3;   /* Receiver Interrupt Priority bits */
        IEC0bits.U1RXIE      = 1;   /* Enable RS232 interrupts */
        IFS0bits.U1RXIF      = 0;   
        
    }

(comments by original code author)

user1999728
  • 913
  • 1
  • 8
  • 25
  • 1
    There is an uart rx ISR in the example (`_U2EInterrupt`). It is triggered on a reception error. DMA has no clue how to deal with reception errors, and the CPU intervention is required. – user58697 Nov 15 '20 at 22:27
  • @user58697 I checked it last time but I wanted to get back to the lab to check this again: there are no error flag raised (unless I don't know how to look for them correctly). To test it, I commented out the default ISR, copied the `_U2ErrInterrupt` (changed to U1 ofc), did "clean and rebuild" and tried again... the breakpoint in the `_U1ErrInterrupt` didn't trigger. The device reset, as it did before I added the default ISR. – user1999728 Nov 16 '20 at 15:32

0 Answers0