It cannot use SPI to control TI cc1101 properly.

Hi friend,

I am using SDK16.0 and softdevice is S140 7.0.1 version. But SPI can only send out 1 byte. It can't call back the function of spi_event_handler, so my code is locked while checking spi_xfer_done.

Can someone help me? My code snippet is below.

Thank you in advance.

static void cc1101_gpio_init(void)
{
    nrf_gpio_pin_dir_set(CC1101A_SS_PIN, NRF_GPIO_PIN_DIR_OUTPUT);
    nrf_gpio_pin_set(CC1101A_SS_PIN);
    nrf_gpio_pin_dir_set(CC1101B_SS_PIN, NRF_GPIO_PIN_DIR_OUTPUT);
    nrf_gpio_pin_set(CC1101B_SS_PIN);

    nrf_gpio_pin_dir_set(CC1101A_PWR_PIN, NRF_GPIO_PIN_DIR_OUTPUT);
    nrf_gpio_pin_clear(CC1101A_PWR_PIN);
    nrf_gpio_pin_dir_set(CC1101B_PWR_PIN, NRF_GPIO_PIN_DIR_OUTPUT);
    nrf_gpio_pin_clear(CC1101B_PWR_PIN);
}

void spi_event_handler(nrf_drv_spi_evt_t const * p_event, void *p_context)
{
    spi_xfer_done = true;
}

void cc1101_spi_init(void)
{
    nrf_drv_spi_config_t const spi_config =
    {
        .sck_pin        = CC1101_SCK_PIN,
        .mosi_pin       = CC1101_MOSI_PIN,
        .miso_pin       = CC1101_MISO_PIN,
        .ss_pin         = NRF_DRV_SPI_PIN_NOT_USED,
        .irq_priority   = SPI_DEFAULT_CONFIG_IRQ_PRIORITY,
        .orc            = 0xFF,
        .frequency      = NRF_DRV_SPI_FREQ_125K,
        .mode           = NRF_DRV_SPI_MODE_0,
        .bit_order      = NRF_DRV_SPI_BIT_ORDER_MSB_FIRST
    };

    APP_ERROR_CHECK(nrf_drv_spi_init(&m_spi, &spi_config, spi_event_handler, NULL));
}

//|==================== SPI Initialisation for CC1101 =========================|
void cc1101_spi_begin(void)
{
   /* configure SPI */
    cc1101_gpio_init();
    cc1101_spi_init();
}
//-------------------------------[end]------------------------------------------

uint8_t cc1101_spi_putc(uint8_t data)
{
    uint8_t statusByte;

    spi_xfer_done = false;
    APP_ERROR_CHECK(nrf_drv_spi_transfer(&m_spi, &data, 1, NULL, 0));
    while(!spi_xfer_done) {}
    spi_xfer_done = false;
    APP_ERROR_CHECK(nrf_drv_spi_transfer(&m_spi, NULL, 0, &statusByte, 1));
    while(!spi_xfer_done) {}
}

//----------------------[CC1101 init functions]---------------------------------
uint8_t cc1101_begin(uint8_t *My_addr)
{
    uint8_t CC1101_freq_select, CC1101_mode_select, CC1101_channel_select;
    uint8_t partnum, version;

    cc1101_spi_begin();                         //inits SPI Interface
//    cc1101_reset();                             //CC1101 init cc1101_reset

    cc1101_spi_write_strobe(SFTX);nrf_delay_us(100);//flush the TX_fifo content
    cc1101_spi_write_strobe(SFRX);nrf_delay_us(100);//flush the RX_fifo content

    partnum = cc1101_spi_read_register(PARTNUM); //reads CC1101 partnumber
    version = cc1101_spi_read_register(VERSION); //reads CC1101 version number

    //checks if valid Chip ID is found. Usualy 0x03 or 0x14. if not -> abort
    if(version == 0x00 || version == 0xFF)
    {
        NRF_LOG_INFO("no CC11xx found!");
        return FALSE;
    }

    NRF_LOG_INFO("Partnumber:%x", partnum);
    NRF_LOG_INFO("Version:%x", version);

    //default settings
    //*My_addr = 0x00;
    CC1101_freq_select = 0x02;    //433.92MHz
    CC1101_mode_select = 0x07;    //gfsk 9.6kbps
    CC1101_channel_select = 0x00;

    //set modulation mode
    cc1101_set_mode(CC1101_mode_select);
    //set ISM band
    cc1101_set_ISM(CC1101_freq_select);
    //set channel
    cc1101_set_channel(CC1101_channel_select);

    //set my receiver address
    cc1101_set_myaddr(*My_addr);                  //set addr
    NRF_LOG_INFO("...done");
    cc1101_receive();                            //set CC1101 in cc1101_receive mode
    return TRUE;
}

  • Hello,

    so my code is locked while checking spi_xfer_done.

    So from where are you calling this? (the function that is calling nrf_drv_spi_transfer() and while (!spi_xfer_done))?

    Are you calling it from your main() function, or from some interrupt? (GPIO change, button press, bluetooth event, other interrupt...)

    Make sure that your spi_xfer_done variable is a volatile, wherever you declare it. E.g.:

    volatile bool spi_xfer_done = false;

    This is to make sure that optimization doesn't mess with it and assumes it knows it's value without actually checking whether it was changed externally. 

    Then, if it still doesn't work, I assume that it is because you are waiting for spi_xfer_done to be set to true from inside another interrupt with the same or higher priority, not allowing access to the SPI interrupt that is supposed to set spi_xfer_done to true. Is that the case? If so, what interrupt are you waiting in?

    Best regards,

    Edvin

  • Hi Edvin,

    I  put my SPI code in the call back function of bsp_event_handler(bsp_event_t event). I moved it to main loop, then it works fine.

    Thank you very much.

    Ted Wu

  • Ok, then that was the case. If you want to keep it in the bsp_event_handler, you need to make sure that the SPI has higher priority than the bsp_event_handler. 

    Look for SPI_DEFAULT_CONFIG_IRQ_PRIORITY and NRFX_SPI_DEFAULT_CONFIG_IRQ_PRIORITY in sdk_config.h and set them to a higher priority (smaller number). Please note that if you are using the SoftDevice (Bluetooth Low Energy stack), then you need to make sure that you don't use the priorities that are reserved for the SoftDevice. You can see what priorities that are reserved here:

    https://infocenter.nordicsemi.com/topic/sds_s140/SDS/s1xx/processor_avail_interrupt_latency/exception_mgmt_sd.html?cp=4_7_4_0_15_1

    Best regards,

    Edvin

Related