硬汉嵌入式论坛

 找回密码
 立即注册
查看: 346|回复: 9
收起左侧

[技术讨论] STM32F103C8T6触发IWDG重启

[复制链接]

35

主题

221

回帖

326

积分

高级会员

积分
326
发表于 2025-9-4 14:09:52 | 显示全部楼层 |阅读模式
板子是STM32F103C8T6的
开启了IWDG,配置了32秒超时时间

正常业务逻辑:
1.开机
2.初始化
3.连接4G
4.判断新版本OTA
5.下载配置
6.读数并保存数据到flash
7.上传数据,包括上传本次采集数据以及历史未上传数据
8.设置下次唤醒时间,休眠等待下次自动唤醒

当前异常情况:不断地
1.开机
2.初始化
3.连接4G
4.判断新版本OTA
5.下载配置
然后1-5不断执行,6从后面成功执行到7的时候上传历史数据来看是正常的
7和8未正常执行就重启,因为7的上传数据服务器没收到,但是后续上传历史数据的时候历史数据里面有数据说明之前读数有保存的


怀疑:
1.程序哪里触发了HardFault,导致重启了,如野指针、数组越界、堆栈溢出等
+日志保存Flash,发现未触发此记录保存
2.看门狗未及时喂狗超时重启了
+判断是否是看门狗重启,日志保存Flash,查到确实是有触发

根据OTA之后的日志,排查确实是看门狗触发重启了。
但是我优化了代码中的所有我知道的可能会导致延迟的地方,还是大概率触发。
也问过chatgpt,优化了可能会出现的uart,spi,adc等等中的receive、transmit、pollfor等等之前用的HAL_MAX_DELAY这种timeout的情况。

就很奇怪,就一个地方的3台设备都会有这个问题,关键这个设备在其他地方之前使用都正常的。
设备在山里,4G信号较弱,CSQ大概在18-20左右,有时候请求都上不了。
边上大约30米开外可能会有挖机施工,刚开始觉着可能是大功率设备干扰,但是没有施工的时候也有这个问题。

现在就怀疑大概率是4G模块这里哪里代码没有处理好。
用的裸机程序,旧代码不敢大改。

[C] 纯文本查看 复制代码

#include "lte.h"

#include <stdio.h>

#include "dwt_delay.h"
#include "stdlib.h"
#include "string.h"
#include "usart.h"

#define LTE_TYPE_EC600N

// LTE UART
// recieve buff
volatile uint8_t LTE_RX_Buffer[LTE_RX_Buffer_SIZE];
// 0X4000:0x0D;0x8000:0x0A;lower:rx data size
// 0x0D:CR (carriage return),0x0A:LF (NL line feed, new line)
volatile uint16_t LTE_RX_STA = 0;
volatile uint8_t LTE_RX_State = 0;

// http request end
uint8_t end[2] = {0x1A, 0x00};

bool flag_debug_log = false;

void LTE_PowerOn(void)
{
  HAL_UART_Receive_IT(&HUART_LTE, (uint8_t*)LTE_RX_Buffer, 1);
  __LTE_POWER_ON;
  Delay_ms(10);
  Refresh_IWDG();
  LOG_Info("LTE Power On.\n");
}

void LTE_PowerOff(void)
{
  __LTE_POWER_OFF;
  Delay_ms(50);
  HAL_UART_AbortReceive_IT(&HUART_LTE);
  Refresh_IWDG();
  LOG_Info("LTE Power Off.\n");
}

void LTE_Clear_Buffer(void)
{
  memset((char*)LTE_RX_Buffer, 0, sizeof(LTE_RX_Buffer));
  LTE_RX_STA = 0;
  HAL_UART_AbortReceive_IT(&HUART_LTE);
  HAL_UART_Receive_IT(&HUART_LTE, (uint8_t*)LTE_RX_Buffer + (LTE_RX_STA & 0x3FFF), 1);
  Refresh_IWDG();
}

void LTE_TurnOn(void)
{
  HAL_GPIO_WritePin(LTE_ON_GPIO_Port, LTE_ON_Pin, GPIO_PIN_SET);
  Delay_second(2);
  Delay_ms(100);
  HAL_GPIO_WritePin(LTE_ON_GPIO_Port, LTE_ON_Pin, GPIO_PIN_RESET);
  Delay_ms(1000);
  Refresh_IWDG();
  LOG_Info("LTE Turn On.\n");
}

void LTE_Command(char* SendBuf)
{
  __LTE_LED_NET_ON;

  uint16_t times = 0;
  while (LTE_RX_State == 1 && times < 5000)
  {
    Refresh_IWDG();
    times += 10;
    Delay_ms(10);
  }
  Refresh_IWDG();
  LTE_Clear_Buffer();
  if (times <= 100)
  {
    Delay_ms(100);
  }

  Refresh_IWDG();
  UART_SendStr(&HUART_LTE, (uint8_t*)SendBuf);
  Refresh_IWDG();
  UART_SendStr(&HUART_LTE, (uint8_t*)"\r\n");
  Refresh_IWDG();
  Delay_ms(300);
  if (flag_debug_log)
  {
    if (strlen((const char*)LTE_RX_Buffer) > 200)
    {
      LOG_Debug("LTE_TX>>%s->RX:%.200s\n", SendBuf, LTE_RX_Buffer);
    }
    else
    {
      LOG_Debug("LTE_TX>>%s->RX:%s\n", SendBuf, LTE_RX_Buffer);
    }
  }
  Refresh_IWDG();
  __LTE_LED_NET_OFF;
}

/**
 * @brief send command and judge rx
 */
bool LTE_CommandJudge(const char* judge, const uint32_t times, char* SendBuf)
{
  flag_debug_log = false;
  char* strx = NULL;
  uint32_t LTE_AT_Count = 0;
  while (strx == NULL)
  {
    Refresh_IWDG();
    LTE_Command(SendBuf);
    strx = strstr((const char*)LTE_RX_Buffer, judge);
    if (LTE_AT_Count++ >= times) break;
  }
  flag_debug_log = true;
  LOG_Debug("LTE_TX>>%s->RX:%s\n", SendBuf, LTE_RX_Buffer);
  return (strx != NULL);
}

bool LTE_Init()
{
  LOG_Info("LTE Init Begin...\n");
  int tryTimes = 3;
  int totalTimes = 0;
  bool flag = false;
  while (totalTimes < tryTimes)
  {
    totalTimes++;
    Refresh_IWDG();
    if (totalTimes > 1)
    {
      LTE_PowerOff();
      Refresh_IWDG();
      LTE_PowerOn();
      Refresh_IWDG();
      LTE_TurnOn();
    }

    if (!LTE_CommandJudge("OK", 50, "AT"))
    {
      continue;
    }
    Refresh_IWDG();
    LTE_Command("ATI");
    Refresh_IWDG();

    // query sim state, nomal will return "READY"
    if (!LTE_CommandJudge("READY", 20, "AT+CPIN?"))
    {
      continue;
    }

    Refresh_IWDG();
    LTE_Command("AT+CSQ");
    Refresh_IWDG();

    //    // query CS, nomal will return "0,1"或"0,5" 2G
    //    {
    //      char *strx = NULL;
    //      uint32_t LTE_AT_Count = 0;
    //      while(strx == NULL)
    //      {
    //        LTE_Command("AT+CREG?");
    //        strx = strstr((const char*)LTE_RX_Buffer, "0,1");
    //        if (strx == NULL){
    //          strx = strstr((const char*)LTE_RX_Buffer, "0,5");
    //        }
    //        if (LTE_AT_Count++ >= 100) break;
    //      }
    //      if (strx == NULL){
    //        continue;
    //      }
    //    }

    // query CS, nomal will return "0,1"或"0,5" 4G
    {
      char* strx = NULL;
      uint32_t LTE_AT_Count = 0;
      while (strx == NULL)
      {
        Refresh_IWDG();
        LTE_Command("AT+CEREG?");
        Refresh_IWDG();
        strx = strstr((const char*)LTE_RX_Buffer, ",1");
        if (strx == NULL)
        {
          strx = strstr((const char*)LTE_RX_Buffer, ",5");
        }
        if (LTE_AT_Count++ >= 100) break;
      }
      if (strx == NULL)
      {
        continue;
      }
    }

    //    // query PS, nomal will return "0,1"或"0,5"
    //    {
    //      char *strx = NULL;
    //      uint32_t LTE_AT_Count = 0;
    //      while(strx == NULL)
    //      {
    //        LTE_Command("AT+CGREG?");
    //        strx = strstr((const char*)LTE_RX_Buffer, "0,1");
    //        if (strx == NULL){
    //          strx = strstr((const char*)LTE_RX_Buffer, "0,5");
    //        }
    //        if (LTE_AT_Count++ >= 100) break;
    //      }
    //    }

    Refresh_IWDG();
    LTE_CommandJudge("OK", 10, "AT+QHTTPCFG=\"contextid\",1");
    Refresh_IWDG();

    LTE_Command("AT+QIACT?");
    Refresh_IWDG();

    // set APN, nomal will return "OK"
    // CMNET
    // LTE_CommandJudge("OK", 5, "AT+QICSGP=1,1,\"CMNET\",\"\",\"\",1");
    // UNINET
    // LTE_CommandJudge("OK", 5, "AT+QICSGP=1,1,\"UNINET\",\"\",\"\",1");

    // activate PDP,nomal will return "OK"
    flag = LTE_CommandJudge("OK", 10, "AT+QIACT=1");
    Refresh_IWDG();
    LTE_Command("AT+QIACT?");
    Refresh_IWDG();
    LTE_Command("AT+CSQ");
    if (flag) break;
  }
  return flag;
}

int8_t LTE_GetCSQ(void)
{
  LTE_Command("AT+CSQ");
  char* strx = NULL;
  strx = strstr((const char*)LTE_RX_Buffer, "+CSQ:");
  if (strx != NULL)
  {
    int x = atoi(strx + 5);
    return x;
  }
  return -1;
}

/**
 * @brief httpGet
 * @note SendBuf is url, return true if httpstatus is 200
 */
bool LTE_HttpGet(char* SendBuf)
{
  int len = strlen(SendBuf);
  char temp[256] = {'\0'};
  sprintf(temp, "AT+QHTTPURL=%d,%d", len, LTE_WAITTIME_SECONDS);
  LTE_Command(&temp[0]);
  int times = 0;
  {
    char* strx = NULL;
    while (strx == NULL && times < 5000)
    {
      Refresh_IWDG();
      strx = strstr((const char*)LTE_RX_Buffer, "CONNECT");
      Delay_ms(50);
      times += 50;
    }
  }

  LTE_Command(SendBuf);

  {
    times = 0;
    char* strx = NULL;
    while (strx == NULL && times < 5000)
    {
      Refresh_IWDG();
      strx = strstr((const char*)LTE_RX_Buffer, "OK");
      Delay_ms(50);
      times += 50;
    }
  }
  memset(temp, 0x00, sizeof(temp));
  sprintf(temp, "AT+QHTTPGET=%d", LTE_WAITTIME_SECONDS);
  LTE_Command(&temp[0]);

  char* strx = NULL;
  {
    times = 0;
    while (strx == NULL && times < LTE_WAITTIME_MS)
    {
      Refresh_IWDG();
      strx = strstr((const char*)LTE_RX_Buffer, "+QHTTPGET:");
      Delay_ms(50);
      times += 50;
    }
  }
  return (strx != NULL);
}

bool LTE_HttpRead(void)
{
  BKP_TEST_FLAG_REG = 201;
  char temp[256] = {'\0'};
  sprintf(temp, "AT+QHTTPREAD=%d", LTE_WAITTIME_SECONDS);
  BKP_TEST_FLAG_REG = 202;
  LTE_Command(&temp[0]);
  BKP_TEST_FLAG_REG = 203;
  uint16_t times = 0;
  while (LTE_RX_State == 1 && times < LTE_WAITTIME_MS)
  {
    BKP_TEST_FLAG_REG = 9000 + times / 10;
    Refresh_IWDG();
    times += 10;
    Delay_ms(10);
  }
  BKP_TEST_FLAG_REG = 204;
  char* strx = NULL;
  strx = strstr((const char*)LTE_RX_Buffer, "OK");
  BKP_TEST_FLAG_REG = 205;
  return (strx != NULL);
}

/**
 * @brief httpPost
 * @note SendBuf is url, return true if httpstatus is 200
 */
bool LTE_HttpPost(char* SendBuf)
{
  // set content_type "application/json"
  // LTE_Command("AT+QHTTPCFG=\"contenttype\",4");
  BKP_TEST_FLAG_REG = 101;
  int len = strlen(SendBuf);
  char temp[256] = {'\0'};
  sprintf(temp, "AT+QHTTPURL=%d,%d", len, LTE_WAITTIME_SECONDS);
  BKP_TEST_FLAG_REG = 102;
  LTE_Command(&temp[0]);
  BKP_TEST_FLAG_REG = 103;
  int times = 0;
  {
    BKP_TEST_FLAG_REG = 104;
    char* strx = NULL;
    while (strx == NULL && times < LTE_WAITTIME_MS)
    {
      BKP_TEST_FLAG_REG = 1000 + times / 50;
      Refresh_IWDG();
      strx = strstr((const char*)LTE_RX_Buffer, "CONNECT");
      Delay_ms(50);
      times += 50;
    }
  }
  BKP_TEST_FLAG_REG = 105;
  LTE_Command(SendBuf);
  BKP_TEST_FLAG_REG = 106;
  times = 0;
  {
    char* strx = NULL;
    BKP_TEST_FLAG_REG = 107;
    while (strx == NULL && times < LTE_WAITTIME_MS)
    {
      BKP_TEST_FLAG_REG = 3000 + times / 50;
      Refresh_IWDG();
      strx = strstr((const char*)LTE_RX_Buffer, "OK");
      Delay_ms(50);
      times += 50;
    }
  }
  BKP_TEST_FLAG_REG = 108;
  memset(temp, 0x00, sizeof(temp));
  BKP_TEST_FLAG_REG = 109;
  sprintf(temp, "AT+QHTTPPOST=3,%d,%d", LTE_WAITTIME_SECONDS, LTE_WAITTIME_SECONDS);
  BKP_TEST_FLAG_REG = 110;
  LTE_Command(&temp[0]);
  BKP_TEST_FLAG_REG = 111;
  times = 0;
  {
    char* strx = NULL;
    while (strx == NULL && times < LTE_WAITTIME_MS)
    {
      BKP_TEST_FLAG_REG = 5000 + times / 50;
      Refresh_IWDG();
      strx = strstr((const char*)LTE_RX_Buffer, "CONNECT");
      Delay_ms(50);
      times += 50;
    }
  }
  BKP_TEST_FLAG_REG = 112;
  LTE_Command("1=1");
  BKP_TEST_FLAG_REG = 113;

  char* strx = NULL;
  times = 0;
  {
    while (strx == NULL && times < LTE_WAITTIME_MS)
    {
      BKP_TEST_FLAG_REG = 7000 + times / 50;
      Refresh_IWDG();
      strx = strstr((const char*)LTE_RX_Buffer, "QHTTPPOST");
      Delay_ms(50);
      times += 50;
    }
  }
  BKP_TEST_FLAG_REG = 114;
  return (strx != NULL);
}

bool LTE_TCPClientConnect(char* TcpServerIp, int TcpServerPort)
{
  char temp[100] = {'\0'};
  sprintf(temp, "AT+QIOPEN=1,0,\"TCP\",\"%s\",%d,0,0", TcpServerIp, TcpServerPort);
  LTE_Command(&temp[0]);
  int times = 0;
  {
    char* strx = NULL;
    while (strx == NULL && times < LTE_WAITTIME_MS)
    {
      Refresh_IWDG();
      strx = strstr((const char*)LTE_RX_Buffer, "OK");
      Delay_ms(50);
      times += 50;
    }
  }
  LTE_Command("AT+QISTATE=1,0");
  char* strx = NULL;
  times = 0;
  {
    while (strx == NULL && times < LTE_WAITTIME_MS)
    {
      Refresh_IWDG();
      strx = strstr((const char*)LTE_RX_Buffer, "OK");
      Delay_ms(50);
      times += 50;
    }
  }
  return (strx != NULL);
}

bool LTE_TCPClientSend(char* SendBuf)
{
  int len = strlen(SendBuf);
  char temp[100] = {'\0'};
  sprintf(temp, "AT+QISEND=0,%d", len);
  LTE_Command(&temp[0]);
  LTE_Command(SendBuf);
  char* strx = NULL;
  int times = 0;
  {
    while (strx == NULL && times < LTE_WAITTIME_MS)
    {
      Refresh_IWDG();
      strx = strstr((const char*)LTE_RX_Buffer, "OK");
      Delay_ms(50);
      times += 50;
    }
  }
  return (strx != NULL);
}

bool LTE_TCPClientRecv(void)
{
  LTE_Command("AT+QIRD=0,1500");
  char* strx = NULL;
  int times = 0;
  {
    while (strx == NULL && times < LTE_WAITTIME_MS)
    {
      Refresh_IWDG();
      strx = strstr((const char*)LTE_RX_Buffer, "OK");
      Delay_ms(50);
      times += 50;
    }
  }
  return (strx != NULL);
}

bool LTE_TCPClientClose(void)
{
  LTE_Command("AT+QICLOSE=0");
  char* strx = NULL;
  int times = 0;
  {
    while (strx == NULL && times < LTE_WAITTIME_MS)
    {
      Refresh_IWDG();
      strx = strstr((const char*)LTE_RX_Buffer, "OK");
      Delay_ms(50);
      times += 50;
    }
  }
  return (strx != NULL);
}


#define DEFAULT_UART_TRANSMIT_TIMEOUT  5000

void UART_SendStr(UART_HandleTypeDef *huart, uint8_t *SendBuf) {
  int len = strlen((const char *)SendBuf);
  UART_Send(huart, SendBuf, len);
}

void UART_Send(UART_HandleTypeDef *huart, uint8_t *SendBuf, uint32_t Length) {
  HAL_UART_Transmit(huart, SendBuf, Length, DEFAULT_UART_TRANSMIT_TIMEOUT);
}







回复

使用道具 举报

9

主题

159

回帖

186

积分

初级会员

积分
186
发表于 2025-9-4 15:11:20 | 显示全部楼层
会不会是电源供不上导致的?
回复

使用道具 举报

35

主题

221

回帖

326

积分

高级会员

积分
326
 楼主| 发表于 2025-9-4 15:14:03 | 显示全部楼层
本帖最后由 LinY 于 2025-9-4 15:15 编辑
tcs_stm32 发表于 2025-9-4 15:11
会不会是电源供不上导致的?

有电源输入电压检测的,用的锂电池,还有12.6V 够用的

而且这几个盒子在这山上不同地方,每个都是单独锂电池供电的
回复

使用道具 举报

9

主题

159

回帖

186

积分

初级会员

积分
186
发表于 2025-9-4 15:15:35 | 显示全部楼层
我看到你是看门狗触发重启,那大概率卡死在哪里了
回复

使用道具 举报

35

主题

221

回帖

326

积分

高级会员

积分
326
 楼主| 发表于 2025-9-4 15:18:47 | 显示全部楼层
tcs_stm32 发表于 2025-9-4 15:15
我看到你是看门狗触发重启,那大概率卡死在哪里了

关键就是找不到卡死的地方
设备在山上,本地也复现不出来。
我尝试把设备包上锡纸然后放入金属盒子中进行4G信号削弱到18左右,最多也就是个别请求上不来,但是程序也不会重启。

回复

使用道具 举报

3

主题

116

回帖

125

积分

初级会员

积分
125
发表于 2025-9-4 15:56:50 | 显示全部楼层
把看门狗关掉,仿真运行看卡死在哪里。这样好定位,开着找问题很难定位.
回复

使用道具 举报

35

主题

221

回帖

326

积分

高级会员

积分
326
 楼主| 发表于 2025-9-4 16:13:20 | 显示全部楼层
WangYI741 发表于 2025-9-4 15:56
把看门狗关掉,仿真运行看卡死在哪里。这样好定位,开着找问题很难定位.

本地测试都没死啊
就现场那里死了
回复

使用道具 举报

35

主题

221

回帖

326

积分

高级会员

积分
326
 楼主| 发表于 2025-9-4 17:19:26 | 显示全部楼层
我怀疑会不变因为IROM不够用了 所以我开着-O3 导致不正常的
回复

使用道具 举报

3

主题

116

回帖

125

积分

初级会员

积分
125
发表于 2025-9-5 09:12:29 | 显示全部楼层
LinY 发表于 2025-9-4 16:13
本地测试都没死啊
就现场那里死了

本地模拟不了现场的环境,你上面说山上的信号比较弱。你可以试着从注网那部分看看。
回复

使用道具 举报

35

主题

221

回帖

326

积分

高级会员

积分
326
 楼主| 发表于 2025-9-10 15:09:33 | 显示全部楼层
本帖最后由 LinY 于 2025-9-10 15:24 编辑

难搞还是没搞定,各种OTA测试排查卡流量都干完了
很奇怪
我在各个可能有问题的语句中间修改RTC_BKP_DR9,这个寄存器在IWDG之后不会修改的。我判断如果是IWDG复位的保存下这个值然后4G上传。
发现值是在Delay_ms之前,说明这个Delay_ms卡死了,奇怪这地方也没问题啊 就是HAL_Delay,delay的也不多才100和300ms
我IWDG设置的32秒 怎么也不会超时 奇怪了
卡在这2个位置
void LTE_Command(char* SendBuf)
{
  __LTE_LED_NET_ON;

  uint16_t times = 0;
  while (LTE_RX_State == 1 && times < 5000)
  {
    Refresh_IWDG();
    times += 10;
    Delay_ms(10);
  }
  Refresh_IWDG();
  LTE_Clear_Buffer();
  // 卡在这个位置1
  if (times <= 100)
  {
    Delay_ms(100);
  }
  Refresh_IWDG();
  UART_SendStr(&HUART_LTE, (uint8_t*)SendBuf);
  Refresh_IWDG();
  UART_SendStr(&HUART_LTE, (uint8_t*)"\r\n");
  Refresh_IWDG();
  // 卡在这个位置2
  Delay_ms(300);
  Refresh_IWDG();
  __LTE_LED_NET_OFF;
}
刚开始以为是因为开启了-O3的原因,然后各种优化到-O0,发现还是有问题
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2025-9-26 16:49 , Processed in 0.046835 second(s), 24 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表