打印
[STM32WL]

STM32WL V1.3.0的LoRaWAN_End_Node_FreeRTOS

[复制链接]
682|10
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
probedog|  楼主 | 2023-8-8 15:49 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
使用STM32WL V1.3.0的LoRaWAN_End_Node_FreeRTOS,stm32wle5cc芯片,发现运行几天后大概率出现systick周期由1ms变为4us的问题,导致freertos任务无法正常运行。

从debug信息中发现STK_LOAD寄存器被修改为很小的值,每次出问题的位置都是在lorawan发送一帧数据的过程中,MAC txDone到MAC rxTimeOut之间。

Debug info:

[2023-08-06 22:22:51-023] 01:01:01:01:01:01:01:01

DevAddr: 01:84:17:D3

g_systick_reg_per:6 2b828e 2b7d7f 400003e8

g_systick_reg_post:7 bb80 bb4b 400003e8 (ß The normal register value regs:1.STK_CTRL 2.STK_LOAD 3.STK_VAL 4.STK_CALIB)

-------------test1 TickCount:281704498--------------

-------------free heap:18328 12072--------------

g_systick_test:220752 tim17_test:201719

name state priority stack num

test_task_creat X 11 126 6

IDLE R 0 81 2

Tmr Svc B 2 223 3

monitor_loop B 6 168 5

sensor_loop B 10 790 4

lm_handler_proc B 8 232 7

lorawan_process

[2023-08-06 22:22:51-123] B 7 22 8

[2023-08-06 22:22:52-441] OnMacProcessNotify pre

OnMacProcessNotify:1

282161s607:MAC txDone

----------start lm_handler_process TickCount:281704881-------------- (LmHandlerProcess() Semaphore received)

----------end lm_handler_process TickCount:281704883-------------- (LmHandlerProcess() Wait semaphore enter sleep)

[2023-08-06 22:22:53-493] 282162s601:RX_1 on freq 922600000 Hz at DR 2 (First receive window)

282162s667:IRQ_RX_TX_TIMEOUT

OnMacProcessNotify pre

OnMacProcessNotify:1

282162s667:MAC rxTimeOut

[2023-08-06 22:23:01-934] delay_handle g_lorawan_state:8 (is RTC timer)

(The freertos cannot run)

[2023-08-07 10:06:39-378] EXTI9_5_IRQHandler () (Use an external interrupt to trigger a print reg info)

[2023-08-07 10:06:44-787] HAL_GPIO_EXTI_Callback:256

g_systick_reg_per:6 fee74e fee22c 400003e8

g_systick_reg_post:10007 2c 24 400003e8 (ß The register value of the exception regs:1.STK_CTRL 2.STK_LOAD 3.STK_VAL 4.STK_CALIB)

-------------test1 TickCount:281704899--------------

-------------free heap:18328 12072--------------

休眠唤醒相关代码:

void PreSleepProcessing(uint32_t *ulExpectedIdleTime)

{

/* Called by the kernel before it places the MCU into a sleep mode because

configPRE_SLEEP_PROCESSING() is #defined to PreSleepProcessing().

NOTE: Additional actions can be taken here to get the power consumption

even lower. For example, peripherals can be turned off here, and then back

on again in the post sleep processing function. For maximum power saving

ensure all unused pins are in their lowest power state. */

uint32_t WakeUpTimer_timeOut_ms = app_freertos_tick_to_ms(*ulExpectedIdleTime);

HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);

UTIL_TIMER_SetPeriod(&WakeUpTimer, WakeUpTimer_timeOut_ms);

UTIL_TIMER_Start(&WakeUpTimer);

Time_BeforeSleep = UTIL_TIMER_GetCurrentTime();

/Stop the systick here so that it stops even in sleep mode/

portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT;

HAL_TIM_Base_Stop_IT(&htim17);

g_systick_reg_pre[0] = portNVIC_SYSTICK_CTRL_REG;

g_systick_reg_pre[1] = portNVIC_SYSTICK_LOAD_REG;

g_systick_reg_pre[2] = portNVIC_SYSTICK_CURRENT_VALUE_REG;

g_systick_reg_pre[3] = portNVIC_SYSTICK_STK_CALIB_REG;

UTIL_LPM_EnterLowPower();

/*

(*ulExpectedIdleTime) is set to 0 to indicate that PreSleepProcessing contains

its own wait for interrupt or wait for event instruction and so the kernel vPortSuppressTicksAndSleep

function does not need to execute the wfi instruction

*/

*ulExpectedIdleTime = 0;

}

void PostSleepProcessing(uint32_t *ulExpectedIdleTime)

{

/* Called by the kernel when the MCU exits a sleep mode because

configPOST_SLEEP_PROCESSING is #defined to PostSleepProcessing(). */

uint32_t SleepDuration = UTIL_TIMER_GetElapsedTime(Time_BeforeSleep);

/ Avoid compiler warnings about the unused parameter. /

UNUSED(ulExpectedIdleTime);

UTIL_TIMER_Stop(&WakeUpTimer);

/ Set the new reload value. /

if (portNVIC_SYSTICK_CURRENT_VALUE_REG > (SleepDuration * CORE_TICK_RATE))

{

/what remains to sleep/

portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG - (app_freertos_ms_to_tick(SleepDuration) * CORE_TICK_RATE);

}

else

{

portNVIC_SYSTICK_LOAD_REG = CORE_TICK_RATE;

}

/ Clear the SysTick count flag and set the count value back to zero. /

portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;

/ Restart SysTick. /

portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;

HAL_TIM_Base_Start_IT(&htim17);

g_systick_reg_post[0] = portNVIC_SYSTICK_CTRL_REG;

g_systick_reg_post[1] = portNVIC_SYSTICK_LOAD_REG;

g_systick_reg_post[2] = portNVIC_SYSTICK_CURRENT_VALUE_REG;

g_systick_reg_post[3] = portNVIC_SYSTICK_STK_CALIB_REG;

HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);

}

用户数据发送部分代码:

void tcs_lorawan_send(int max_temp, int min_temp)

{

LmHandlerErrorStatus_t status = LORAMAC_HANDLER_ERROR;

UTIL_TIMER_Time_t nextTxIn = 0;

static uint16_t sn = 0;

float temp;

if (g_is_connect) {

uint8_t len = 0;

static uint16_t battery = 0xFFFF;

static uint16_t batt_tmp;

batt_tmp = SYS_GetBatteryLevel();

if (batt_tmp < battery) {

battery = batt_tmp;

}

max_temp -= 2731;

min_temp -= 2731;

max_temp += MAX_TEMP_OFFSET;

min_temp += MIN_TEMP_OFFSET;

temp = objectTemperatureByDistance((float)max_temp / 10, (float)CONFIG.distance_corr / 100);

max_temp = temp * 100;

min_temp *= 10;

APP_LOG(TS_ON, VLEVEL_M, "VDDA: %dmv\r\n", battery);

APP_LOG(TS_ON, VLEVEL_M, "max_temp:%d min_temp:%d\r\n", max_temp, min_temp);

if (((max_temp > TEMP_MAX_ERR) || (max_temp < TEMP_MIN_ERR)) ||

((min_temp > TEMP_MAX_ERR) || (min_temp < TEMP_MIN_ERR))) {

UTIL_TIMER_StartWithPeriod(&g_delay_timer, SEND_INTERVAL * 1000);

g_lorawan_state = LORAWAN_STATE_SEND_RETRY;

return;

}

AppData.Port = LORAWAN_USER_APP_PORT;

/ head /

AppData.Buffer[len++] = 0xAA;

if 1
/ len (Skip Length) /

len++;

/ serial number /

AppData.Buffer[len++] = (uint8_t)sn & 0xFF;

AppData.Buffer[len++] = (uint8_t)((sn >> 8) & 0xFF);

sn++;

/ dev_t /

AppData.Buffer[len++] = (uint8_t)PROTOCOL_DEV_TYPE & 0xff;

AppData.Buffer[len++] = (uint8_t)((PROTOCOL_DEV_TYPE >> 8) & 0xff);

/ key (ignore)/

AppData.Buffer[len++] = 0x00;

AppData.Buffer[len++] = 0x00;

AppData.Buffer[len++] = 0x00;

/ data /

AppData.Buffer[len++] = (uint8_t)(battery & 0xFF);

AppData.Buffer[len++] = (uint8_t)((battery >> 8) & 0xFF);

AppData.Buffer[len++] = (uint8_t)(max_temp & 0xFF);

AppData.Buffer[len++] = (uint8_t)((max_temp >> 8) & 0xFF);

AppData.Buffer[len++] = (uint8_t)(min_temp & 0xFF);

AppData.Buffer[len++] = (uint8_t)((min_temp >> 8) & 0xFF);

AppData.Buffer[len++] = (uint8_t)(CONFIG.distance_corr & 0xFF);

AppData.Buffer[len++] = (uint8_t)((CONFIG.distance_corr

& 0xFF);
AppData.Buffer[len++] = CONFIG.emissivity;

AppData.Buffer[len++] = CONFIG.max_temp_limit;

AppData.Buffer[len++] = CONFIG.min_temp_limit;

/ set len /

AppData.Buffer[1] = len;

/ set checksum /

AppData.Buffer[len++] = get_checkSum(AppData.Buffer, len);

endif
AppData.BufferSize = len;

status = LmHandlerSend(&AppData, LmHandlerParams.IsTxConfirmed, false);

if (LORAMAC_HANDLER_SUCCESS == status) {

APP_LOG(TS_ON, VLEVEL_L, "SEND REQUEST\r\n");

} else if (LORAMAC_HANDLER_DUTYCYCLE_RESTRICTED == status) {

nextTxIn = LmHandlerGetDutyCycleWaitTime();

if (nextTxIn > 0) {

APP_PRINTF("Next Tx in : ~%d second(s)\n", (nextTxIn / 1000));

}

}

}

UTIL_TIMER_StartWithPeriod(&g_delay_timer, MAX(nextTxIn, SEND_INTERVAL * 1000));

}

使用特权

评论回复
沙发
公羊子丹| | 2024-2-21 07:17 | 只看该作者

应在操作时间内将胶料灌注完毕,否则影响流平

使用特权

评论回复
板凳
万图| | 2024-2-21 08:20 | 只看该作者

测试负载测试是在特定的测试条件下进行的

使用特权

评论回复
地板
Uriah| | 2024-2-21 09:23 | 只看该作者

在测试中,可以改变负载电流,得到最大输出电流和输出电压

使用特权

评论回复
5
帛灿灿| | 2024-2-21 11:19 | 只看该作者

信号防雷电路应满足相应接口信号传输速率及带宽的需求,且接口与被保护设备兼容。

使用特权

评论回复
6
Pulitzer| | 2024-2-21 12:22 | 只看该作者

随着对电路板模块的需求增加

使用特权

评论回复
7
周半梅| | 2024-2-21 14:18 | 只看该作者

防雷电路的输出残压值必须比被防护电路自身能够耐受的过电压峰值低,并有一定裕量

使用特权

评论回复
8
Pulitzer| | 2024-2-21 15:21 | 只看该作者

模信号是幅度相等且相位相同的信号

使用特权

评论回复
9
童雨竹| | 2024-2-21 17:17 | 只看该作者

Cfinal是CESD和人体电容的并联组合

使用特权

评论回复
10
Wordsworth| | 2024-2-21 18:20 | 只看该作者

构成各种滤波器对EMI进行滤波

使用特权

评论回复
11
Clyde011| | 2024-2-21 19:23 | 只看该作者

在动态测试之前,首先需要设定测试时间和测试频率

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

378

主题

2018

帖子

3

粉丝