FIFO and Dereferencing struct

I can't seem to get the FIFO to work and I think it is because I'm not dereferencing the consumer thread properly. I have reviewed the nRF Connect SDK Intermediate, data passing and exercise2 FIFO already.

Within the data_item_t struct I am adding another struct. The data seems to go into the structure ok (checked via LOG_INF), but I can't get it out properly... Assuming I did all the FIFO stuff correctly. Any advice on how to dereference, or if I setup FIFO wrong, would be appreciated.

My producer thread creates:

LOG_INF("dcheck: producer thread: cmd: %d uuid: %s d0: %d", tx_data->MYGATE.cmd, tx_data->MYGATE.uuid, tx_data->MYGATE.d0);

[00:00:51.509,948] <inf> esb_child_event_handler: dcheck: producer thread: cmd: 7 uuid: 3BD5142E4BA09B49 d0: 9696110 (this is correct)

My consumer thread:

LOG_INF("dcheck: consumer thread: cmd: %d uuid: %s d0: %d\n", command, rx_data->MYGATE.uuid, rx_data->MYGATE.d0);

//[00:00:44.177,856] <inf> esb_child_event_handler: dcheck: consumer thread: cmd: 181 uuid: d0: 0 (not correct!)

I didn't show it, but I added data to MYGATE which is why the producer LOG_INF has the correct data.

For clarification and testing the data is produced and consumed immediately, so I expect the data to be the same.

typedef struct{
	uint8_t cmd; //command
	uint8_t chan; //channel number
	uint8_t prod; //product: Gate, Wearable, etc
	uint8_t isParent; //parent or child
	char uuid[HW_ID_LEN]; //processor uuid (char array)
	uint32_t d0; //data (integer)
	uint32_t d1; //data (integer)
	uint32_t d2; //data (integer)
	uint32_t d3; //data (integer)
	uint32_t d4; //data (integer)
	uint32_t d5; //data (integer)
	uint32_t d6; //data (integer)
} Device_t;

struct data_item_t {
    void *fifo_reserved;   /* 1st word reserved for use by FIFO */
    Device_t MYGATE;
};

void producer_thread(Device_t *_mygate)
{
    /* create data item to send */
    struct data_item_t *tx_data = k_malloc(sizeof(struct data_item_t));

    tx_data->MYGATE = *_mygate;

    LOG_INF("dcheck: producer thread: cmd: %d uuid: %s d0: %d", tx_data->MYGATE.cmd, tx_data->MYGATE.uuid, tx_data->MYGATE.d0);

//[00:00:51.509,948] <inf> esb_child_event_handler: dcheck: producer thread: cmd: 7 uuid: 3BD5142E4BA09B49 d0: 9696110 (this is correct)

    /* send data to consumers */
    k_fifo_alloc_put(&my_fifo, &tx_data);
    
    //k_free(tx_data); I don't think this can be freed before reading from consumer thread?
    //or can it because I used: k_fifo_alloc_put??
}

void consumer_thread()
{
    struct data_item_t  *rx_data;

    if(k_fifo_is_empty(&my_fifo) == 0){
        LOG_ERR("FIFO1 Queue is Empty");
    }
    else{
        rx_data = k_fifo_get(&my_fifo, K_NO_WAIT);

        /* process FIFO data item */
        Device_t temp = rx_data->MYGATE;

        LOG_INF("dcheck: consumer thread: cmd: %d uuid: %s d0: %d\n", command, rx_data->MYGATE.uuid, rx_data->MYGATE.d0);

//[00:00:44.177,856] <inf> esb_child_event_handler: dcheck: consumer thread: cmd: 181 uuid:    d0: 0 (not correct!)

        k_free(rx_data);
    }
}

void send_child_data2()
{
	COMMON_CHILD_TX_DATA_TO_SEND_FLAG = true;

	int duration = MYGATE.d1 - MYGATE.d0;

	MYGATE.d0 = MYGATE.d0 + PARENT_TIMESTAMP_OFFSET;
	MYGATE.d1 = MYGATE.d1 + PARENT_TIMESTAMP_OFFSET;
    MYGATE.cmd = cmd_data;

	if(!MYGATE.isParent)
	{		
		// esb_child_ptx_send_Tx2();
        producer_thread(&MYGATE);
        consumer_thread();

		LOG_WRN("CHILD(%s) d0: %d, d1: %d (%d) (P_TS_OFFSET: %d )", MYGATE.uuid, MYGATE.d0, MYGATE.d1, duration, PARENT_TIMESTAMP_OFFSET);
	}
}

Parents Reply Children
  • Thanks! I probably copied the consumer print from my serial window out of order.

    I made progress and got the output I expected. And, I get both the queue has member and queue is empty messages. Thanks for your reply!

    void producer_thread(Device_t *_mygate)
    {
        /* create data item to send */
        struct data_item_t *buf = k_malloc(sizeof(struct data_item_t));
        if (buf == NULL){
            LOG_INF("Unable to locate memory from the heap");
            return ;
        }
    
        /* Populate the data item. This is usually done using memcpy() */
        memcpy(&buf->MYGATE, _mygate, sizeof(*_mygate));
    
        LOG_INF("dcheck: producer thread: cmd: %d uuid: %s d0: %d", buf->MYGATE.cmd, buf->MYGATE.uuid, buf->MYGATE.d0);
    
        /* send data to consumers */
        int err = k_fifo_alloc_put(&my_fifo, buf);
        if(err){
            LOG_ERR("ERROR, fifo alloc put failed: %d", err);
        }
    
        // k_free(buf); data access violation
    }
    
    void consumer_thread()
    {
        struct data_item_t  *rx_data;
    
        if(k_fifo_is_empty(&my_fifo)){
            LOG_ERR("FIFO1 Queue is Empty");
        }
        else{
            LOG_DBG("FIFO1 Queue has member");
        }
        
        rx_data = k_fifo_get(&my_fifo, K_NO_WAIT);
    
        /* process FIFO data item */
        Device_t temp = rx_data->MYGATE;
    
        LOG_INF("dcheck: consumer thread: cmd: %d uuid: %s d0: %d", temp.cmd, temp.uuid, rx_data->MYGATE.d0);
    
        k_free(rx_data);
    
        /*
            Returns Non-zero if the FIFO queue is empty.
            Returns 0 if data is available.
        */
    
        if(k_fifo_is_empty(&my_fifo)){
            LOG_ERR("FIFO2 Queue is Empty\n");
            k_sleep(K_MSEC(100));
            return;
        }
    }

Related