【问题标题】:PGSERR and PGPERR Bit ClearPGSERR 和 PGPERR 位清零
【发布时间】:2020-07-24 05:21:21
【问题描述】:

重置操作后设置 PGSERR 和 PGPERR 位有问题

我使用的是 stm32f4 板,而不是使用 CANBUS 和固件更新过程。

当我在 MX_CAN1_Init 函数中使用串行调试打印时。我面临闪存擦除错误。然后我分析那个错误,我发现 PGSERR 和 PGPERR 位已设置。

这些位必须为“0”。

我想分析这个问题,所以我在初始化状态下进行了这些测试:

    MX_CAN1_Init();
 
 Serialdebugprint("Read PGAERR FLAG %d\n",__HAL_FLASH_GET_FLAG((FLASH_FLAG_PGPERR)));
 
 Serialdebugprint("Read PGSERR FLAG %d\n",__HAL_FLASH_GET_FLAG((FLASH_FLAG_PGSERR)));

我得到这个值:

Read PGAERR FLAG 64

Read PGSERR FLAG 128

我得到这个值:

读取 PGAERR 标志 64

读取 PGSERR 标志 128

但这些标志必须为0。重置后。

如果我删除了 MX_CAN1_Init 这些标志等于“0”。

当我将 CAN_Init 函数中的某些参数(例如通信速度更改为 83.3kps 到 1Mbs)时,我将此标志设为 0 和 128 。顺便说一句,当我删除 serialdebug 时,我又得到了 0 和 128。

如果我将 MX_CAN1_Init 函数放在几个函数之后,则此标志返回“0”。

是什么原因?

    /**
 * @brief CAN1 Init function
 * @retval null
 */
 
static void MX_CAN1_Init(void)
{
  CAN_FilterTypeDef  sFilterConfig;
 
  
  hcan1.Instance = CAN1;
  hcan1.Init.Prescaler = 28; //3
  hcan1.Init.Mode = CAN_MODE_NORMAL;
  hcan1.Init.SyncJumpWidth = CAN_SJW_1TQ;
  hcan1.Init.TimeSeg1 = CAN_BS1_15TQ; //11
  hcan1.Init.TimeSeg2 = CAN_BS2_2TQ; //2
  hcan1.Init.TimeTriggeredMode = DISABLE;
  hcan1.Init.AutoBusOff = ENABLE;
  hcan1.Init.AutoWakeUp = DISABLE;
  hcan1.Init.AutoRetransmission = ENABLE;
  hcan1.Init.ReceiveFifoLocked = DISABLE;
  hcan1.Init.TransmitFifoPriority = DISABLE;
  if (HAL_CAN_Init(&hcan1) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }
 
    /*##-2- Configure the CAN Filter ###########################################*/
  sFilterConfig.FilterBank = 0;
  sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
  sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
  sFilterConfig.FilterIdHigh = 0x0000;
  sFilterConfig.FilterIdLow = 0x0000;
  sFilterConfig.FilterMaskIdHigh = 0x0000;
  sFilterConfig.FilterMaskIdLow = 0x0000;
  sFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0;
  sFilterConfig.FilterActivation = ENABLE;
  sFilterConfig.SlaveStartFilterBank = 0;
 
  if (HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig) != HAL_OK)
  {
    /* Filter configuration Error */
        // SerialPrint("FILTER ERROR !!");
    Error_Handler();
  }
 
  /*##-3- Start the CAN peripheral ###########################################*/
  if (HAL_CAN_Start(&hcan1) != HAL_OK)
  {
    // SerialPrint("CAN START ERROR !!");
    /* Start Error */
    Error_Handler();
  }
 
  /*##-4- Activate CAN RX notification #######################################*/
  if(HAL_CAN_ActivateNotification(&hcan1,CAN_IT_TX_MAILBOX_EMPTY | CAN_IT_RX_FIFO0_MSG_PENDING |CAN_IT_BUSOFF) != HAL_OK)
  {
    Error_Handler();
  }
  Serialdebugprint("Success CAN Init \n");
}

串口调试功能:

void Serialdebugprint(const char *serial_data, ...)
{
  char uartbuffer[1024]="";
  va_list arg;
  va_start(arg, serial_data);
  uint16_t len = vsnprintf(uartbuffer, 1024, serial_data, arg);
  va_end(arg);
  HAL_UART_Transmit(&huart2, (uint8_t *)uartbuffer, len, 100);
 
}
 

我认为问题在此行之后开始 HAL_UART_Transmit(&huart2, (uint8_t *)uartbuffer, len, 100)。是什么原因?

【问题讨论】:

  • 更新问题

标签: stm32 can-bus flash-memory


【解决方案1】:

当我调试一个相关的问题时偶然发现了这个线程。在我的固件中,我需要擦除 STM32L496 闪存中的 1 页。我从 STM HAL 得到的只是 HAL_ERROR。进一步的调查表明,PGSERR 标志是在之前的闪存写入过程中设置的。最后我发现设置了错误标志是因为 memset 操作地址为 0x00。

意味着如果你有这样的代码可以设置 PGSERR 标志:

uint8_t* pointer; 
memset(pointer, 0x00, 10);

顺便说一句。在我的情况下,运行该代码时没有 Hartfault。

【讨论】:

  • 在你回答这个问题后看到了这个问题。该错误几乎可以肯定是堆栈溢出,这反过来会导致与访问随机内存位置类似的问题,例如您的 memset 示例。我也发布了一个关于这个的答案。
【解决方案2】:

char uartbuffer[1024]=""; 的意思是“请尽快给我一个堆栈溢出”。不要在堆栈上声明像这样的巨大缓冲区,将它们移动到文件范围和/或声明为static

堆栈溢出会破坏您的调用堆栈以及几乎所有其他内容,之后您的代码开始运行或访问 la-la-land 中的地址,从而导致 PGSERR。

【讨论】:

    猜你喜欢
    • 2014-02-21
    • 1970-01-01
    • 2021-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-09
    • 1970-01-01
    相关资源
    最近更新 更多