Other Parts Discussed in Thread: HALCOGEN
Tool/software:
Dear TI support,
Do you example source code and HalcoGen configuration for I2C read and write by DMA controller?
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.
Tool/software:
Dear TI support,
Do you example source code and HalcoGen configuration for I2C read and write by DMA controller?
Hi Manoraj,
I don't have any direct example to share with you, but you can implement in the following way:
First understand how the DMA will work with i2c module:

Also refer below thread, here you find some code reference.
Just try to implement from your side, if you get any difficulty in your implementation then i will assist you further.
--
Thanks & regards,
Jagadish.
Hi Jagadish,
Thanks for your reply.
I used internal loopback to read back Data with size 16 bits.
I am able to read only first 8 bits through DMA.
Please find my code below
/*
* Copyright (C) 2009-2015 Texas Instruments Incorporated - www.ti.com
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* distribution.
*
* Neither the name of Texas Instruments Incorporated nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/* USER CODE BEGIN (0) */
/* USER CODE END */
/* Include Files */
#include "HL_sys_common.h"
#include "HL_system.h"
#include "HL_sys_dma.h"
/* USER CODE BEGIN (1) */
#include "HL_i2c.h"
#define own_add 0x20
#define slv_add 0x10
#define bsize 16
#define I2C1_TX_ADDR ((uint32_t)(&(i2cREG1->DXR)) + 3)
#define I2C1_RX_ADDR ((uint32_t)(&(i2cREG1->DRR)) + 3)
uint8 TX_PACK[bsize]={'H','E','R','C','U','L','E','S','M','I','C','R','O','-','T','A'};
uint8 DMA_RX_PACK[bsize]={0};
void i2cEnableLoopback(i2cBASE_t *i2c);
/* USER CODE END */
/* USER CODE BEGIN (2) */
/* USER CODE END */
void main(void)
{
/* USER CODE BEGIN (3) */
g_dmaCTRL g_dmaCTRLPKT2, g_dmaCTRLPKT1;
// enable CPU response to interrupt request
_enable_IRQ();
/* i2c initialization */
i2cInit();
/* Configure address of Slave to talk to */
i2cSetSlaveAdd(i2cREG1, slv_add);
i2cSetDirection(i2cREG1, I2C_TRANSMITTER);
/* set i2c own address */
i2cSetOwnAdd(i2cREG1,own_add);
/* enable internal loopback */
i2cEnableLoopback(i2cREG1);
dmaReqAssign(DMA_CH0, DMA_REQ10);
dmaReqAssign(DMA_CH1, DMA_REQ11);
dmaSetChEnable(DMA_CH0, DMA_HW);
dmaSetChEnable(DMA_CH1, DMA_HW);
dmaEnableInterrupt(DMA_CH0, BTC, DMA_INTA);
dmaEnableInterrupt(DMA_CH1, BTC, DMA_INTA);
/*Configure control packet for Channel 1*/
g_dmaCTRLPKT1.SADD = I2C1_RX_ADDR; /* source address */
g_dmaCTRLPKT1.DADD = (uint32_t)DMA_RX_PACK; /* destination addr ss */
g_dmaCTRLPKT1.CHCTRL = 0; /* channel control */
g_dmaCTRLPKT1.FRCNT = bsize; /* frame count */
g_dmaCTRLPKT1.ELCNT = 1; /* element count */
g_dmaCTRLPKT1.ELDOFFSET = 0; /* element destination offset */
g_dmaCTRLPKT1.ELSOFFSET = 0; /* element destination offset */
g_dmaCTRLPKT1.FRDOFFSET = 0; /* frame destination offset */
g_dmaCTRLPKT1.FRSOFFSET = 0; /* frame destination offset */
g_dmaCTRLPKT1.PORTASGN = PORTB_READ_PORTA_WRITE;
g_dmaCTRLPKT1.RDSIZE = ACCESS_8_BIT; /* read size */
g_dmaCTRLPKT1.WRSIZE = ACCESS_8_BIT; /* write size */
g_dmaCTRLPKT1.TTYPE = FRAME_TRANSFER; /* transfer type */
g_dmaCTRLPKT1.ADDMODERD = ADDR_FIXED; /* address mode read */
g_dmaCTRLPKT1.ADDMODEWR = ADDR_INC1; /* address mode write */
g_dmaCTRLPKT1.AUTOINIT = AUTOINIT_OFF; /* autoinit */
/*Configure control packet for Channel 0*/
g_dmaCTRLPKT2.SADD = (uint32_t)TX_PACK; /* source address */
g_dmaCTRLPKT2.DADD = I2C1_TX_ADDR; /* destination address */
g_dmaCTRLPKT2.CHCTRL = 0; /* channel control */
g_dmaCTRLPKT2.FRCNT = bsize; /* frame count */
g_dmaCTRLPKT2.ELCNT = 1; /* element count */
g_dmaCTRLPKT2.ELDOFFSET = 0; /* element destination offset */
g_dmaCTRLPKT2.ELSOFFSET = 0; /* element destination offset */
g_dmaCTRLPKT2.FRDOFFSET = 0; /* frame destination offset */
g_dmaCTRLPKT2.FRSOFFSET = 0; /* frame destination offset */
g_dmaCTRLPKT2.PORTASGN = PORTA_READ_PORTB_WRITE;
g_dmaCTRLPKT2.RDSIZE = ACCESS_8_BIT; /* read size */
g_dmaCTRLPKT2.WRSIZE = ACCESS_8_BIT; /* write size */
g_dmaCTRLPKT2.TTYPE = FRAME_TRANSFER; /* transfer type */
g_dmaCTRLPKT2.ADDMODERD = ADDR_INC1; /* address mode read */
g_dmaCTRLPKT2.ADDMODEWR = ADDR_FIXED;; /* address mode write */
g_dmaCTRLPKT2.AUTOINIT = AUTOINIT_OFF; /* autoinit */
/* - setting dma control packets for transmit */
dmaSetCtrlPacket(DMA_CH0, g_dmaCTRLPKT1);
dmaSetCtrlPacket(DMA_CH1, g_dmaCTRLPKT2);
dmaEnable();
i2cREG1->DMACR |= 0x3;
i2cSetStop(i2cREG1);
/* transmit Start Condition */
i2cSetStart(i2cREG1);
/* wait for ever */
while(1);
/* USER CODE END */
}
/* USER CODE BEGIN (4) */
/* USER CODE END */
Please find the snapshot DMA receive buffer

Can you check Configuration of control packet ?
What could be the problem?
Hi Manoraj,
You can't directly receive or transmit 16-bits directly from I2C

As you can see the data width would be 8 bits only. So, if you want to receive 16 bits then you should need to send 2 bytes.
So, if you want to transfer 2 bytes or receive 2 bytes, you should configure DMA as below
/*Configure control packet for Channel 1*/ g_dmaCTRLPKT1.SADD = I2C1_RX_ADDR; /* source address */ g_dmaCTRLPKT1.DADD = (uint32_t)DMA_RX_PACK; /* destination addr ss */ g_dmaCTRLPKT1.CHCTRL = 0; /* channel control */ g_dmaCTRLPKT1.FRCNT = 2; /* frame count */ g_dmaCTRLPKT1.ELCNT = 1; /* element count */ g_dmaCTRLPKT1.ELDOFFSET = 0; /* element destination offset */ g_dmaCTRLPKT1.ELSOFFSET = 0; /* element destination offset */ g_dmaCTRLPKT1.FRDOFFSET = 0; /* frame destination offset */ g_dmaCTRLPKT1.FRSOFFSET = 0; /* frame destination offset */ g_dmaCTRLPKT1.PORTASGN = PORTB_READ_PORTA_WRITE; g_dmaCTRLPKT1.RDSIZE = ACCESS_8_BIT; /* read size */ g_dmaCTRLPKT1.WRSIZE = ACCESS_8_BIT; /* write size */ g_dmaCTRLPKT1.TTYPE = FRAME_TRANSFER; /* transfer type */ g_dmaCTRLPKT1.ADDMODERD = ADDR_FIXED; /* address mode read */ g_dmaCTRLPKT1.ADDMODEWR = ADDR_INC1; /* address mode write */ g_dmaCTRLPKT1.AUTOINIT = AUTOINIT_OFF; /* autoinit */ /*Configure control packet for Channel 0*/ g_dmaCTRLPKT2.SADD = (uint32_t)TX_PACK; /* source address */ g_dmaCTRLPKT2.DADD = I2C1_TX_ADDR; /* destination address */ g_dmaCTRLPKT2.CHCTRL = 0; /* channel control */ g_dmaCTRLPKT2.FRCNT = 2; /* frame count */ g_dmaCTRLPKT2.ELCNT = 1; /* element count */ g_dmaCTRLPKT2.ELDOFFSET = 0; /* element destination offset */ g_dmaCTRLPKT2.ELSOFFSET = 0; /* element destination offset */ g_dmaCTRLPKT2.FRDOFFSET = 0; /* frame destination offset */ g_dmaCTRLPKT2.FRSOFFSET = 0; /* frame destination offset */ g_dmaCTRLPKT2.PORTASGN = PORTA_READ_PORTB_WRITE; g_dmaCTRLPKT2.RDSIZE = ACCESS_8_BIT; /* read size */ g_dmaCTRLPKT2.WRSIZE = ACCESS_8_BIT; /* write size */ g_dmaCTRLPKT2.TTYPE = FRAME_TRANSFER; /* transfer type */ g_dmaCTRLPKT2.ADDMODERD = ADDR_INC1; /* address mode read */ g_dmaCTRLPKT2.ADDMODEWR = ADDR_FIXED;; /* address mode write */ g_dmaCTRLPKT2.AUTOINIT = AUTOINIT_OFF; /* autoinit */
Configure 2 frames and 1 element of size 8-bits, so in this way you can receive or transfer two 8 bytes using DMA on I2C.
--
Thanks & regards,
Jagadish.
Hi Jagadish,
I tried Configuring 2 frames and 1 element of size 8-bits
I am reading only first 2 bits

Hi Jagadish,
I am able to read 16 bits Data through DMA using below DMA and HalCoGen configuration
/*Configure control packet for Channel 1*/
g_dmaCTRLPKT1.SADD = I2C1_RX_ADDR; /* source address */
g_dmaCTRLPKT1.DADD = (uint32_t)DMA_RX_PACK; /* destination addr ss */
g_dmaCTRLPKT1.CHCTRL = 0; /* channel control */
g_dmaCTRLPKT1.FRCNT = bsize; /* frame count */
g_dmaCTRLPKT1.ELCNT = 1; /* element count */
g_dmaCTRLPKT1.ELDOFFSET = 0; /* element destination offset */
g_dmaCTRLPKT1.ELSOFFSET = 0; /* element destination offset */
g_dmaCTRLPKT1.FRDOFFSET = 0; /* frame destination offset */
g_dmaCTRLPKT1.FRSOFFSET = 0; /* frame destination offset */
g_dmaCTRLPKT1.PORTASGN = PORTB_READ_PORTA_WRITE;
g_dmaCTRLPKT1.RDSIZE = ACCESS_8_BIT; /* read size */
g_dmaCTRLPKT1.WRSIZE = ACCESS_8_BIT; /* write size */
g_dmaCTRLPKT1.TTYPE = FRAME_TRANSFER; /* transfer type */
g_dmaCTRLPKT1.ADDMODERD = ADDR_FIXED; /* address mode read */
g_dmaCTRLPKT1.ADDMODEWR = ADDR_INC1; /* address mode write */
g_dmaCTRLPKT1.AUTOINIT = AUTOINIT_OFF; /* autoinit */
/*Configure control packet for Channel 0*/
g_dmaCTRLPKT2.SADD = (uint32_t)TX_PACK; /* source address */
g_dmaCTRLPKT2.DADD = I2C1_TX_ADDR; /* destination address */
g_dmaCTRLPKT2.CHCTRL = 0; /* channel control */
g_dmaCTRLPKT2.FRCNT = bsize; /* frame count */
g_dmaCTRLPKT2.ELCNT = 1; /* element count */
g_dmaCTRLPKT2.ELDOFFSET = 0; /* element destination offset */
g_dmaCTRLPKT2.ELSOFFSET = 0; /* element destination offset */
g_dmaCTRLPKT2.FRDOFFSET = 0; /* frame destination offset */
g_dmaCTRLPKT2.FRSOFFSET = 0; /* frame destination offset */
g_dmaCTRLPKT2.PORTASGN = PORTA_READ_PORTB_WRITE;
g_dmaCTRLPKT2.RDSIZE = ACCESS_8_BIT; /* read size */
g_dmaCTRLPKT2.WRSIZE = ACCESS_8_BIT; /* write size */
g_dmaCTRLPKT2.TTYPE = FRAME_TRANSFER; /* transfer type */
g_dmaCTRLPKT2.ADDMODERD = ADDR_INC1; /* address mode read */
g_dmaCTRLPKT2.ADDMODEWR = ADDR_FIXED;; /* address mode write */
g_dmaCTRLPKT2.AUTOINIT = AUTOINIT_OFF; /* autoinit */
HalCoGen configuration : Changing I2C Bit count from 8 to 16

Hi Jagadish,
for I2C loopback, this configuration works fine.
if I want to read from slave device , what all i need to change in Configuration of control packet?

What to configure in the highlighted configuration?
because i want to just read data from slave device
Hi Manoraj,
I think your previous configuration to receive 16bit data is also not correct.
The highlighted setting is not for 16bit data transmission, it means 16 characters of data need to be receive on i2c.

g_dmaCTRLPKT1.FRCNT = bsize; /* frame count */
This setting also not correct, as you can see its name is frame count, that means number of frames that needs to be send or receive. You should not initialize with bit size here.
To receive or transmit 16bits you just need to keep the above both settings to 2.
What is your slave device?
--
Thanks & regards,
Jagadish.
Hi Jagadish,
Thanks for your feedback.
My slave device is LSM6DSO32: always-on 3-axis accelerometer and 3-axis gyroscope
in Configuration of control packet, what changes needs to be done to data from slave device LSM6DSO32?
I have already implementation to read data from LSM6DSO32 through normal i2C.
Since i want to read more data from LSM6DSO32, i want to use DMA to reduce CPU load
Hi Manoraj,
I created one i2c example project for both transmission and reception.
Here is my project:
I tested this project by connecting to slave (another TI board which is configured as slave) device as well.
When i configured for Transmitter, i am sending below highlighted data to the slave:

And here is my output, as you can see i received ACK from slave and then our TMS board sending the data properly to the slave on DMA.

Similarly, i tested receive functionality as well:
To test receive functionality, i am sending below highlighted data on the slave side,

Here is my master output, i am able to properly receive the data into the master RX buffer from slave.


So, take this code as a reference and properly configure the slave address, data count properly based on your slave.


And also make sure you are following the slave protocol properly, if you do these things correctly then your code definitely will work.
And my one more suggestion is that, usually customers will not prefer i2c on DMA. This is because i2c slave devices will send small quantity of bytes may be a few bytes, for this quantity of data DMA is not necessary. If there is a huge chunk of data, then it might be useful but for few bytes it is not necessary. Anyway, it is your call, and i provided an example to you.
--
Thanks & regards,
Jagadish.
Hi Jagadish,
Thank you so much for sharing the project.
Using DMA I2C, i will read data of 3kb from FIFO of my slave device
that is why i am trying DMA to avoid CPU load.
I am using I2C2 peripheral.
How to identify own address of i2c2?

Using DMA I2C, i will read data of 3kb from FIFO of my slave device
In that case, it makes sense to go for DMA.
How to identify own address of i2c2?
own address may not be important in this case, only make sure you were configuring the proper slave address. Ignore the own address.
Hi Jagadish,
I have configured slave device and i am able to read FIFO from slave.
but there is a limitation in the slave device that
To read complete FIFO, i need to read 7 register individually for number of configured sampling.
It means i need to call i2cSetStart(i2cREG2) for 7 * number of configured sampling.
it need to use I2C all the time to clear the FIFO keeping CPU Busy
is there any repeat mode in I2C or DMA for reading data for n number of times?


Hi Manoraj,
but there is a limitation in the slave device that
To read complete FIFO, i need to read 7 register individually for number of configured sampling.
I am not aware of this slave device completely.
If there is a limitation on slave device what we could do, but my suggestion would be check the slave device completely, there might be some feature like continues FIFO read modes, that might be useful.
How Auto-initiation Mode (AIM) works in DMA?
Regarding Auto-Initialization mode understanding refer below thread:
I mean after completion of a transfer it will again initialize the all the parameters like source address, destination address, frame counts automatically for to initiate the next transfer. And if we enable the DMA channel then the next transfer will get initiated automatically.
--
Thanks & regards,
Jagadish.