This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

DMA & ADC/GIO Interrupts

Other Parts Discussed in Thread: RM48L952, MOTORWARE, DRV8301

I'm using the DMA module of RM48L952 CNCD to transfer data from SCI RX -from which I need to receive 5 packets of 8 bits of data in ~400k baudrate. It all works fine when I don't use ADC & GIO interrupts (which are the same as the motorware sensored foc example), but the moment I enable those interrupts, DMA starts to lose packets. I couldn't figure the problem myself and I'm still not sure what causes it. Any help will be greatly appreciated. Thanks

-Asa

  • Asa,

    I think that there is something wrong with your software and would suggest you taking following steps to debug the problem.

    (1) Set up timeline. How often do you expect the DMA, ADC, and GIO interrupts to occur? How long can you wait to respond to an interrupt after it occurs? How long each ISR would run? This would provide a picture if you can fit everything in time.

    (2) If you need to read SCI data continuously, I would suggest you using a double buffer mechanism with DMA autoinit enabled. For example, you can set up a DMA block transfer of 10 bytes with autoinit enabled. You also need to enable DMA HBC and BTC interrupts. When the first half block (5 bytes) is received, HBC interrupt will notify CPU to use the first 5 bytes of data. When the second half of the block is received, the BTC interrupt will notify CPU to processed the second half block. DMA will automatically restart to transfer data to the beginning of the buffer.

    Thanks and regards,

    Zhaohong

  • I disabled the GIO interrupts and reduced the number of ADC interrupts, but ADC interrupt triggers an important function essential for the code (the routine which runs the motor). It is basically the same code from the sensored foc example of the motorware. This is a periodic interrupt triggered by the HET module and runs for about 18 us (the interrupt period is 50 us). I assumed that even with such an interrupt, DMA could still transfer the data from SCI RX, but apparently this interrupt blocks either SCI or DMA related jobs. To provide more info, I'm initializing the SCI module with:

    void sciInit(void)
    {
        /** - bring SCI out of reset */
        sciREG->GCR0 = 1U;

        /** - Disable all interrupts */
        sciREG->CLRINT    = 0xFFFFFFFFU;
        sciREG->CLRINTLVL = 0xFFFFFFFFU;

        /** - global control 1 */
        sciREG->GCR1 = (0U << 25U)  /* enable transmit */
                      | (1U << 24U)  /* enable receive */
                      | (0U << 17)
                      | (1U << 5U)   /* internal clock (device has no clock pin) */
                      | (1U << 4U)  /* number of stop bits */
                      | (0U << 3U)  /* even parity, otherwise odd */
                      | (1U << 2U)  /* enable parity */
                      | (1U << 1U);  /* asynchronous timing mode */

        /** - set baudrate */
        sciREG->BRS = 12U;  /* baudrate */

        /** - transmission length */
        sciREG->FORMAT = 8U - 1U;  /* length */

        /** - set SCI pins functional mode */
        sciREG->FUN = (1U << 2U)  /* tx pin */
                     | (1U << 1U)  /* rx pin */
                     | (0U);  /* clk pin */

        /** - set SCI pins default output value */
        sciREG->DOUT = (0U << 2U)  /* tx pin */
                      | (0U << 1U)  /* rx pin */
                      | (0U);  /* clk pin */

        /** - set SCI pins output direction */
        sciREG->DIR = (0U << 2U)  /* tx pin */
                     | (0U << 1U)  /* rx pin */
                     | (0U);  /* clk pin */

        /** - set SCI pins open drain enable */
        sciREG->ODR = (0U << 2U)  /* tx pin */
                     | (0U << 1U)  /* rx pin */
                     | (0U);  /* clk pin */

        /** - set SCI pins pullup/pulldown enable */
        sciREG->PD = (0U << 2U)  /* tx pin */
                    | (0U << 1U)  /* rx pin */
                    | (0U);  /* clk pin */

        /** - set SCI pins pullup/pulldown select */
        sciREG->PSL = (1U << 2U)  /* tx pin */
                     | (1U << 1U)  /* rx pin */
                     | (1U);  /* clk pin */

        /** - set interrupt level */
        sciREG->SETINTLVL = (0U << 26U)  /* Framing error */
                           | (0U << 25U)  /* Overrun error */
                           | (0U << 24U)  /* Parity error */
                           | (0U << 9U)  /* Receive */
                           | (0U << 8U)  /* Transmit */
                           | (0U << 1U)  /* Wakeup */
                           | (0U);  /* Break detect */

        /** - set interrupt enable */
        sciREG->SETINT = (0U << 26U)  /* Framing error */
                        | (0U << 25U)  /* Overrun error */
                        | (0U << 24U)  /* Parity error */
                        | (1U << 18U)  /* SET RX DMA ALL */
                        | (1U << 17U)  /* SET RX DMA */
                        | (0U << 9U)  /* Receive */
                        | (0U << 1U)  /* Wakeup */
                        | (0U);  /* Break detect */

        /** - initialize global transfer variables */
        g_sciTransfer_t[0U].mode   = 0U << 8U;
        g_sciTransfer_t[0U].length = 0U;

        /** - Finaly start SCI */
        sciREG->GCR1 |= (1U << 7U);

    }

    initializing the DMA module with:

        dmaEnable();
        dmaReqAssign(DMA_CH0, 30);

        newDmaPacket.SADD      = 0xFFF7E534U;
        newDmaPacket.DADD      = (uint32_t)dest;
        newDmaPacket.CHCTRL    = 0;
        newDmaPacket.FRCNT     = 5;
        newDmaPacket.ELCNT     = 1;
        newDmaPacket.ELDOFFSET = 0; 
        newDmaPacket.ELSOFFSET = 0;
        newDmaPacket.FRDOFFSET = 0;
        newDmaPacket.FRSOFFSET = 0;
        newDmaPacket.PORTASGN  = 4;
        newDmaPacket.RDSIZE    = ACCESS_8_BIT;
        newDmaPacket.WRSIZE    = ACCESS_8_BIT;
        newDmaPacket.TTYPE     = FRAME_TRANSFER;
        newDmaPacket.ADDMODERD = ADDR_FIXED;
        newDmaPacket.ADDMODEWR = ADDR_INC1;
        newDmaPacket.AUTOINIT  = AUTOINIT_OFF;

        // Channel 30
        dmaSetCtrlPacket(DMA_CH0, newDmaPacket);
        dmaSetChEnable(DMA_CH0, DMA_HW);

    and I'm trying to receive the data with:

            if(dmaREG->HWCHENAS == 0)
            {
                dmaSetChEnable(DMA_CH0, DMA_HW);
                CheckSum = (RawData[0] + RawData[1] + RawData[2] + RawData[3] + RawData[4]);

                if(CheckSum == 0xFF)
                {
                   Data = (RawData[0] << 24)
                            | (RawData[1] << 16)
                            | (RawData[2] << 8)
                            | (0x00);
                }
            }

    As can be seen from the last code, the order of the 5 packets of 8 bits of data is quite important, but when I enable the ADC interrupt, DMA starts to lose packets, thus the order gets changed. I tried with and without software trigger and also auto-init, without any success.

  • Asaygl,

    From the SCI operation described in your first post and the DMA set up described in your last post. You have to restart DMA within 25 us after the previous block transfer is complete. Otherwise you will SCI data. From the DMA code you posted, it seems that you are polling the DMA status in the mainloop. It will cause problem because all interrupts will take priority.

    As I already said in my first reply, you need to analyze the maximum allowable processing delay for each event in your application and and arrange processing priority so that they can be handled in time. For example, with your DMA set up you have to serve DMA within 25 us ( time to receive one SCI data) after DMA complete transfer of 5 bytes. If this is the most critical part of processing, you need to serve the DMA in an interrupt with top priority. If you use the mechanism I suggested, the maximum allowable delay is increased to 125 us (time to receive 5 SCI data).

    Thanks and regards,

    Zhaohong

  • I'm using the multi-buffer mode SCI now and I'm checking the buffers which themselves lose the packets, with or without DMA. Is it right to say that the "ADC interrupt" blocks the SCI from transferring data from the RX port to its buffer, thus losing one (or more) packets. In other words, transferring data from the pin to the buffer requires CPU time which is not available at interrupts. Is there any way to use a continuous SCI data transfer method that can fill the buffers without the CPU, thus even at  different interrupts?

  • Asaygl,

    SCI and ADC operates independently. SCI operation is not blocked by any interrupts. The key issue you need to understand is that you need to read the SCI buffer fast enough so that the old data is not over written by new ones. the ping-pong buffer mechanism I proposed earlier is a typical method. You also should not perform intensive data processing in interrupt service routines. Instead, you can set a flag in ISR and poll the flag in the main loop.

    Thanks and regards,

    Zhaohong

  • I think I got the problem and it is not related to the interrupts: When I enable the motor controller via the gui->EnableFlg of the Motorware FOC Encoder example of the DRV8301 RM48 kit, I can see a periodic noise (much like the pwms) on SCI_RX pin (DIMM 74) and a random noise on LIN_RX (SCIRX_Base, DIMM 43) via an oscilloscope. Because of the noise, the SCI module keeps getting parity errors, thus the constant losing of packets. Do you have any suggestions for solving this noise problem of the DRV8301 RM48 kit?

  • I can see the noise on other pins as well, QEPA (DIMM 40), QEPB (DIMM 90) etc. It only appears after I enable the motor controller by setting gui->EnableFlg. I'm using DRV 8301 RM48 Kit and the example foc_encoder_speed of Motorware.

  • Asaygl,

    I would suggest you taking a look at this forum thread for using SCI with Motorware.

    http://e2e.ti.com/support/microcontrollers/hercules/f/312/p/260090/915627.aspx#915627

    Thanks and regards,

    Zhaohong