This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Avoiding HardFault and Optimizing Code Size with TWI Transaction Manager

I recently experimented with the TWI Transaction Manager and found the following:

This function would cause HardFault Error

void _BAD_read_func(app_twi_t* param_p_app_twi, 
                      uint8_t* param_p_reg_addr, 
                      uint8_t* param_p_buffer, 
                      uint8_t byte_cnt)
{
  app_twi_transfer_t        const transfer_1[] = 
  {
    HTS221_READ(param_p_reg_addr, param_p_buffer, byte_cnt)
  };

  app_twi_transaction_t     const transaction_1 =
  {
      .callback             = custom_app_twi_callback,
      .p_user_data          = NULL,
      .p_transfers          = transfer_1,
      .number_of_transfers  = sizeof(transfer_1)/sizeof(transfer_1[0])
  };

  APP_ERROR_CHECK(app_twi_schedule(param_p_app_twi, &transaction_1));
}

But this would not

uint8_t reg_addr = HTS221_WHO_AM_I_REG_ADDR;
uint8_t m_buffer[50];

app_twi_transfer_t          transfer_2[] = 
{
  HTS221_READ(&reg_addr, m_buffer, 1)
};

app_twi_transaction_t       transaction_2 =
{
    .callback               = custom_app_twi_callback,
    .p_user_data            = NULL,
    .p_transfers            = transfer_2,
    .number_of_transfers    = sizeof(transfer_2)/sizeof(transfer_2[0])
};

void _GOOD_read_func(app_twi_t* param_p_app_twi, 
                      uint8_t* param_p_reg_addr, 
                      uint8_t* param_p_buffer, 
                      uint8_t byte_cnt)
{
  APP_ERROR_CHECK(app_twi_schedule(param_p_app_twi, &transaction_2));
}

I am guessing that the TWI peripheral does not touch the app_twi_transaction_t struct nor the app_twi_transfer_t struct before the TWI operation is actually carried out. That is why if I store the variable in the stack as in the first function, when the TWI operation look up the values, the stack variables have already been popped and that is why it caused a HardFault.

Is my guess correct?


Another question is: I need to optimize my firmware for code size. Therefore I really prefer not having to declare a global or static local app_twi_transfer_t array and a app_twi_transaction_tfor every TWI operation I have.

With the second approach I posted above, I could modify the global variable depending on what I want to read/write. But then there is the case of two consecutive transactions. When I set up the second transaction and modify the global variables, would that potentially mess up the first transaction?

Related