nrf_twi_mngr_transfer_t and const write data

I am trying to populate a nrf_twi_mngr_transfer_t at runtime depending on chunks of an input file that I'm pushing to i2c. 

nrf_twi_mngr_transfer_t const write_cfg_transfers[] = {
   NRF_TWI_MNGR_WRITE(bytes[0] >> 1, &data, i-1, 0),
};
Then I get a build error - 

error: initializer element is not constant

How is this done? 

I've tried using the twi instance from the twi_mngr struct, I can see it on the wire, but I get a hardfault on invoking the callback (likley undefined at this point)

ret_code_t err_code = nrf_drv_twi_tx(&(m_nrf_twi_mngr.twi), bytes[0] >> 1, data, i-1, false);
    • For TWIM (TWI Master with EasyDMA): Buffers must be located in RAM. The TWI transaction manager needs to reserve sufficient space in RAM to copy the buffer contents before initiating transfers if buffers in flash are to be used with the TWIM peripheral.
    • For TWI (legacy TWI without EasyDMA): The buffers can be const (located in flash).
    • The NRF_TWI_MNGR_BUFFERS_IN_RAM definition helps the compiler and linker determine the correct location for the buffers based on the presence of the TWIM peripheral. 

    wow. the second bullet should say 'the buffers MUST be const' 

    Does TWIM work with twi_manager ? Its using nrf_drv_twi.h

  • For more context - I've inherited production code that is using TWI MNGR everywhere. 
    It would take weeks to rewrite this using one of the other API's. 

    Is there a magic combination of SDK_CONFIG options to use the TWIM driver with twi_mngr and nrf_drv_twi ?
    It looks like if I can manage to define TWIM_PRESENT, the const qualifier should be dropped. 


    //If TWIM is present buffers can only be in RAM
    /*lint -save -e491*/

    /**
    * @brief Macro checking if buffers should be stored in RAM.
    */
    #ifndef NRF_TWI_MNGR_BUFFERS_IN_RAM
    #define NRF_TWI_MNGR_BUFFERS_IN_RAM defined(TWIM_PRESENT)
    #endif

    /**
    * @brief Modifier used in array declaration for TWI Manager.
    *
    * @note For TWI peripheral array can be const, for TWIM array has to be located in RAM.
    */
    #if NRF_TWI_MNGR_BUFFERS_IN_RAM
    #define NRF_TWI_MNGR_BUFFER_LOC_IND
    #else
    #define NRF_TWI_MNGR_BUFFER_LOC_IND const
    #endif
  • It looks like NRF_TWI_MNGR_BUFFERS_IN_RAM is being set.
    I wrapped my transaction with #ifdef NRF_TWI_MNGR_BUFFERS_IN_RAM and I still get the 
    error: initializer element is not constant.

    Specifically on the byte count, which for me, varies every time this function is called. My i2c address is also variable, as my device address varies in normal operation vs ROM mode. Can the byte count and I2C address also be in RAM? 

    I see the example twi_master_using_nrf_twi_mngr claims to be using buffers in RAM, but it is using constants for the byte count and device address.

  • If I switch back to the nrf_drv_twi_tx/nrf_drv_twi_rx API, is there a way to disable the callback?
    It looks like it is trying to invoke the callback from the macro 

    NRF_TWI_MNGR_DEF - 

    static nrf_twi_mngr_cb_t CONCAT_2(_nrf_twi_mngr_name, _cb); \

    I tried to set the callback as NULL but it is read only. Otherwise, this is what I get 



    I'm looking for a sensible way to use the nrf_drv_twi_tx/rx API's alongside the twi_mngr so I don't have to rewrite all the other things using the manager. 

    edit - If I do this before the application uses twi_mngr, I can run nrf_drv_twi_init, then nrf_drv_twi_uninit. Then twi_mngr can be used freely.

Related