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 fill I2C RX data buffer with zeros

Hello,

I use SM470R1B1M and IAR Embedded Workbench 7.30.4.

My application uses I2C2 interface on SM470R1B1m to get real time stamp from RTC. Since I2C is a slow communication interface, I want to use DMA transfer to free CPU time. Before implement I2C2 DMA mode transfer, I have implemented an I2C2 polling mode device driver. Currently I have no problem to use polling mode device driver to access RTC on I2C2. That means I know how to configure I2C2 properly. However when I develop a DMA mode device driver to read RTC time stamp from I2C2, I have got all zeros in RX data buffer.

According to SM470R1B1M data sheet, I2C2 read uses DMAREQ[9]. There are 32 DMA packets. I assign packet 9 to I2C2 RX. When I use oscillate scope to monitor SCL and SDA, I can see both SCL and SDA signals. However I can tell SDA is not all zeros.  

Before read a few bytes of RTC data, SM470 should send 1-byte starting address to RTC. From scope I can see 2-byte signals. The first byte is 7-bit I2C2 address plus 1-bit write signal. The second byte is the starting RTC register address. After that I start DMA read. Since my program will read 7-byte data from RTC through I2C2, I can see 8-byte SDA and SCL signals from scope. The first byte consists of 7-bit I2C2 address and 1-bit read signal. The rest of 7-byte is data from RTC. 

The DMA0 interrupt is generated properly. DMA process can be repeated. When DMA0 interrupt is generated, I have checked DMASA09, DMADA09 and DMATC09 values. DMASA09 has I2C2DRR's address which is remain unchanged before and after DMA as expected. At the end of DMA, DMADA09 pointed to the next address of the end of RX data buffer. DMATC09 becomes to "0". For debugging purpose, I initialize RX data buffer with non-zero values. After DMA, the RX data buffer become all zeros. 

I try to get help to diagnose what is wrong in my program. There is one place I can think of:

For DMA09 register configuration, I choose DSTMOD_2 and SRCMOD_15. This two bits are for memory selection. According to DMA Reference Guide, source peripheral I2C2 should be SRCMOD_15. The RX data buffer is in RAM. That means for destination, we should select either DSTMOD_2 or DSTMOD_3. I tried both of them and there is no luck. 

Anybody has I2C DMA experience? What I did wrong? Thank you!

Lisa

  • Lisa,
    Unfortunately I do not have any I2C dma example code.
    I will take a look and see if I can spot anything. Possibly some other users will have input.
    Regards,
    Wade
  • Hi All,

    Let me post my I2C2 DMA source code here.

    I use SM470. I2C2 RX use DMA9 channel and I2C2 TX use DMA10 channel. I assign packet 09 to I2C2 RX and packet 10 for I2C2 TX.

    Before I implement I2C2 DMA transfer data, I have implemented I2C2 polling mode data trasfer. I believe that I have setup I2C2 properly already. I use same I2C2_Config() function for both DMA mode and polling mode. I have no problem to run I2C2 polling mode functions. Here I only list my DMA configuration for I2C2 source code:

    void DMA0_IrqHandler(void)
    {
    switch(DMAIO0 & 0x1F)
    {
    case DMA_CH9:
    REQMASK &= ~REQMASK18;
    DMAC09 &= ~INTEN;
    DMACPSC &= ~DMACPS_PCK9;
    gRTC_DMA_Rd_Buf[1] &= RTC_MINUTE_REG_MASK;
    gRTC_Time_Flg = I2C2_RX_DMA_DONE;
    I2C2DIR &= ~I2C_RXDMAEN;
    I2C2MDR &= ~STP;
    break;

    case DMA_CH10:
    REQMASK &= ~REQMASK18;
    DMAC10 &= ~INTEN;
    DMACPSC &= ~DMACPS_PCK10;
    gRTC_Time_Flg = I2C2_TX_DMA_DONE;
    I2C2DIR &= ~I2C_TXDMAEN;
    I2C2MDR &= ~STP;
    break;

    default:
    break;
    }

    DMAGD = 0;
    }

    /* Packet 09 for I2C2 RX */
    void I2C2_DMA_Rd_Config(unsigned int* pBufAddr, unsigned short byte_len)
    {
    DMAC09 = INTEN | TRSIZE_0 | DSTINC | DSTMOD_2 | SRCMOD_15;
    DMASA09 = (unsigned int)&I2C2DRR;
    DMADA09 = (unsigned int)pBufAddr;
    DMATC09 = byte_len;
    DMACC1 |= SEN9 | RQEN9;
    DMAGC = 0;
    DMAGD = 0;
    DMACPS |= DMACPS_PCK9; /* DMACPS_PCK9 = 0x200 */
    }

    /* Packet 10 for I2C2 TX */
    void I2C2_DMA_Wr_Config(unsigned int* pBufAddr, unsigned short byte_len)
    {
    DMAC10 = INTEN | TRSIZE_0 | SRCINC | DSTMOD_15 | SRCMOD_2;
    DMASA10 = (unsigned int)pBufAddr;
    DMADA10 = (unsigned int)&I2C2DXR;
    DMATC10 = byte_len;
    DMACC1 |= SEN10 | RQEN10;
    DMAGC = 0;
    DMAGD = 0;
    DMACPS |= DMACPS_PCK10;
    }

    void Rd_DMA_KickStart(unsigned short byte_len)
    {
    DMACCP2 |= DMEN9 | CCPACK9_8 | CCPACK9_1;
    REQMASK |= REQMASK18;
    I2C2DIR |= I2C_RXDMAEN;
    I2C2MDR &= ~TRX;
    I2C2MDR |= NIRS;
    I2C2CNT = byte_len; /* I am not sure if this is nessary. It seems has no affect. */
    I2C2MDR |= STT | MST;
    }

    void Wr_DMA_KickStart(unsigned short byte_len)
    {

    DMACCP2 |= DMEN10 | CCPACK10_8 | CCPACK10_2;
    REQMASK |= REQMASK18;

    I2C2CNT = byte_len;
    I2C2MDR |= STT | MST | TRX;
    I2C2DIR |= I2C_TXDMAEN;
    }

    unsigned short I2C2_RTC_DMA_Rd(unsigned short byte_len)
    {
    unsigned short Ret = RET_NORMAL;

    I2C2_DMA_Rd_Config((unsigned int*)gRTC_DMA_Rd_Buf, byte_len);
    gRTC_Time_Flg = I2C2_NO_EVENT;

    I2C2MDR |= NIRS;

    I2C2CNT = LISA_I2C_CNT_1_BYTE;
    I2C2MDR |= STT | MST | TRX;
    I2C2DXR = RTC_TIME_START_ADDR;

    Ret = while_w_timeout((unsigned int)I2CSR_TXRDY,
    (unsigned char)1,
    (unsigned short)I2C2SR_TIMEOUT);

    Rd_DMA_KickStart(byte_len);

    return Ret;
    }

    void I2C2_RTC_DMA_Wr(unsigned char* pConfigBuf, unsigned char byte_len)
    {
    I2C2_DMA_Wr_Config((unsigned int*)pConfigBuf, (unsigned short)byte_len);
    gRTC_Time_Flg = I2C2_NO_EVENT;
    Wr_DMA_KickStart(byte_len);
    }

    With above program, what I have found is that at the end of DMA RX, gRTC_DMA_Rd_Buf is filled with zeros. I use oscillate scope to monitor SDA and SCL. They both appear correct on scope. I can see second byte changine constantly.

    Anybody can help me what is wrong in my DMA configuration? Thanks in advance!

    Lisa