Resetting Twim

Hello, im trying to implement PingPong buffer( i guess that's the name of mechanism )

the way i  have it currently done is.

#include "twim_data.h"
#include "twim_r.h"


#define MASTER_SCL_PIN 3
#define MASTER_SDA_PIN 4
sensor_data_t BUFF1[8];
sensor_data_t BUFF2[8];

#define BME280_I2C_ADDRESS 0x76
// SYF 


LOG_MODULE_REGISTER(twim_r, LOG_LEVEL_INF);
uint8_t counter = 0; 
struct k_work work;
struct twi_info {

};
sensor_data_t *ptr_curr = BUFF1;
bool dupa = true; 
int XD = 1; 
// Za kazdym razem jak stanie sie counter >8 to zresetuj buffor. 
void show_dump_twim(struct k_work *work)
{
   
    
    if(ptr_curr == BUFF1)
    {
        LOG_INF("BUFF1\n");
    }
    else
    {
        LOG_INF("BUFF2\n");
    }
    LOG_HEXDUMP_INF(ptr_curr, 48, "TWIM RX BUFFER");

    //disable twim with buff A
    nrfx_twim_disable(&mytwim.instance);

    //init twim with buff B 

    twim_init(&mytwim);
}

void Buff_reset(uint8_t *ptr_buff)
{   

    if (ptr_buff != NULL){
        memset(ptr_buff, 0, sizeof(sensor_data_t)*8);
        LOG_HEXDUMP_INF(ptr_buff, 48, "RESET BUFFER");

    }
}



static void twim_handler(nrfx_twim_evt_t const *p_event, void *p_context)
{
    if(counter >= 8){
        counter = 0;
        k_work_submit(&work);

        
    }
    

    LOG_INF("TWIM HANDLER\n");

    if (p_event->type == NRFX_TWIM_EVT_DONE)
    {

        LOG_INF("TWIM EVT DONE\n");
        counter++;
        LOG_INF("COUNTER: %d\n", counter);

    }
    if (p_event->type == NRFX_TWIM_EVT_BUS_ERROR)
    {

        LOG_INF("BUS ERROR");
    }
    if (p_event->type == NRFX_TWIM_EVT_ADDRESS_NACK)
    {

        LOG_INF("ADDRESS NACK\n");
    }
}

void twim_init(twim_config_t *twim)
{
    // if (twim->read_buffer == NULL && twim->write_buffer == NULL)
    // {
    //     LOG_INF("READ BUFFER IS NULL");
    // }
    if(dupa ==  true) {
        k_work_init(&work, show_dump_twim);
        dupa = false; 
    }
    pp_buffer_swap(twim);
    void *p_context = ptr_curr;

    nrfx_twim_config_t twim_config = {
        .scl_pin = MASTER_SCL_PIN,
        .sda_pin = MASTER_SDA_PIN,
        .frequency = NRF_TWIM_FREQ_100K,
        .interrupt_priority = NRFX_TWIM_DEFAULT_CONFIG_IRQ_PRIORITY,
        .hold_bus_uninit = true
    };
    nrfx_err_t status; 
    if(XD == 1){
     status = nrfx_twim_init(&twim->instance, &twim_config, twim_handler, p_context);
     if (status != NRFX_SUCCESS)
    {
        LOG_ERR("TWIM INIT FAILED\n");
    }

    }

    
    if(status == NRFX_ERROR_ALREADY_INITIALIZED){

        LOG_INF("TWIM ALREADY INITIALIZED\n");
    }

    nrfx_twim_enable(&twim->instance);

    nrfx_twim_xfer_desc_t twim_xfer_desc = NRFX_TWIM_XFER_DESC_TXRX(BME280_I2C_ADDRESS, // BME280 I2C
                                                                    twim->write_buffer,  // Buffer z adresem rejestru TX
                                                                    1,                  // Amount
                                                                    ptr_curr,   // RX buffer
                                                                    twim->read_len       // Amount
    );

    status = nrfx_twim_xfer(&twim->instance, &twim_xfer_desc, NRFX_TWIM_FLAG_RX_POSTINC | NRFX_TWIM_FLAG_REPEATED_XFER);

    if (status != NRFX_SUCCESS)
    {
        LOG_ERR("TWIM XFER FAILED\n");
    }

    Buff_reset(ptr_curr);
    XD = 2;
}


void pp_buffer_swap(twim_config_t *twim)
{
    if (ptr_curr == BUFF1)
    {
        ptr_curr = BUFF2;
    }
    else
    {
        ptr_curr = BUFF1;
    }
}


 Here comes the problem what should i do to reinitialize(if its needed) the  twim instance with different buffer.
should i just do nrfx_twim_disable(my instance) and change nrfx_twim_xfer_desc_t to my second buffer then enable it, or should i do nrfx_twim_uninit. and do everything again.

PS: Dont mind my stupid bools checkers, ive tried to figure it out myself with easiest implementation in my head.

Parents
  • Hi,

    You provide new buffer pointer every time you call nrfx_twim_xfer(), both for TX and RX buffers. If you want to swap between two different sets of buffers, you can define two nrfx_twim_xfer_desc_t objects to pass to nrfx_twim_xfer(). Once you call this function, the transfer will start (since you are the master), and the buffers will be clocked out/filled, based on the requested transfer lengths. When the transfer is completed, the buffers are free to be reused or processed. It is not necessary to disable to uninit the TWIM driver to swap the buffers, when you start a new transfer by calling nrfx_twim_xfer(), new buffers can be provided. If you want to switch buffers in the middle of a transfer for some reason, you should first wait for the previous transfer to complete by waiting for the NRFX_TWIM_EVT_DONE before starting a new transfer.

    Best regards,
    Jørgen

Reply
  • Hi,

    You provide new buffer pointer every time you call nrfx_twim_xfer(), both for TX and RX buffers. If you want to swap between two different sets of buffers, you can define two nrfx_twim_xfer_desc_t objects to pass to nrfx_twim_xfer(). Once you call this function, the transfer will start (since you are the master), and the buffers will be clocked out/filled, based on the requested transfer lengths. When the transfer is completed, the buffers are free to be reused or processed. It is not necessary to disable to uninit the TWIM driver to swap the buffers, when you start a new transfer by calling nrfx_twim_xfer(), new buffers can be provided. If you want to switch buffers in the middle of a transfer for some reason, you should first wait for the previous transfer to complete by waiting for the NRFX_TWIM_EVT_DONE before starting a new transfer.

    Best regards,
    Jørgen

Children
  • I just want to have continous reading from TWIM without any delays, so i should just change  nrfx_twim_xfer_desc_t whenever 1 transfer is completed and that's all? In pseudo code if would be like this:

    - If counter >=8  submit to queue with old buffer and change nrfx_twim_xfer_desc_t to new buffer? 

     

  • Dzolo2k1 said:
    I just want to have continous reading from TWIM without any delays, so i should just change  nrfx_twim_xfer_desc_t whenever 1 transfer is completed and that's all?

    The TWIM peripheral supports EasyDMA, which will transfer data directly from/to RAM without any CPU intervention. If you configure nrfx_twim_xfer_desc_t to write one byte and read 8 bytes, this will happen automatically when the transfer is started, there is no need for the CPU to be involved. The lengths of the buffers should be decided the datasheet of the sensor that you are reading.

    It is possible to switch buffers in HW using the EasyDMA ArrayList feature as well, if you want to do multiple transfers after each other without changing the buffers using the CPU, but this is more advanced.

  • So I know the first section of ur reply. But im a bit confused right now. My question is still: what should I do to change buffers( 1 2 1 2 1 2 - thats the sequence i want to achieve ). I get first lets say 8 B then it is send to workQ where its used for some data processing, and the second buffer is already running, then it swaps again and again and again. How do i do it- there is no information about it in documentation that can help me. 

  • Hi,

    Like I said in my previous answer, you need to provide a buffer every time you call nrfx_twim_xfer(). If you are not using EasyDMA Arraylist feature, you can simply use a variable to keep track of the current buffer whenever it is called:

    static uint8_t tx_buffer[1] = {0x00};
    static uint8_t rx_buffer1[8];
    static uint8_t rx_buffer2[8];
    static uint8_t current_buffer = 0;
    
    static nrfx_twim_xfer_desc_t twim_xfer_desc1 = NRFX_TWIM_XFER_DESC_TXRX(BME280_I2C_ADDRESS, tx_buffer, 1, rx_buffer1, 8);
    static nrfx_twim_xfer_desc_t twim_xfer_desc2 = NRFX_TWIM_XFER_DESC_TXRX(BME280_I2C_ADDRESS, tx_buffer, 1, rx_buffer2, 8);
    
    void twim_transfer(void)
    {
    	if(current_buffer == 0)
    	{
    		nrfx_twim_xfer(&twim->instance, &twim_xfer_desc1, NULL);
    		current_buffer = 1;
    	}
    	else
    	{
    		nrfx_twim_xfer(&twim->instance, &twim_xfer_desc2, NULL);
    		current_buffer = 0;
    	}
    }
    
    static void twim_handler(nrfx_twim_evt_t const *p_event, void *p_context)
    {
    	if(p_event->type == NRFX_TWIM_EVT_DONE)
    	{
    		if(current_buffer == 0)
    		{
    			// process rx_buffer1
    		}
    		else
    		{
    			// process rx_buffer2
    		}
    	}
    }

    I see that you have set NRFX_TWIM_FLAG_RX_POSTINC/NRFX_TWIM_FLAG_REPEATED_XFER in your code, which relates to the EasyDMA ArrayList feature. However, your posted code does not include any details on the length of the RX in your transfer, how the sensor_data_t type is declared, how next transfer is started, etc. If you are planning to use this, please include your full project in the ticket.

    Best regards,
    Jørgen

Related