I am seeing a rare case where sometimes CC1200 goes to SETTLING state after doing successful CCA.
In RX mode G0 is configured as PKT_CRC_OK: CC120X_IOCFG0 = 19
In TX mode G0 is configured as PKT_SYNC_RXTX: CC120X_IOCFG0 = 6
G2 is configured as CARRIER_SENSE_VALID: CC120X_IOCFG2 = 16
Here are other important registers:
{CC120X_PKT_CFG2, 0x0C}, // CCA mode: Indicates clear channel when RSSI is below threshold and currently not receiving a packet
{CC120X_RFEND_CFG1, 0x1F}, // radio goes automatically to FSTXON to send ACK message after receiving a good packet
{CC120X_RFEND_CFG0, 0x30}, // radio goes automatically to RX to listen incoming message after sending a packet
I am doing CCA in this way:
error_t m_do_cca() {
uint8_t counter = 0;
uint8_t state = m_get_chip_state();
if (state == CC_STATE_OFF){
return EOFF;
}
else if (state == CC_STATE_CALIBRATE || state == CC_STATE_SETTLING) {
// we can only do CCA in RX mode, so check for that
// if we're idle, calibrating or settling, return ERETRY so the sender will try again
return ERETRY;
}
else if (state == CC_STATE_RXFIFO_OVERFLOW) {
// it is for sanity check
warn4("RXFIFO overflow");
call Spi.strobe(CC120X_SIDLE);
call Spi.strobe(CC120X_SFRX);
#warning radio goes to IDLE after SFRX, who else puts it to RX beside LPL
return FAIL;
}
else if (state == CC_STATE_FSTXON) {
// radio goes automatically to FSTXON to send out ack packet after receive
// that is why we are in this state
}
else if (state != CC_STATE_RX) {
err4("ASSERT wrong state %u", state);
// what if we are in IDLE for some reason, should we switch to RX?
return ERETRY;
}
// carrier sense not yet valid
if (!call G2.get()) {
return ERETRY;
}
call Spi.strobe(CC120X_STX);
while (1) {
state = m_get_chip_state();
counter++;
// check if radio is still in RX
// it means channel is not clear and radio stays in RX
if (counter >= 5 && state == CC_STATE_RX) {
return FAIL;
}
if (state == CC_STATE_TX) {
break;
}
if (counter >= 15) {
return FAIL;
}
}
// just to be sure read out radio state to check if CCA was successful or failed
// 1 - CCA failed, radio stays in RX mode
// 0 - CCA succeeded, radio goes to TX mode
if (!(call Spi.readRegister(CC120X_MARC_STATUS0) & (1<<2))) {
return SUCCESS;
}
else {
// if CCA fails radio stays in RX mode
return FAIL;
}
}
Logic:
- radio must be in RX state before doing CCA and G2 pin indicating CARRIER_SENSE_VALID must be set
- if STX is strobed and radio stays in RX, then channel is considered busy and MARC_STATUS0 must have set TXONCCA_FAILED bit
- if STX is strobed and radio changes state to TX, then MARC_STATUS0 TXONCCA_FAILED bit must be 0
Lets say CCA succeeded, then another function is called that configures G0 pin to PKT_SYNC_RXTX to catch packet sent interrupt. This is TinyOS code hence those "call" keywords.
void m_write_to_txfifo() {
uint8_t* data = (uint8_t*) call ChipconPacket.getHeader(m_tx_msg);
uint8_t length = call ChipconPacket.getPacketLength(m_tx_msg);
uint8_t power = call PacketTransmitPower.isSet(m_tx_msg) ? call PacketTransmitPower.get(m_tx_msg) : m_default_tx_power;
ASSERT(m_tx_msg != NULL);
if (power != m_tx_power) {
m_tx_power = power;
//call Spi.writeRegister(PATABLE, m_tx_power);
}
// set GDO0 to de-assert (falling) if packet is sent.
atomic {
m_waiting_rx_int = FALSE;
call Spi.writeRegister(CC120X_IOCFG0, 0x06);
call G0Interrupt.enableFallingEdge();
}
// TODO, how to put timestamp
// signal HalChipconControl.txStart(call LocalTime.get());
call Spi.burstWriteFifo(data, length);
call CSn.set();
call CSn.clr();
}
I do not assume that after successful CCA radio goes automatically to SETTLING or to some other state from TX. However this exactly sometimes happening. Fortunately I was able to catch it with logic analyzer. Channels 0-7 are device 1 SPI trace and channels 8-15 are device 2 SPI trace. Notice that these devices are sending almost at the same time. Device 1 start 9 us earlier that device 2.
Look device 2 SPI trace where successful CCA can be seen. However actually if m_write_to_txfifo() is started radio is already in SETTLING state. This is unexpected behavior for me.
Question is if I am doing something wrong in the first place or this is normal and I should try to handle it?
Here is another picture showing strange radio statuses if TXFIFO is filled (being in the wrong state), notice that G2 goes low:
After that radio is in TX_FIFO_ERR state. Firstly radio is put back to IDLE and then FIFO is flushed with SFTX:
The problem is that G2 pin indicating CARRIER_SENSE_VALID never goes high again after this issue therefore cca function does not work anymore. What should I do handle this error correctly?
NB: writing this post I realized that SFTX and SFRX can be called immediately if XX_FIFO_ERR state is detected, I issued SIDLE before those commands maybe this is incorrect?
Andres