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(¶m_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);