cancel
Showing results for 
Search instead for 
Did you mean: 

Using HAL_I2C_transmit/receive_DMA inside a callback function

Jefferson Cunalata
Associate II
Posted on June 10, 2017 at 18:35

Hi everybody, I am trying to implement callback function for I2C peripheral.

This is the code without dma implementation:

void ADXL345_GetXyzRAW(uint8_t *buffer){

uint8_t firstRegAddress = ADXL345_DATAX0;

HAL_I2C_Master_Transmit(ADXL345_I2C,

(uint8_t)(ADXL345_ADDRESS<<1),

&firstRegAddress,

1,

ADXL345_I2C_TIMEOUT_TRANSFER);

HAL_I2C_Master_Receive(ADXL345_I2C,

(uint8_t)(ADXL345_ADDRESS<<1),

buffer,

6,

ADXL345_I2C_TIMEOUT_TRANSFER);

}

As you can see, the code works properly but it demands cpu cycles. So my objective is to use dma controller for automatizing the process. The problem rise when the task

ADXL345_GetXyzRAW

demand me two i2c functions (transmit and receive).

It is a problem because my idea is execute 

ADXL345_GetXyzRAW function once and then still doing another task. It doens't allow me wait for ending of I2C transmit for then executing i2c receive (time is gold for my device). I need both of theses task executing one by one with out wait for the first for then execute the second in a polling mode.

My idea is

call the function

i2c receive dma

inside

 

HAL_I2C_MasterTxCpltCallback(), but i dont know if I am doing a bad practice or a violation for access memory.

#hal #stm32 #dma #callback #i2c
5 REPLIES 5
john doe
Lead
Posted on June 10, 2017 at 22:15

I have always read that you should set/check a flag in your interrupt handler, in order to get out of the handler as quickly as possible, rather than doing things like serial i/o inside it.

Jefferson Cunalata
Associate II
Posted on June 11, 2017 at 12:46

I think that I will access to the function 

ADXL345_GetXyzRAW two times, first one for transmit and second one for receive, I will control the operation with a couple of flags, for fragmenting the operation. However I don't feel this solution as a correct and optimized solution for doing the task. If someone has another sight for solving my problem, it will be very welcome.

Thank you very much.

Posted on October 16, 2017 at 16:48

Cunalata.Jefferson

Can you share your code if you found a way to use DMA ?

Posted on October 16, 2017 at 16:57

Dear Alexander, 

I am sorry but I could not solve the problem. I had to implement a flag and interrupt mode.

Youssouf Coulibaly
Associate II
Posted on March 14, 2018 at 12:07

Hello,

Based on I2C protocol specification itself, you need to provide 2 functions to fullfill this goal.

But using DMA functions, it is fairly easy to only use one function provided by ST to do that. 

This depends on your I2C slave ADXL device. Looking into the datasheet it has a register address (we call this an i2c memory slave device), so you can use this HAL function :

HAL_StatusTypeDef HAL_I2C_Mem_Read_DMA

(

      I2C_HandleTypeDef *hi2c,

      uint16_t DevAddress,

      uint16_t MemAddress,

      uint16_t MemAddSize,

      uint8_t *pData,

      uint16_t Size

)

and you have to register to the low level DMA transfer complet event. 

void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *hi2c)

{

}

Basically, with one function and one IRQ interrupt you are done.

Hope this could help.

Regards,

Youssouf