Skip to main content
abhinav
Associate
August 13, 2014
Question

i2c dma transmit/receive multiple bytes

  • August 13, 2014
  • 5 replies
  • 1831 views
Posted on August 13, 2014 at 17:46

I am trying to transmit multiple bytes on I2C bus using dma. In the sample code I am trying to send 3 bytes. I see on my scope that three bytes are being sent but the problem is that the first byte gets sent three times. I am also able to recive three bytes without any problem but agian nothing gets written in the location of the second and third byte.

I generated the code using CubeMX but modified the main file to send/recieve at the right time. My master transmitter code looks like this:

#define

 

i2c_buffer_size 3

 

uint8_t

i2c_data_buffer[i2c_buffer_size] = {0x03,0x10,

0xFF};

 

uint16_t slaveAddress =

0x05;

 

....

 

void

cmd_send_i2c(

){

 

HAL_I2C_Master_Transmit_DMA(&hi2c1, slaveAddress,i2c_data_buffer, i2c_buffer_size);

 

}

 

My slave receiver code looks like this

 

</p>

 

int

 

</b>

 

 

main(

void

){

 

/* Reset of all peripherals, Initializes the Flash interface and the

Systick

. */

 

HAL_Init();

 

/* Initialize all configured peripherals */

 

MX_GPIO_Init();

 

MX_DMA_Init();

 

MX_I2C1_Init();

 

while

(1)

 

{

 

if

(HAL_I2C_GetState(&hi2c1)==

HAL_I2C_STATE_READY

)

 

HAL_I2C_Slave_Receive_DMA(&hi2c1,(

uint8_t

*) i2c_data_buffer,i2c_buffer_size);

 

}

 

return

0;

 

}

 

 

and the receive call back function is

 

 

void

 

 

 

HAL_I2C_SlaveRxCpltCallback(

I2C_HandleTypeDef

*hi2c){

 

LED_RED_TOGGLE;

 

if

(i2c_data_buffer[0] == 0x03)

 

    

LED_BLUE_TOGGLE;

 

if

(i2c_data_buffer[1] == 0x10)

 

    LED_GREEN_TOGGLE;

 

return

;

 

}

 

I am checking the i2c_data_buffer using a debugger and the value for i2c_data_buffer[0] is correct but i2c_data_buffer[1] is not correct.

 

 

Thanks in advance for the help!
    This topic has been closed for replies.

    5 replies

    jwoolston
    Associate III
    August 13, 2014
    Posted on August 13, 2014 at 17:57

    Can you show the contents of the HAL_DMA_Init() method? I'm assuming the DMA is not configured to auto increment the memory location or your data width is perhaps incorrect.

    jwoolston
    Associate III
    August 13, 2014
    Posted on August 13, 2014 at 17:58

    MX_I2C1_Init as well please

    abhinav
    abhinavAuthor
    Associate
    August 13, 2014
    Posted on August 13, 2014 at 19:01

    Please see below functions HAL_DMA_Init, MX_I2C1_Init and MX_DMA_Init. I am also adding the code snippet for the DMA peripheral initialization from the function HAL_I2C_MspInit.

    Thanks a lot for looking at this code!

    HAL_StatusTypeDef

    HAL_DMA_Init(

    DMA_HandleTypeDef

    *hdma)

    {

    uint32_t

    tmp = 0;

    /* Check the DMA handle allocation */

    if

    (hdma == NULL)

    {

    return

    HAL_ERROR

    ;

    }

    /* Check the parameters */

    assert_param(IS_DMA_ALL_INSTANCE(hdma->

    Instance

    ));

    assert_param(IS_DMA_DIRECTION(hdma->

    Init

    .

    Direction

    ));

    assert_param(IS_DMA_PERIPHERAL_INC_STATE(hdma->

    Init

    .

    PeriphInc

    ));

    assert_param(IS_DMA_MEMORY_INC_STATE(hdma->

    Init

    .

    MemInc

    ));

    assert_param(IS_DMA_PERIPHERAL_DATA_SIZE(hdma->

    Init

    .

    PeriphDataAlignment

    ));

    assert_param(IS_DMA_MEMORY_DATA_SIZE(hdma->

    Init

    .

    MemDataAlignment

    ));

    assert_param(IS_DMA_MODE(hdma->

    Init

    .

    Mode

    ));

    assert_param(IS_DMA_PRIORITY(hdma->

    Init

    .

    Priority

    ));

    /* Change DMA peripheral state */

    hdma->

    State

    =

    HAL_DMA_STATE_BUSY

    ;

    /* Get the CR register value */

    tmp = hdma->

    Instance

    ->

    CCR

    ;

    /* Clear PL, MSIZE, PSIZE, MINC, PINC, CIRC, DIR bits */

    tmp &= ((

    uint32_t

    )~(DMA_CCR_PL | DMA_CCR_MSIZE | DMA_CCR_PSIZE | \

        DMA_CCR_MINC | DMA_CCR_PINC | DMA_CCR_CIRC | \

        DMA_CCR_DIR));

    /* Prepare the DMA Channel configuration */

    tmp |= hdma->

    Init

    .

    Direction

    |

        hdma->

    Init

    .

    PeriphInc

    | hdma->

    Init

    .

    MemInc

    |

        hdma->

    Init

    .

    PeriphDataAlignment

    | hdma->

    Init

    .

    MemDataAlignment

    |

        hdma->

    Init

    .

    Mode

    | hdma->

    Init

    .

    Priority

    ;

        /* Write to DMA Channel CR register */

    hdma->

    Instance

    ->

    CCR

    = tmp;

    /*

    Initialise

    the error code */

    hdma->

    ErrorCode

    = HAL_DMA_ERROR_NONE;

    /* Initialize the DMA state*/

    hdma->

    State

    =

    HAL_DMA_STATE_READY

    ;

    return

    HAL_OK

    ;

    }

    /* I2C1

    init

    function */

    void

    MX_I2C1_Init(

    void

    )

    {

    hi2c1.

    Instance

    = I2C1;

    hi2c1.

    Init

    .

    Timing

    = 0x2000090E;

    hi2c1.

    Init

    .

    OwnAddress1

    = 0x05;

    hi2c1.

    Init

    .

    AddressingMode

    = I2C_ADDRESSINGMODE_7BIT;

    hi2c1.

    Init

    .

    DualAddressMode

    = I2C_DUALADDRESS_DISABLED;

    hi2c1.

    Init

    .

    OwnAddress2

    = 0;

    hi2c1.

    Init

    .

    OwnAddress2Masks

    = I2C_OA2_NOMASK;

    hi2c1.

    Init

    .

    GeneralCallMode

    = I2C_GENERALCALL_DISABLED;

    hi2c1.

    Init

    .

    NoStretchMode

    = I2C_NOSTRETCH_DISABLED;

    HAL_I2C_Init(&hi2c1);

    /**Configure

    Analogue

    filter

    */

    HAL_I2CEx_AnalogFilter_Config(&hi2c1, I2C_ANALOGFILTER_ENABLED);

    }

     

    void

    MX_DMA_Init(

    void

    )

    {

    /* DMA controller clock enable */

    __DMA1_CLK_ENABLE();

    /* DMA interrupt

    init

    */

    /* Sets the priority grouping field */

    HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_0);

    HAL_NVIC_SetPriority(

    DMA1_Channel6_IRQn

    , 0, 0);

    HAL_NVIC_EnableIRQ(

    DMA1_Channel6_IRQn

    );

    /* Sets the priority grouping field */

    HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_0);

    HAL_NVIC_SetPriority(

    DMA1_Channel7_IRQn

    , 0, 0);

    HAL_NVIC_EnableIRQ(

    DMA1_Channel7_IRQn

    );

    }

    From HAL_I2C_MspInit

    hdma_i2c1_tx.

    Instance

    = DMA1_Channel6;

    hdma_i2c1_tx.

    Init

    .

    Direction

    = DMA_MEMORY_TO_PERIPH;

    hdma_i2c1_tx.

    Init

    .

    PeriphInc

    = DMA_PINC_DISABLE;

    hdma_i2c1_tx.

    Init

    .

    MemInc

    = DMA_MINC_DISABLE;

    hdma_i2c1_tx.

    Init

    .

    PeriphDataAlignment

    = DMA_PDATAALIGN_BYTE;

    hdma_i2c1_tx.

    Init

    .

    MemDataAlignment

    = DMA_MDATAALIGN_BYTE;

    hdma_i2c1_tx.

    Init

    .

    Mode

    = DMA_NORMAL;

    hdma_i2c1_tx.

    Init

    .

    Priority

    = DMA_PRIORITY_LOW;

    HAL_DMA_Init(&hdma_i2c1_tx);

    jwoolston
    Associate III
    August 13, 2014
    Posted on August 13, 2014 at 19:09

    As I thought, the DMA is not configured to increment the memory location. Change

    hdma_i2c1_tx.Init.MemInc = DMA_MINC_DISABLE;

    To:

    hdma_i2c1_tx.Init.MemInc = DMA_MINC_ENABLE;

    And you should be good.
    abhinav
    abhinavAuthor
    Associate
    August 13, 2014
    Posted on August 13, 2014 at 19:16

    Thanks a lot for the help. It is working fine now!