Scheduling Issues Between SPIM and NUS Integration

I am programming with the nRF52840DKs. [Toolchain Manager: v1.3.0, IDE: Visual Studio Code (VSCode), SDK: ncs v2.6.0, window11 pro]

I am currently working on integrating 'NUS_peripheral' and 'SPIM'.

My goal: communicate with the ADC via SPIM and transmit the collected data via Bluetooth.

The initialization of both functions has been successful; however, I am uncertain about how to effectively manage the tasks between NUS_peripheral and SPIM.

Currently, I am attempting the following approach, but it is not yielding the desired results:

  • SPIM communicates at regular intervals using a timer and PPI.
  • BLE sends data by calling the bt_nus_send() function within a separate thread.

Below is the main part of the code.

nrfx_spim_t spim1_inst = NRFX_SPIM_INSTANCE(SPIM_INST_IDX);
nrfx_timer_t timer1_inst = NRFX_TIMER_INSTANCE(TIMER_INST_IDX);
nrfx_gpiote_t gpiote_inst = NRFX_GPIOTE_INSTANCE(GPIOTE_INST_IDX);
nrf_ppi_channel_t ppi_channel_spi_start;
nrf_ppi_channel_t ppi_channel_spi_end;
nrf_ppi_channel_t ppi_channel_spi_count;


#define STACKSIZE CONFIG_BT_NUS_THREAD_STACK_SIZE
#define PRIORITY 7 

void spim1_handler(nrfx_spim_evt_t const * p_event, void * p_context) {   
   // LOG_INF("spim1_handler - %d", spi_counter);
    if ((spi_counter == 29) || (spi_counter > 29 && (spi_counter % 18 == 11))) {
        spim1_inst.p_reg->TXD.PTR = (uint32_t)spim_tx_buf_repeated[0];
    } 

    if ( (spi_counter > 29) && (spi_counter % 1000 == 0)) {
        spim1_inst.p_reg->RXD.PTR = (uint32_t)spim_rx_buf_A[0];
        spi_counter = 30;
    }

    spi_counter++;

    if (spi_counter == 0) {
        spi_counter = 30; 
    }
}

void timer0_handler(nrf_timer_event_t event_type, void * p_context){   

} 

void peripheral_setup(void){
    //LOG_INF("main - peripheral_setup");
    nrfx_err_t error;
    (void)error;
    
    /*  GPIOTE Setting */
    static const nrfx_gpiote_output_config_t output_config = {
        .drive = NRF_GPIO_PIN_S0S1,
        .input_connect = NRF_GPIO_PIN_INPUT_DISCONNECT,
        .pull = NRF_GPIO_PIN_NOPULL,
    };
    const nrfx_gpiote_task_config_t task_config = {
        .task_ch = out_channel,
        .polarity = NRF_GPIOTE_POLARITY_TOGGLE,
        .init_val = NRF_GPIOTE_INITIAL_VALUE_HIGH,
    };

    error = nrfx_gpiote_output_configure(&gpiote_inst, SS_PIN_MASTER, &output_config, &task_config);
    nrfx_gpiote_out_task_enable(&gpiote_inst, SS_PIN_MASTER);

    /*  SPIM 1 Setting */
    nrfx_spim_config_t spim1_config = NRFX_SPIM_DEFAULT_CONFIG(SCK_PIN_MASTER,
                                                            MOSI_PIN_MASTER,
                                                            MISO_PIN_MASTER,
                                                            NRF_SPIM_PIN_NOT_CONNECTED);
    spim1_config.frequency      = NRFX_MHZ_TO_HZ(8);
    error = nrfx_spim_init(&spim1_inst, &spim1_config, spim1_handler,0);

    nrfx_spim_xfer_desc_t spim1_xfer_desc = NRFX_SPIM_XFER_TRX((uint8_t*)spim_tx_buf_initial, 2, (uint8_t*)spim_rx_buf_A, 2);
    uint32_t spim1_flags = NRFX_SPIM_FLAG_HOLD_XFER | NRFX_SPIM_FLAG_REPEATED_XFER; 
    error = nrfx_spim_xfer(&spim1_inst, &spim1_xfer_desc, spim1_flags);
    spim1_inst.p_reg->TXD.PTR = (uint32_t)spim_tx_buf_initial[0];
    spim1_inst.p_reg->TXD.MAXCNT = 2;
    spim1_inst.p_reg->TXD.LIST =SPIM_TXD_LIST_LIST_ArrayList << SPIM_TXD_LIST_LIST_Pos;
    spim1_inst.p_reg->RXD.PTR = (uint32_t)spim_rx_buf_A[0];
    spim1_inst.p_reg->RXD.MAXCNT = 2;
    spim1_inst.p_reg->RXD.LIST = SPIM_RXD_LIST_LIST_ArrayList << SPIM_RXD_LIST_LIST_Pos;

    /*  TIMER 0 Setting */
    nrfx_timer_config_t timer0_config = NRFX_TIMER_DEFAULT_CONFIG(16000000);
    timer0_config.bit_width          = NRF_TIMER_BIT_WIDTH_32,
    error = nrfx_timer_init(&timer1_inst, &timer0_config, timer0_handler);
    nrfx_timer_clear(&timer1_inst);
    k_sleep(K_MSEC(2000));

    uint32_t desired_ticks = nrfx_timer_us_to_ticks(&timer1_inst, TIME_TO_WAIT_US);
    nrfx_timer_extended_compare(&timer1_inst, NRF_TIMER_CC_CHANNEL0, desired_ticks, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, true);

    /*   PPI  Setting  */
    uint32_t gpiote_task_addr = nrfx_gpiote_out_task_address_get(&gpiote_inst ,SS_PIN_MASTER);    
    uint32_t timer_start_compare_event_addr = nrfx_timer_compare_event_address_get(&timer1_inst, NRF_TIMER_CC_CHANNEL0);
    uint32_t spi_start_task_addr   = nrfx_spim_start_task_address_get(&spim1_inst);
    uint32_t spi_end_evt_addr = nrfx_spim_end_event_address_get(&spim1_inst);


    // Timer reaches the desired tick -> GPIOTE toggle(off), SPI start
    error = nrfx_gppi_channel_alloc(&ppi_channel_spi_start);
    nrfx_gppi_channel_endpoints_setup(ppi_channel_spi_start, timer_start_compare_event_addr, gpiote_task_addr);
    nrfx_gppi_fork_endpoint_setup(ppi_channel_spi_start, spi_start_task_addr);
    // SPI tx-rx transmission ends -> GPIOTE toggle(on)
    error = nrfx_gppi_channel_alloc(&ppi_channel_spi_end);
    nrfx_gppi_channel_endpoints_setup(ppi_channel_spi_end, spi_end_evt_addr, gpiote_task_addr);
}



int main(void){
    nrfx_err_t status;
    (void)status;
   	int err;
    
    initialization_command();

   	bt_conn_cb_register(&conn_callbacks); 
    
    err = bt_conn_auth_info_cb_register(&conn_auth_info_callbacks); 
    LOG_INF("main - bt_conn_auth_info_cb_register: %d",err);
    
    err = bt_enable(NULL);
    LOG_INF("main - bt_enable: %d",err);

    if (IS_ENABLED(CONFIG_SETTINGS)) {
		settings_load();
	}

    err = bt_nus_init(&nus_cb);

    err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd));

	k_sem_take(&param_ok, K_FOREVER);
	k_sem_take(&data_length_ok, K_FOREVER);
	k_sem_take(&phy_ok, K_FOREVER);

    /************ SPIM ************/ 
    #if defined(__ZEPHYR__)
		IRQ_CONNECT(NRFX_IRQ_NUMBER_GET(NRF_SPIM_INST_GET(SPIM_INST_IDX)), IRQ_PRIO_LOWEST,     
										NRFX_SPIM_INST_HANDLER_GET(SPIM_INST_IDX), 0, 0);
        IRQ_CONNECT(NRFX_IRQ_NUMBER_GET(NRF_TIMER_INST_GET(TIMER_INST_IDX)), IRQ_PRIO_LOWEST, 
                                        NRFX_TIMER_INST_HANDLER_GET(TIMER_INST_IDX), 0, 0);
	#endif

    status = nrfx_gpiote_init(&gpiote_inst, NRFX_GPIOTE_DEFAULT_CONFIG_IRQ_PRIORITY);
    LOG_INF("main - nrfx_gpiote_init: %d", status);

    status = nrfx_gpiote_channel_alloc(&gpiote_inst, &out_channel);
    LOG_INF("main - nrfx_gpiote_channel_alloc: %d", status);

    peripheral_setup();

    LOG_INF(" spim_rx_buf_A[0][0]: %p", (void*)&spim_rx_buf_A[0][0]);
    LOG_INF(" spim_rx_buf_A[%d][0]: %p",rx_data_size-1, (void*)&spim_rx_buf_A[rx_data_size-1][0]);

    nrfx_gpiote_out_task_enable(&gpiote_inst, SS_PIN_MASTER);
    nrfx_gppi_channels_enable(BIT(ppi_channel_spi_start));
    nrfx_gppi_channels_enable(BIT(ppi_channel_spi_end));
    nrfx_timer_enable(&timer1_inst);
    k_sem_give(&nus_start);
    
	return 0;
}

void ble_write_thread(void){
	int ret;
	k_sem_take(&nus_start, K_FOREVER);
	LOG_INF("Starting BLE Write Thread");
	while (1) {
        ret = bt_nus_send(current_conn, data_to_central, MTU_SIZE);
	    LOG_INF("bt_nus_send: %d", ret);
		if (k_sem_take(&disconnect_sem, K_NO_WAIT) == 0){
            LOG_INF("Disconnected, exiting BLE Write Thread");
            return;
        }
	}
}

K_THREAD_DEFINE(ble_write_thread_id, 1024, ble_write_thread, NULL, NULL, NULL, PRIORITY, 0, 0);

 

Related