Hello !
I thought to have found a work around by doing a first access to by pass "the unexpected timing", but time to time it does not work !
See code of the work around tested:
void spi_transfer(enum Chip chip, unsigned char* txBuffer, size_t len, bool with_rx)
{
int ret;
int fd;
uint8_t bits;
uint32_t speed;
uint8_t mode;
unsigned short delay;
char * tx = NULL;
char * rx = NULL;
char hex_dump_tx_prefix[9] = {0};
char hex_dump_rx_prefix[9] = {0};
switch(chip){
case RADIO:
fd = st_spi.fd_radio;
speed = st_spi.speed_radio;
mode = st_spi.mode_radio;
bits = st_spi.bits_radio;
delay = st_spi.delay_radio;
strcpy(hex_dump_tx_prefix,"tx_radio");
strcpy(hex_dump_rx_prefix,"rx_radio");
break;
case RTC:
fd = st_spi.fd_rtc;
speed = st_spi.speed_rtc;
mode = st_spi.mode_rtc;
bits = st_spi.bits_rtc;
delay = st_spi.delay_rtc;
strcpy(hex_dump_tx_prefix,"tx___rtc");
strcpy(hex_dump_rx_prefix,"rx___rtc");
break;
case FLASH:
fd = st_spi.fd_flash;
speed = st_spi.speed_flash;
mode = st_spi.mode_flash;
bits = st_spi.bits_flash;
delay = st_spi.delay_flash;
strcpy(hex_dump_tx_prefix,"tx_flash");
strcpy(hex_dump_rx_prefix,"rx_flash");
break;
default:
printf("Unexpected chip value !\n");
exit_with_trace(EXIT_STATUS_SPI_ERROR, ulTraceModule, __FUNCTION__, __FILE__, __LINE__);
break;
}
tx = malloc(len);
check_malloc(tx, ulTraceModule, __FILE__, __LINE__);
rx = malloc(len);
check_malloc(rx, ulTraceModule, __FILE__, __LINE__);
memcpy (tx, txBuffer, len);
unsigned char payload_wa_radio[2] = {0x20, 0x00};
struct spi_ioc_transfer tr_wa_radio = {
.tx_buf = (unsigned long)payload_wa_radio,
.rx_buf = (unsigned long)0,
.len = 2,
.delay_usecs = delay,
.speed_hz = speed,
.bits_per_word = bits,
};
struct spi_ioc_transfer tr = {
.tx_buf = (unsigned long)tx,
.rx_buf = (unsigned long)rx,
.len = len,
.delay_usecs = delay,
.speed_hz = speed,
.bits_per_word = bits,
};
if (mode & SPI_TX_QUAD) {
tr.tx_nbits = 4;
}
else if (mode & SPI_TX_DUAL) {
tr.tx_nbits = 2;
}
if (mode & SPI_RX_QUAD) {
tr.rx_nbits = 4;
}
else if (mode & SPI_RX_DUAL) {
tr.rx_nbits = 2;
}
if (!(mode & SPI_LOOP)) {
if (mode & (SPI_TX_QUAD | SPI_TX_DUAL)) {
tr.rx_buf = 0;
}
else if (mode & (SPI_RX_QUAD | SPI_RX_DUAL)) {
tr.tx_buf = 0;
}
}
#if DBG_SPI
hex_dump(tx, len, 32, hex_dump_tx_prefix);
#endif
//toolMutexLock(&MutexSPI);
if (chip == RADIO) {
// This part of code is a workaround for the radio because the radio spi is touchy to the clock timing of
// the first spi access as the mode is set during the first access.
// The workaround consists in doing a first access without impact on the radio configuration to bypass the
// issue, and then a second access to really execute the spi command.
// For the first access, we send command "0x00, 0x20" which is interpreted by the radio "0x00, 0x10" due to the
// the clock timing. So we only do a read access at the address 0 of the config register without impact on the radio configuration.
// Let's see task #30190 for more details.
ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr_wa_radio);
if (ret < 1) {
printf("can't send spi message\n");
exit_with_trace(EXIT_STATUS_SPI_ERROR, ulTraceModule, __FUNCTION__, __FILE__, __LINE__);
}
}
ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
if (ret < 1) {
printf("can't send spi message\n");
exit_with_trace(EXIT_STATUS_SPI_ERROR, ulTraceModule, __FUNCTION__, __FILE__, __LINE__);
}
//toolMutexUnlock(&MutexSPI);
if (with_rx == true)
memcpy (txBuffer, rx, len);
#if DBG_SPI
hex_dump(rx, len, 32, hex_dump_rx_prefix);
#endif
free(rx);
free(tx);
}
See capture bellow doing a read access in loop on the radio spi. Time to time, there is also an expected CLK timing on the second access.
Conclusion:
Doing a first access to bypass the unexpected timing is not enough. I have to add something else or find another solution ...