Skip to content

Commit

Permalink
🐛 1. 解决&说明内存空间非法访问导致卡死的问题 2.解决无法延迟跳转的问题 3. 修正个别错误
Browse files Browse the repository at this point in the history
Signed-off-by: DAVE <[email protected]>
  • Loading branch information
SummerFalls committed May 25, 2021
1 parent 23c6f31 commit fa7a572
Show file tree
Hide file tree
Showing 13 changed files with 57 additions and 36 deletions.
Binary file added LinkSetting_ForUsageFault_00.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added LinkSetting_ForUsageFault_01.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added LinkSetting_ForUsageFault_02.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,26 @@ S32K1xx 的 CAN 接 `周立功 USBCANFD-100U-mini`,使用 `ZCANPRO` 软件的
![Pic_ZCANPRO_ECU_Refresh_Note_ProgramSession][Pic_ZCANPRO_ECU_Refresh_Note_ProgramSession]
![Pic_ZCANPRO_ECU_Refresh_Note_ResetECU][Pic_ZCANPRO_ECU_Refresh_Note_ResetECU]

---

### :warning: 特别注意

< :ok_hand: 已解决 > 关于 `S32K144 APP 工程` 调用 `Flash_EraseFlashDriverInRAM()` 会导致程序卡死的问题进行说明记录:

- 根据 Ozone 调试得知,实际现象为出现 `HardFault``HFSR` 寄存器 `FORCED` 位被置 1,所以可以判断由其它 Fault 异常提升而来,实际为 `UsageFault``INVSTATE` 位被置 1,如下图所示:
- ![LinkSetting_ForUsageFault_00][LinkSetting_ForUsageFault_00]
- 由于程序卡死的位置并不是每次都在同一位置,故初期的排查非常困难。由于同样的代码,在 `S32K118 APP 工程` 中被调用时,并不会产生该问题,所以需要从两个不同芯片的工程的不同之处寻找原因。经过比对,初步判断与两芯片的链接文件空间分配有关联,具体为两个芯片的 `Flash Driver` 所占用的 RAM 地址空间不同。其中,在 `S32K144` 的 `Bootloader 工程` 中,`m_flash_driver` 地址空间在 `APP 工程` 中会与 `m_data` 地址空间合并,从 Bootloader 跳转至 APP 时,会先调用 `Reset_Handler` 汇编函数,此汇编函数会进行相关初始化之后再跳转到 `main` 函数,其中在初始化时,会调用 `init_data_bss()` 函数,此函数其中的一个工作就是将位于 ROM 中(即 `m_interrupts` 地址空间内)的中断向量表拷贝到 RAM 中(即 `m_data` 地址空间内)的起始地址处,此时,如若在 `APP 工程` 中尝试调用 `Flash_EraseFlashDriverInRAM()` ,会对 `0x1FFF8000` 起始地址处连续 `0x800` 个字节的内容进行清零操作,而 `0x1FFF8000` ~ `0x1FFF8800` 地址空间段已经完全属于 `m_data` ,如若再执行 `Flash_EraseFlashDriverInRAM()` 则会将 RAM 中的中断向量表擦除,导致中断响应出现异常,故最终会导致程序卡死,详细配合以下截图进行分析。
- ![LinkSetting_ForUsageFault_01][LinkSetting_ForUsageFault_01]
- ![LinkSetting_ForUsageFault_02][LinkSetting_ForUsageFault_02]
- 解决方法有两种:APP 工程中一律不调用 `Flash_EraseFlashDriverInRAM()` 或将链接文件内 `m_flash_driver` 的地址空间从 `m_data_2` 地址空间的后半段进行划分。
- 但经过评估,显然前者为更恰当的解决方法,因为在 APP 工程中,已不存在 `m_flash_driver` 地址空间,此时就算在 Bootloader 中将 `m_data_2` 的后半段空间划分给 `m_flash_driver` ,在 APP 工程中再对该片空间进行自行清零的操作是不妥的,因为 `m_data_2` 会用于存放 `customSectionBlock``bss``heap``stack`, 此时如若再在 APP 中调用 `Flash_EraseFlashDriverInRAM()` ,同样有可能会将这些数据清零。

[Pic_ZCANPRO_ECU_Refresh]: ./Pic_ZCANPRO_ECU_Refresh.png
[Pic_ZCANPRO_ECU_Refresh_Note_ProgramSession]: ./Pic_ZCANPRO_ECU_Refresh_Note_ProgramSession.png
[Pic_ZCANPRO_ECU_Refresh_Note_ResetECU]: ./Pic_ZCANPRO_ECU_Refresh_Note_ResetECU.png
[LinkSetting_ForUsageFault_00]: ./LinkSetting_ForUsageFault_00.png
[LinkSetting_ForUsageFault_01]: ./LinkSetting_ForUsageFault_01.png
[LinkSetting_ForUsageFault_02]: ./LinkSetting_ForUsageFault_02.png

[UDS_SecurityAccess]: https://github.com/SummerFalls/UDS_SecurityAccess
[UDS_S32K144_Bootloader]: https://github.com/SummerFalls/UDS_S32K144_Bootloader
Expand Down
2 changes: 1 addition & 1 deletion UDS_PortingFiles/UDS_alg_hal.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ boolean UDS_ALG_HAL_DecryptData(const uint8 *i_pCipherText, const uint32 i_dataL
deAes((sint8 *)i_pCipherText, i_dataLen, (sint8 *)&gs_aKey[0], (sint8 *)o_pPlainText);
#endif
#ifdef EN_ZLG_SA_ALGORITHM
/* TODO Bootloader: #02 Simple Security Access Algorithm Decryption function implemented by DTek */
/* TODO Bootloader: #02 Simple Security Access Algorithm Decryption function */
deZLGKey((sint8 *)i_pCipherText, i_dataLen, (sint8 *)o_pPlainText);
#endif
return ret;
Expand Down
22 changes: 11 additions & 11 deletions UDS_PortingFiles/flash_hal_Cfg.c
Original file line number Diff line number Diff line change
Expand Up @@ -321,20 +321,14 @@ boolean FLASH_HAL_GetFlashDriverInfo(uint32 *o_pFlashDriverAddrStart, uint32 *o_
}

/* Get reset handler information */
void FLASH_HAL_GetRestHanlderInfo(boolean *o_pIsEnableWriteResetHandlerInFlash, uint32 *o_pResetHanderOffset, uint32 *o_pResetHandlerLength)
void FLASH_HAL_GetResetHandlerInfo(boolean *o_pIsEnableWriteResetHandlerInFlash, uint32 *o_pResetHandlerOffset, uint32 *o_pResetHandlerLength)
{
ASSERT(NULL_PTR == o_pIsEnableWriteResetHandlerInFlash);
ASSERT(NULL_PTR == o_pResetHanderOffset);
ASSERT(NULL_PTR == o_pResetHandlerOffset);
ASSERT(NULL_PTR == o_pResetHandlerLength);
*o_pIsEnableWriteResetHandlerInFlash = EN_WRITE_RESET_HANDLER_IN_FLASH;
*o_pResetHanderOffset = APP_VECTOR_TABLE_OFFSET + RESET_HANDLER_OFFSET;
*o_pResetHandlerLength = RESET_HANDLER_ADDR_LEN;
}

/* Get storage reset handler information */
uint32 FLASH_HAL_GetStorageRestHandlerAddr(void)
{
return APP_VECTOR_TABLE_OFFSET + RESET_HANDLER_OFFSET;
*o_pIsEnableWriteResetHandlerInFlash = FLASH_HAL_IsEnableStorageResetHandlerInFlash();
*o_pResetHandlerOffset = FLASH_HAL_GetStorageRestHandlerAddr();
*o_pResetHandlerLength = FLASH_HAL_GetResetHandlerLen();
}

/* Is enable write reset handler in flash? */
Expand All @@ -343,6 +337,12 @@ boolean FLASH_HAL_IsEnableStorageResetHandlerInFlash(void)
return EN_WRITE_RESET_HANDLER_IN_FLASH;
}

/* Get storage reset handler information */
uint32 FLASH_HAL_GetStorageRestHandlerAddr(void)
{
return APP_VECTOR_TABLE_OFFSET + RESET_HANDLER_OFFSET;
}

/* Get reset handler addr length */
uint32 FLASH_HAL_GetResetHandlerLen(void)
{
Expand Down
8 changes: 4 additions & 4 deletions UDS_PortingFiles/flash_hal_Cfg.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,14 @@ uint32 FLASH_HAL_GetFlashLengthToSectors(const uint32 i_startFlashAddr, const ui
boolean FLASH_HAL_GetFlashDriverInfo(uint32 *o_pFlashDriverAddrStart, uint32 *o_pFlashDriverEndAddr);

/* Get reset handler information */
void FLASH_HAL_GetRestHanlderInfo(boolean *o_pIsEnableWriteResetHandlerInFlash, uint32 *o_pResetHanderOffset, uint32 *o_pResetHandlerLength);

/* Get storage reset handler information */
uint32 FLASH_HAL_GetStorageRestHandlerAddr(void);
void FLASH_HAL_GetResetHandlerInfo(boolean *o_pIsEnableWriteResetHandlerInFlash, uint32 *o_pResetHandlerOffset, uint32 *o_pResetHandlerLength);

/* Is enable write reset handler in flash? */
boolean FLASH_HAL_IsEnableStorageResetHandlerInFlash(void);

/* Get storage reset handler information */
uint32 FLASH_HAL_GetStorageRestHandlerAddr(void);

/* Get reset handler addr length */
uint32 FLASH_HAL_GetResetHandlerLen(void);

Expand Down
2 changes: 1 addition & 1 deletion UDS_PortingFiles/user_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ typedef enum

/* -------------------- Jump to APP delay time when have not received UDS message -------------------- */
#define EN_DELAY_TIME
#define DELAY_MAX_TIME_MS (5000u)
#define DELAY_MAX_TIME_MS (2000u)

#endif /* USER_CONFIG_H_ */

Expand Down
4 changes: 4 additions & 0 deletions UDS_ProtocolStack/bootloader_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,12 @@ void UDS_MAIN_Init(void (*pfBSP_Init)(void), void (*pfAbortTxMsg)(void))
Boot_PowerONClearAllFlag();
}

#ifndef EN_DELAY_TIME

Boot_JumpToAppOrNot();

#endif

#endif

if (NULL_PTR != pfBSP_Init)
Expand Down
22 changes: 10 additions & 12 deletions UDS_ProtocolStack/fls_app.c
Original file line number Diff line number Diff line change
Expand Up @@ -256,9 +256,8 @@ void Flash_InitDowloadInfo(void)

if (TRUE == IsFlashDriverDownload())
{
#if (defined UDS_PROJECT_FOR_APP) && (MCU_TYPE == MCU_S32K14x)
#else
/* TODO : #00 S32K144 执行本函数会导致 HardFault,S32K118 无此问题,待解决 */
#ifdef UDS_PROJECT_FOR_BOOTLOADER
/* TODO : #00 由于链接文件地址空间分配的问题,APP 中不可执行本函数,否则会导致 HardFault */
Flash_EraseFlashDriverInRAM();
#endif
SetFlashDriverNotDonwload();
Expand All @@ -275,9 +274,8 @@ void Flash_InitDowloadInfo(void)
void FLASH_APP_Init(void)
{
gs_stFlashDownloadInfo.isFingerPrintWritten = FALSE;
#if (defined UDS_PROJECT_FOR_APP) && (MCU_TYPE == MCU_S32K14x)
#else
/* TODO : #00 S32K144 执行本函数会导致 HardFault,S32K118 无此问题,待解决 */
#ifdef UDS_PROJECT_FOR_BOOTLOADER
/* TODO : #00 由于链接文件地址空间分配的问题,APP 中不可执行本函数,否则会导致 HardFault */
Flash_EraseFlashDriverInRAM();
#endif
SetFlashDriverNotDonwload();
Expand Down Expand Up @@ -1050,9 +1048,9 @@ uint8 Flash_WriteFlashAppInfo(void)
uint32 newestAPPInfoLen = 0u;
tAppFlashStatus *pstNewestAPPFlashStatus = NULL_PTR;
uint32 resetHandleAddr = 0u;
boolean bIsEnableWriteResetHandle = FALSE;
uint32 resetHandleOffset = 0u;
uint32 resetHandleLength = 0u;
boolean bIsEnableWriteResetHandlerInFlash = FALSE;
uint32 resetHandlerOffset = 0u;
uint32 resetHandlerLength = 0u;
CreateAndSaveAppStatusCrc(&crc);
oldAppType = Flash_GetOldAPPType();
newestAPPType = Flash_GetNewestAPPType();
Expand All @@ -1062,7 +1060,7 @@ uint8 Flash_WriteFlashAppInfo(void)
{
/* Write data information in flash */
pAppStatusPtr = GetAppStatusPtr();
FLASH_HAL_GetRestHanlderInfo(&bIsEnableWriteResetHandle, &resetHandleOffset, &resetHandleLength);
FLASH_HAL_GetResetHandlerInfo(&bIsEnableWriteResetHandlerInFlash, &resetHandlerOffset, &resetHandlerLength);

/* Update APP cnt */
if (TRUE == FLASH_HAL_GetAPPInfo(newestAPPType, &newestAPPInfoStartAddr, &newestAPPInfoLen))
Expand All @@ -1076,8 +1074,8 @@ uint8 Flash_WriteFlashAppInfo(void)
}

/* Get APP start address from flash. The address is the newest APP, because the APP info not write in flash, so the APP is old */
resetHandleAddr = appInfoStartAddr + resetHandleOffset;
SaveAppResetHandlerAddr(*((uint32 *)resetHandleAddr), resetHandleLength);
resetHandleAddr = appInfoStartAddr + resetHandlerOffset;
SaveAppResetHandlerAddr(*((uint32 *)resetHandleAddr), resetHandlerLength);
FLSDebugPrintf("APP type =%X, APP address=0x%X\n", oldAppType, *((uint32 *)resetHandleAddr));
crc = 0u;
CreateAndSaveAppStatusCrc(&crc);
Expand Down
5 changes: 5 additions & 0 deletions UDS_ProtocolStack/uds_app.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@
#include "fls_app.h"
#include "uds_alg_hal.h"

#ifdef UDS_PROJECT_FOR_BOOTLOADER
#ifdef EN_DELAY_TIME
extern tJumpAppDelayTimeInfo gs_stJumpAPPDelayTimeInfo;
#endif
#endif

void UDS_Init(void)
{
Expand Down
5 changes: 2 additions & 3 deletions UDS_ProtocolStack/uds_app_cfg.c
Original file line number Diff line number Diff line change
Expand Up @@ -867,7 +867,7 @@ tUDSService *GetUDSServiceInfo(uint8 *m_pSupServItem)

#ifdef UDS_PROJECT_FOR_BOOTLOADER
/* If RX UDS msg, set UDS layer received message TURE */
void SetIsRxUdsMsg(const uint8 i_SetValue)
void SetIsRxUdsMsg(const boolean i_SetValue)
{
#ifdef EN_DELAY_TIME

Expand All @@ -883,7 +883,7 @@ void SetIsRxUdsMsg(const uint8 i_SetValue)
#endif
}

uint8 IsRxUdsMsg(void)
boolean IsRxUdsMsg(void)
{
#ifdef EN_DELAY_TIME
return gs_stJumpAPPDelayTimeInfo.isReceiveUDSMsg;
Expand Down Expand Up @@ -1357,7 +1357,6 @@ void UDS_SystemTickCtl(void)
}
else
{
/* Max timeout timeout */
Boot_JumpToAppOrNot();
}
}
Expand Down
6 changes: 2 additions & 4 deletions UDS_ProtocolStack/uds_app_cfg.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,6 @@ typedef struct
boolean isReceiveUDSMsg;
uint32 jumpToAPPDelayTime;
} tJumpAppDelayTimeInfo;

extern tJumpAppDelayTimeInfo gs_stJumpAPPDelayTimeInfo;
#endif
#endif

Expand All @@ -122,9 +120,9 @@ uint8 IsCurSecurityLevelRequet(uint8 i_SerSecurityLevel);
tUDSService *GetUDSServiceInfo(uint8 *m_pSupServItem);

#ifdef UDS_PROJECT_FOR_BOOTLOADER
void SetIsRxUdsMsg(const uint8 i_SetValue);
void SetIsRxUdsMsg(const boolean i_SetValue);

uint8 IsRxUdsMsg(void);
boolean IsRxUdsMsg(void);
#endif

void SetNegativeErroCode(const uint8 i_UDSServiceNum,
Expand Down

0 comments on commit fa7a572

Please sign in to comment.