If I call app_timer_stop(ble_recv_timeout_id) before starting the timer, the system will crash after running at most 7 times:
#include "spim_app.h"
// #include "all_file_header.h"
#include "nrfx_spim.h"
#include "nrf_spim.h"
#include "nrf_drv_spi.h"
#include "nrf_qspi.h"
#include "nrf_gpio.h"
#include "nrf_gpiote.h"
#include "gpio_app.h"
#include "app_util_platform.h"
#include "nrf_drv_gpiote.h"
#include "nrf_delay.h"
#include "nrf_soc.h"
#include "app_error.h"
#include <stdbool.h>
#include <string.h>
#include "gh_demo.h"
/*log打印的头文件*/
#include "nrf_log.h"
#include "nrf_drv_ppi.h"
#include "uart_app.h"
#include "app_sys.h"
#include "app_task_id.h"
#include "gh_demo_config.h"
#define SPIM_PIN_INIT(_pin) nrf_gpio_cfg((_pin), \
NRF_GPIO_PIN_DIR_OUTPUT, \
NRF_GPIO_PIN_INPUT_DISCONNECT, \
NRF_GPIO_PIN_NOPULL, \
NRF_GPIO_PIN_H0H1, \
NRF_GPIO_PIN_NOSENSE)
/**************************************************************************/
#define SPIM_TX_BUF_LEN (1024 * 2)
#define SPIM_RX_BUF_LEN (1024 * 3)
uint8_t SPIM_TX_BUF[SPIM_TX_BUF_LEN] = {0};
uint8_t SPIM_RX_BUF[SPIM_RX_BUF_LEN] = {0};
/*SPIM3可以达到32M,840只有SPIM3支持外部扩展功能,就是外部DCX控制功能*/
static nrfx_spim_t m_spim = NRFX_SPIM_INSTANCE(3);
static volatile bool g_spim_xfer_done = false;
/*同时设置TX和RX的buffer*/
// nrfx_spim_xfer_desc_t m_buffer = NRFX_SPIM_XFER_TRX(SPIM_TX_BUF, SPIM_TX_BUF_LEN, SPIM_RX_BUF, SPIM_RX_BUF_LEN);
/**
* @brief SPI user event handler.
* @param event
*/
void spim_event_handler(nrfx_spim_evt_t const *p_event,
void *p_context)
{
if (p_event->type == NRFX_SPIM_EVENT_DONE)
{
g_spim_xfer_done = true;
}
}
void spim_hal_init(void)
{
/*不能使用低频引脚,还要配置为高驱*/
nrfx_spim_config_t spim_config = NRFX_SPIM_DEFAULT_CONFIG;
spim_config.ss_pin = DVC_SPIM_PIN_CS;
spim_config.miso_pin = DVC_SPIM_PIN_MISO; // 如果是刷屏可以不使用MISO数据pin脚,可以设置为 NRFX_SPIM_PIN_NOT_USED
spim_config.mosi_pin = DVC_SPIM_PIN_MOSI;
spim_config.sck_pin = DVC_SPIM_PIN_CLK;
// 配置SPI参数
spim_config.irq_priority = APP_IRQ_PRIORITY_LOW_MID;
spim_config.frequency = NRF_SPIM_FREQ_16M; // SPI时钟频率
spim_config.ss_active_high = false; ///< Polarity of the Slave Select pin during transmission.
spim_config.mode = NRF_SPIM_MODE_0; // SPI模式0 (CPOL=0, CPHA=0)
spim_config.bit_order = NRF_SPIM_BIT_ORDER_MSB_FIRST; // 高位在前
SPIM_PIN_INIT(DVC_SPIM_PIN_RESET);
SPIM_PIN_INIT(DVC_SPIM_PIN_CS);
SPIM_PIN_INIT(DVC_SPIM_PIN_CLK);
SPIM_PIN_INIT(DVC_SPIM_PIN_MOSI);
// SPIM_PIN_INIT(DVC_SPIM_PIN_DCX);
// SPIM_PIN_INIT(DVC_SPIM_PIN_MISO);
APP_ERROR_CHECK(nrfx_spim_init(&m_spim, &spim_config, spim_event_handler, NULL));
/*初始化用户需要的引脚*/
nrf_gpio_cfg_output(DVC_SPI_PIN_USER_CS);
nrf_gpio_pin_write(DVC_SPI_PIN_USER_CS, 1); // 默认拉高
/*PWOER PIN*/
nrf_gpio_cfg_output(DVC_POWER_PIN_USER);
nrf_gpio_pin_write(DVC_POWER_PIN_USER, 1); // 默认拉高
LOG("SPIM init end.");
}
void spim_int_pin_cb(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
{
// user_hal_red_on();
hal_gh3x2x_int_handler_call_back();
app_sys_ppg_int_flag_set();
}
void spim_user_int_pin_init(void)
{
gpio_app_init_pin(DVC_INT_PIN_USER_INT, GPIO_APP_LOTOHI_MODE, GPIO_APP_PULL_DOWN, spim_int_pin_cb);
LOG("INT PIN init end");
}
void spim_user_reset_pin_init(void)
{
nrf_gpio_cfg_output(DVC_SPI_PIN_USER_RESET);
nrf_gpio_pin_write(DVC_SPI_PIN_USER_RESET, 1); // 默认拉高
LOG("RESET PIN init end");
}
void spim_user_cs_write(uint8_t level)
{
nrf_gpio_pin_write(DVC_SPI_PIN_USER_CS, level);
}
void spim_user_reset_write(uint8_t level)
{
nrf_gpio_pin_write(DVC_SPI_PIN_USER_RESET, level);
}
// 等待直到SPIM空闲
void wait_until_spim_ready(void)
{
// 等待传输完成,同时允许 SoftDevice 处理事件
while (!g_spim_xfer_done)
{
sd_app_evt_wait();
}
g_spim_xfer_done = false;
}
// 发送单个字节函数
void spim_send_single_byte(uint8_t data)
{
nrfx_spim_xfer_desc_t xfer_desc = NRFX_SPIM_SINGLE_XFER(&data, 1, NULL, 0);
// 执行SPI传输 (只发送,不接收)
g_spim_xfer_done = false;
nrfx_err_t err_code = nrfx_spim_xfer(&m_spim, &xfer_desc, 0);
APP_ERROR_CHECK(err_code);
wait_until_spim_ready();
}
// 发送多个连续字节函数
void spim_send_multiple_bytes(uint8_t *header, uint32_t h_len, uint8_t *data, uint32_t length)
{
uint32_t idx = 0;
// 检查数据长度是否超出缓冲区大小
if ((h_len + length) > SPIM_TX_BUF_LEN)
{
LOG_D_ERR("Err Spi RL");
return;
}
if (header != NULL && h_len > 0)
{
memcpy(&SPIM_TX_BUF[idx], header, h_len);
idx += h_len;
}
// 将数据复制到发送缓冲区
memcpy(&SPIM_TX_BUF[idx], data, length);
nrfx_spim_xfer_desc_t xfer_desc = NRFX_SPIM_SINGLE_XFER(SPIM_TX_BUF, length + h_len, NULL, 0);
// wait_until_spim_ready();
// 执行SPI传输
g_spim_xfer_done = false;
nrfx_err_t err_code = nrfx_spim_xfer(&m_spim, &xfer_desc, 0);
APP_ERROR_CHECK(err_code);
wait_until_spim_ready();
}
// 接收多个字节
uint8_t spim_read_multiple_bytes(uint8_t *rx_data, uint32_t length)
{
if (length > SPIM_RX_BUF_LEN)
{
LOG_D_ERR("Err Spi TL");
return 1;
}
nrfx_spim_xfer_desc_t xfer_desc = NRFX_SPIM_SINGLE_XFER(NULL, 0, SPIM_RX_BUF, length);
g_spim_xfer_done = false;
nrfx_err_t err_code = nrfx_spim_xfer(&m_spim, &xfer_desc, 0);
APP_ERROR_CHECK(err_code);
wait_until_spim_ready();
// 将接收到的数据复制到输出缓冲区
memcpy(rx_data, SPIM_RX_BUF, length);
return 0;
}
// 同时发送和接收多个字节(全双工)
void spim_transfer_full_duplex(uint8_t *tx_data, uint8_t *rx_data, uint32_t length)
{
if (length > SPIM_TX_BUF_LEN || length > SPIM_RX_BUF_LEN)
{
return;
}
memcpy(SPIM_TX_BUF, tx_data, length);
nrfx_spim_xfer_desc_t xfer_desc = NRFX_SPIM_SINGLE_XFER(SPIM_TX_BUF, length, SPIM_RX_BUF, length);
g_spim_xfer_done = false;
nrfx_err_t err_code = nrfx_spim_xfer(&m_spim, &xfer_desc, 0);
APP_ERROR_CHECK(err_code);
wait_until_spim_ready();
// 将接收到的数据复制到输出缓冲区
memcpy(rx_data, SPIM_RX_BUF, length);
}
this is my timer code:
#include "timer_app.h"
#include "app_task_id.h"
/**
_____ _____ _____ _____ _ ___ ___ _____ _____
| _ \ |_ _| / ___| |_ _| | | / |/ | | ____| | _ \
| |_| | | | | | | | | | / /| /| | | |__ | |_| |
| _ / | | | | | | | | / / |__/ | | | __| | _ /
| | \ \ | | | |___ | | | | / / | | | |___ | | \ \
|_| \_\ |_| \_____| |_| |_| /_/ |_| |_____| |_| \_\
*/
APP_TIMER_DEF(m_sorft_timer_tmr);
APP_TIMER_DEF(ble_recv_timeout_id);
APP_TIMER_DEF(ble_slow_send_timeout_id);
static nrf_drv_wdt_channel_id m_channel_id;
static uint8_t br_timer_cb_flag = 0;
static uint8_t bs_timer_cb_flag = 0;
/*******************/
/**
*
*/
static void ble_recv_timer_handle(void *p_context)
{
br_timer_cb_flag = 1;
LOG_I_RTT("ble recv timeout\n");
}
static void ble_slow_send_timer_handle(void *p_context)
{
bs_timer_cb_flag = 1;
}
static void app_sys_sorft_timer_cb(void *p_context)
{
st_timer_tick_flag = 1;
}
/**@brief Function for initializing the timer module.
*/
void timers_init(void)
{
ret_code_t err_code = app_timer_init();
APP_ERROR_CHECK(err_code);
}
void timer_app_init(void)
{
ret_code_t err_code;
st_sorft_timer_init();
timers_init();
err_code = app_timer_create(&m_sorft_timer_tmr, APP_TIMER_MODE_REPEATED, app_sys_sorft_timer_cb);
APP_ERROR_CHECK(err_code);
err_code = app_timer_create(&ble_recv_timeout_id, APP_TIMER_MODE_SINGLE_SHOT, ble_recv_timer_handle);
APP_ERROR_CHECK(err_code);
err_code = app_timer_create(&ble_slow_send_timeout_id, APP_TIMER_MODE_SINGLE_SHOT, ble_slow_send_timer_handle);
APP_ERROR_CHECK(err_code);
err_code = app_timer_start(m_sorft_timer_tmr, APP_TIMER_TICKS(100), NULL);
APP_ERROR_CHECK(err_code);
}
void timer_app_ble_data_recv_timeout_start(uint32_t time)
{
app_timer_stop(ble_recv_timeout_id);
app_timer_start(ble_recv_timeout_id, APP_TIMER_TICKS(time), NULL);
LOG_I_RTT("ble recv timeout start:%d\n", APP_TIMER_TICKS(time));
}
void timer_app_ble_slow_send_timeout_start(uint32_t time)
{
// app_timer_stop(ble_slow_send_timeout_id);
app_timer_start(ble_slow_send_timeout_id, APP_TIMER_TICKS(time), NULL);
}
void timer_app_stop_all(void)
{
// app_timer_stop(ble_recv_timeout_id);
// app_timer_stop(ble_slow_send_timeout_id);
}
/**************************************************/
/**************** TIMER PROCESS ******************/
/**************************************************/
void timer_all_process(void)
{
if (br_timer_cb_flag)
{
app_task_ble(0);
br_timer_cb_flag = 0;
}
if (bs_timer_cb_flag)
{
bs_timer_handlw();
bs_timer_cb_flag = 0;
}
}