This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Hi everyone,
I have an issue with SSI communication, and I need guidance to understand better or to handle the exception which is generated by the code.
- I have a custom board with the tm4c1294ncpdt Tiva C processor
- I have 4x digital sensors ( icm20602 ) which I read from and are connected to the custom board via USB-c
- These sensors can be removed while in operation, and when the sensor is removed the data gathering is stopped and a software reset is triggered on the tiva, to start from the beginning.
Sometimes this sequence does not happen and it goes into a loop then after 10s it performs the reset and everything is fine
I suspect that when I remove the sensor at the exact time when I reed the data from it, it enters into the delay loop
code which is used to red the sensor data into a buffer and then swapping the bytes of the acc and gyro
uint8_t read_icm20602_sensor(uint8_t sensor_id, uint8_t timeout, uint8_t *buffer) { uint8_t drdy_data; uint8_t whoamy_data; uint8_t icm_buff[14]; select_digi_sensor(sensor_id); // SSI1_device_read(WHO_AM_I, 1, &whoamy_data); // if(whoamy_data != WHO_AM_I_DATA_OK) return 0; uint16_t buffer_index = ICM20602_DATA_SIZE * (sensor_id -1); while(timeout--){ SSI1_device_read(INT_STATUS, 1, &drdy_data); if ((drdy_data & 0x01) == 0x01){ SSI1_device_read(ACCEL_XOUT_H, 14, icm_buff); icm20602_buffer_byte_swap(&buffer[buffer_index], icm_buff); return 1; } } return 0; }
function where the SSI read and transmit is implemented
unsigned char SSI1_transmit_data(unsigned char data) { uint32_t rx_buffer; while(SSIDataGetNonBlocking(SSI1_BASE, &rx_buffer)); SSIDataPut(SSI1_BASE, data); while(SSIBusy(SSI1_BASE)); SSIDataGet(SSI1_BASE, &rx_buffer); // while(SSIBusy(SSI1_BASE));// added for testing purpose, this waits till the buffer is full. return rx_buffer & 0x00FF; } void SSI1_device_read(uint8_t address, uint8_t size, uint8_t *buffer) { uint32_t i = 0; SSI1_cs_on(); address |= 0x80; SSI1_transmit_data(address); for(i = 0; i < size; i++){ buffer[i] = SSI1_transmit_data(0xFF); } SSI1_cs_off(); }
Do I oversee something on in the code or the handling of these kind of functionality
void read_4_sensor_device(uint8_t sensorId, uint8_t *buffer) { if(sensorId == 1){ // ICM20602 1 if device is available read data from it if (digi_sensor_status1){ digi_sensor_status1 = read_icm20602_sensor(SENSOR_ID_1, READ_TIMEOUT, &digi_sensor_buffer); } else{ if(isavailable_icm20602(SENSOR_ID_1)){ if (check_digi_byte() == 1){ digi_sensor_status1 = 1; // no restart }else{ // restart indicated digi_sensor_current |= SENSOR_ACTIVE_1; } } else{ digi_sensor_current &= ~SENSOR_ACTIVE_1; } } } if(sensorId == 1){ // ICM20602 2 if device is available read data from it if (digi_sensor_status2){ digi_sensor_status2 = read_icm20602_sensor(SENSOR_ID_2, READ_TIMEOUT, &digi_sensor_buffer); } else{ if(isavailable_icm20602(SENSOR_ID_2)){ if (check_digi_byte() == 1){ digi_sensor_status2 = 1; // no restart }else{ // restart indicated digi_sensor_current |= SENSOR_ACTIVE_2; } } else{ digi_sensor_current &= ~SENSOR_ACTIVE_2; } } } if(sensorId == 2){ // ICM20602 3 if device is available read data from it if (digi_sensor_status3){ digi_sensor_status3 = read_icm20602_sensor(SENSOR_ID_3, READ_TIMEOUT, &digi_sensor_buffer); } else{ if(isavailable_icm20602(SENSOR_ID_3)){ if (check_digi_byte() == 1){ digi_sensor_status3 = 1; // no restart }else{ // restart indicated digi_sensor_current |= SENSOR_ACTIVE_3; } } else{ digi_sensor_current &= ~SENSOR_ACTIVE_3; } } } if(sensorId == 2){ // ICM20602 4 if device is available read data from it if (digi_sensor_status4){ digi_sensor_status4 = read_icm20602_sensor(SENSOR_ID_4, READ_TIMEOUT, &digi_sensor_buffer); } else{ if(isavailable_icm20602(SENSOR_ID_4)){ if (check_digi_byte() == 1){ digi_sensor_status4 = 1; // no restart/ }else{ // restart indicated digi_sensor_current |= SENSOR_ACTIVE_4; } } else{ digi_sensor_current &= ~SENSOR_ACTIVE_4; } } } //Update the digital sensor statuses digi_sensor_status &= 0x00; digi_sensor_status = digi_sensor_status1 << DIGI_SENSOR_INDEX_1 | digi_sensor_status2 << DIGI_SENSOR_INDEX_2 | digi_sensor_status3<< DIGI_SENSOR_INDEX_3 | digi_sensor_status4 << DIGI_SENSOR_INDEX_4; // TODO: Debug current digital sensor status current_state = digi_sensor_status; // TODO: Restart Handler if(DIGI_SENSOR_AUTO_RESET){ // Currently running configuration if(digi_sensor_status != digi_sensor_current && restart_timeout < 2){ // LEDs GPIO_write(Board_LED1,1); GPIO_write(Board_LEDS5,1); restart_timeout = 1; // start counter - Enable the resetting variable and function } if (restart_timeout>0) // increment after once the restart_timeout=1 restart_timeout++; if (restart_timeout>RESTART_TIMEOUT){ // Maybe to send the restart sequence as a semaphore Semaphore_post(sw_simulated_reset_sem_handle); } }else{ if( digi_sensor_status != sensors_frozen_stats){ // Default frozen state removed // start reconfiguration procedure Semaphore_post(hot_digi_reconfigure_sem_handle); // hot_digi_reconfigure(); // update: digi_sensor_status if(digi_sensor_status == sensors_frozen_stats){ GPIO_write(Board_LED1, 0); GPIO_write(Board_LEDS5,0); } else{ GPIO_write(Board_LED1, 1); GPIO_write(Board_LEDS5,1); } } else{ GPIO_write(Board_LED1,0); GPIO_write(Board_LEDS5,0); // DS4 LED } } }
RTOS is used on the tiva.
After testing more, I saw that the code continues executing but it still did not set the LED, it is like it never gets into line 98. But when I check in debug I see that it is gathering digital data and the channel which is removed has -1 in it.
Hi,
I'm not familiar with icm20602. I can't really debug your long lines of code as I don't know what your application is. When you remove the sensor, what input to the processor will indicate the sensor is removed? You must have a method to detect and inform that the sensor is removed, right? Is INT/DRDY from icm20602 such a signal you can use to detect the removal of the sensor? If INT is the right signal to use then you can use to generate an interrupt to the processor. When the processor detects the interrupt, in the ISR you can post the semaphore to the task that is pending to generate a software reset. As far as I know, if the sensor is removed, your SPI interface between the processor and the sensor is cut off. I don't think you can rely on reading some status to know if the sensor is removed. That is just my opinion.
Hi,
I don't have any physical connection to determine if the sensor is connected or not. I only use the spi line and the communication for determining if the sensor is attached or not.
I read the drdy register of the icm and if data is ready than the sensor is connected and I can read the data from it. if it is zero than the processor registers it a missing sensor. The data rate which I read from the sensor is 1kHz.
Because of this solution i use the digi sensor at 8kHz sampling rate, to have data always available.
Regarding to this digital sensor, part, there is a possibility that the counting semaphores are used up, and also somehow a pin interrupt is disabled regarding other part of the code.
and now there are no counting semaphores and also the interrupt is disabled, can this go into the idle_loop which is used by the rtos.
if yes how can I set a trigger in cases of forever idle_loop , to get out of it, maybe with a software reset
I read the drdy register of the icm and if data is ready than the sensor is connected and I can read the data from it. if it is zero than the processor registers it a missing sensor.
When SPI interface is disconnected, how can you be sure your will read zero? The SSI master still drives the SPICLK and CS and expects to read from RX input. If RX is disconnected, it is most likely a floating signal which can be high or low or intermediate state. Do you have a pulldown on RX?
That is true I dont realy know, but is should clear after the second try, or not? was our assumption.
As you wrote we dont realy know. After debugging we found that when we get into this delayed reset sequence. The removed sensor still receives a one on the read of the INT_STATUS register and receives 0xFF for the sensor data.
First solution which we tried is to check the buffer for 0xFF , if 14 times 0xFF than Reset else continue.
The second solution is to just read the who_am_I register of the sensor than read the int_status reg and then the data. --- This one solved the issue, first one is also a possible solution but the second is more clean.