Hi, All
We realized I2C driver for MOD5441X working properly via CPU interrupts(working with EEPROM).
Due to some timing problems we would like to implement I2C driver writing/reading via DMA.
Copying from memory to memory via DMA also works properly but not from memory to I2C...
Implementing “write to I2C via DMA” I set DMAEN bit on I2C Control Register in I2C Start sequence, according to the document explanation. In I2C Write sequence I put address of my write buffer to DMA Source address(sim2.edma.tcd[channel].saddr) and I put address of I2C Data register to DMA Destination address(sim2.edma.tcd[channel].daddr). Destination offset = 0 – all the time writing to the same data register(sim2.edma.tcd[channel].doff = 0). DMA Source offset sim2.edma.tcd[channel].soff" = 1(writing every byte). Minor loop(citer=biter=1). Major loop (nbytes = written_bytes_number). Writing buffer contains device address byte, EEPROM address(2 bytes) and written data bytes. DMA "channel" = 24 (I2C0 in our case). I set DMA interrupt bit and set DMA start bit. DMA informs about transmit finished(like in successful case of memory to memory copy)...
But no any transmit via I2c is initiated... No any clock of data seen via scope. No data is written to EEPROM
May be anybody have practice with this issue ? Any example or advice how to work with I2c via DMA ?
MOD5441X. I2C driver via DMA
Re: MOD5441X. I2C driver via DMA
Standard comment about DMA: Use revision 3 of the reference manual. Rev 4 is missing critical information in that chapter.
Can you post a
Can you post a
Code: Select all
formatted section of your source in question?
-Dan
Dan Ciliske
Project Engineer
Netburner, Inc
Project Engineer
Netburner, Inc
Re: MOD5441X. I2C driver via DMA
Yes, we are using Revision 3 of MCF5441X reference manual
===================== CODE============================
START I2C Sequence
------------------------
I set DMAEN bit and Interrupt bit on I2C control register
WRITE I2C Sequence
-----------------------
parameter "channel" = 24
// Reset TCD
memset((void*)(&(sim2.edma.tcd[channel])), 0, sizeof(sim2.edma.tcd[24]));
sim2.edma.serq = channel; // set request I2C0 channel
sim2.edma.tcd[channel].citer = 1; // 1 byte minor loop
sim2.edma.tcd[channel].biter = 1; // 1 byte major loop
sim2.edma.tcd[channel].nbytes = 17; // 17 bytes - write length (includes device address byte A0
//and 2 bytes of EEPROM address)
sim2.edma.tcd[channel].saddr = (vudword)source_buf; // source
sim2.edma.tcd[channel].soff = 1; // read from source 1 byte
sim2.edma.tcd[channel].attr = 0; // 1 byte transfer from source - 0
sim2.edma.tcd[channel].slast = -17; // back 17 source
sim2.edma.tcd[channel].daddr = (vudword)&(sim2.i2c0.i2dr); // Data register of I2C
sim2.edma.tcd[channel].doff = 0; // write to destination 1 byte
sim2.edma.tcd[channel].attr |= 0x0000; // 1 byte transfer to destination - 0
sim2.edma.tcd[channel].dlast_sga = -17; // back 17 dest
sim2.edma.tcd[channel].csr = 0x0002; // enable interrupts when major count completed
sim2.edma.tcd[channel].csr |= 0x0001; // start transfer
while (!(sim2.edma.tcd[channel].csr & 0x0080)); // waiting for transmit complete...
sim2.edma.cerq = 24; // clear request
STOP I2C sequence
----------------------
As usual...
=============================== CODE ===================================
What I miss ?
Thanks
===================== CODE============================
START I2C Sequence
------------------------
I set DMAEN bit and Interrupt bit on I2C control register
WRITE I2C Sequence
-----------------------
parameter "channel" = 24
// Reset TCD
memset((void*)(&(sim2.edma.tcd[channel])), 0, sizeof(sim2.edma.tcd[24]));
sim2.edma.serq = channel; // set request I2C0 channel
sim2.edma.tcd[channel].citer = 1; // 1 byte minor loop
sim2.edma.tcd[channel].biter = 1; // 1 byte major loop
sim2.edma.tcd[channel].nbytes = 17; // 17 bytes - write length (includes device address byte A0
//and 2 bytes of EEPROM address)
sim2.edma.tcd[channel].saddr = (vudword)source_buf; // source
sim2.edma.tcd[channel].soff = 1; // read from source 1 byte
sim2.edma.tcd[channel].attr = 0; // 1 byte transfer from source - 0
sim2.edma.tcd[channel].slast = -17; // back 17 source
sim2.edma.tcd[channel].daddr = (vudword)&(sim2.i2c0.i2dr); // Data register of I2C
sim2.edma.tcd[channel].doff = 0; // write to destination 1 byte
sim2.edma.tcd[channel].attr |= 0x0000; // 1 byte transfer to destination - 0
sim2.edma.tcd[channel].dlast_sga = -17; // back 17 dest
sim2.edma.tcd[channel].csr = 0x0002; // enable interrupts when major count completed
sim2.edma.tcd[channel].csr |= 0x0001; // start transfer
while (!(sim2.edma.tcd[channel].csr & 0x0080)); // waiting for transmit complete...
sim2.edma.cerq = 24; // clear request
STOP I2C sequence
----------------------
As usual...
=============================== CODE ===================================
What I miss ?
Thanks
Re: MOD5441X. I2C driver via DMA
I tried also to configure previously DMA like in my example, and then to send the first byte(device address) directly writing it to I2C data register. I expected that I2C will start DMA tranfser(as configured previously) after 1-st byte transferring by CPU...
But without any progress...
But without any progress...
Re: MOD5441X. I2C driver via DMA
By the way
If I make in DMA section(described above code) only 1 byte transferring(citer=biter=nbytes=1), it works properly. In my FOR() loop I can transfer such way all bytes I need, but it has no sense to execute this DMA section many times. We need to put in DMA the number of bytes(for example EEPROM page amount - 128 bytes) and DMA should execute the work by it self. It seems, we need somehow cause I2C data register(our destination addr in DMA tcd) to know to receive more than 1 byte. Via CPU interrupts it is understood mechanism, via DMA - not.
If I make in DMA section(described above code) only 1 byte transferring(citer=biter=nbytes=1), it works properly. In my FOR() loop I can transfer such way all bytes I need, but it has no sense to execute this DMA section many times. We need to put in DMA the number of bytes(for example EEPROM page amount - 128 bytes) and DMA should execute the work by it self. It seems, we need somehow cause I2C data register(our destination addr in DMA tcd) to know to receive more than 1 byte. Via CPU interrupts it is understood mechanism, via DMA - not.
Re: MOD5441X. I2C driver via DMA
Are you setting the bits apropriatly in the I2C hardware for DMA?
Specifically read the notes in table 42-4 of the V3 version of the manual.
Specifically read the notes in table 42-4 of the V3 version of the manual.