STM32 趟坑一览
张静茹2021/01/18软件综合 IP:山东


CubeMX 添加RTX



前言:

STM32CubeMX是意法推出的基于STM32的一款强大的可视化开发软件,在常规的产品开发中,可以结合可视化的硬件配置来完成系统平台的初始化配置,选用一些中间软件包,如OS,FS等。

RTX5是Keil公司打造的一款轻量型,实时,低延迟,高可靠,安全的操作系统,MDK开发环境本身集成了RTX5软件包。但STM32CubeMX中不包含RTX5组件包,并不支持RTX5组件包,这需要在STM32CubeMXb生成的工程文件中手动添加RTX5软件包,下面详细阐述该过程,并对其中的编译错误的更正过程进行了的说明。

开发环境:

  • MDK 5.25

  • STM32CubeMX 4.25

  • STM32CubeMX STM32F4 组件包版本为1.21.0

  • RTX5 5.3.0

一. 在STM32CubeMX生成的工程中添加RTX5源码

1. 打开STM32CubeMX工程

如果中间件FreeRTOS被勾选,要勾选掉,防止两个操作系统同时存在:

upload_downloader_1610940249286_45807139.png

2. 生成MDK工程代码

在STM32CubeMX,生成并打开MDK工程代码。

在MDK的工程Options for target ...的Output选显卡中,勾选掉默认的选项"Browse Iniormation",这样可以加快编译速度,否则编译会非常耗时。


3. 增加RTX5软件组件:

upload_downloader_1610940249483_53685877.png

添加RTOS2-->Keil RTX5,这里为5.3.0版本(单击图片可放大):

upload_downloader_1610940279186_24133307.png

如提示出现“Validation Output",点击信息框下面的"Resolve"。

有两种添加RTX5的方式:库和源代码。这里重点说明如何对添加的RTX5源码进行工程编译,所以这里选择"Source"。

上图 “Keil RTX5”对应的右侧栏目选择"Source",然后点击"Resolve"。

二. 工程编译错误的解决

1. "Unknown Arm Architecture!"错误

尝试工程编译,会提示如下的编译错误:

error:  #35: #error directive: "Unknown Arm Architecture!"

删除工程目录Drivers\CMSIS\Include\下的cmsis_armcc.h

这样工程会使用C:\Keil_v5\ARM\PACK\ARM\CMSIS\5.3.0\CMSIS\Include\cmsis_armcc.h

后一个文件的文件头代码如下:

#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 400677)

  #error "Please use Arm Compiler Toolchain V4.0.677 or later!"

#endif

/* CMSIS compiler control architecture macros */

#if ((defined (__TARGET_ARCH_6_M  ) && (__TARGET_ARCH_6_M   == 1)) || \

     (defined (__TARGET_ARCH_6S_M ) && (__TARGET_ARCH_6S_M  == 1))   )

  #define __ARM_ARCH_6M__           1

#endif

#if (defined (__TARGET_ARCH_7_M ) && (__TARGET_ARCH_7_M  == 1))

  #define __ARM_ARCH_7M__           1

#endif

#if (defined (__TARGET_ARCH_7E_M) && (__TARGET_ARCH_7E_M == 1))

  #define __ARM_ARCH_7EM__          1

#endif

  /* __ARM_ARCH_8M_BASE__  not applicable */

  /* __ARM_ARCH_8M_MAIN__  not applicable */

/* CMSIS compiler specific defines */

#ifndef   __ASM

  #define __ASM                                  __asm

#endif

#ifndef   __INLINE

  #define __INLINE                               __inline

#endif

#ifndef   __STATIC_INLINE

  #define __STATIC_INLINE                        static __inline

#endif

#ifndef   __STATIC_FORCEINLINE                

  #define __STATIC_FORCEINLINE                   static __forceinline

#endif          

#ifndef   __NO_RETURN

  #define __NO_RETURN                            __declspec(noreturn)

#endif

#ifndef   __USED

  #define __USED                                 __attribute__((used))

#endif

#ifndef   __WEAK

  #define __WEAK                                 __attribute__((weak))

#endif

...

而在STM32CubeMX生成的Drivers\CMSIS\Include\下的cmsis_armcc.h的文件中并无这些宏定义。

特别,如下宏定义分支有效:

#if (defined (__TARGET_ARCH_7_M ) && (__TARGET_ARCH_7_M  == 1))

  #define __ARM_ARCH_7M__           1

#endif

2. 代码重复冲突错误

再次编译,会出现如下错误:

error: L6235E: More than one section matches selector - cannot all be FIRST/LAST.

这是由于STM32CubeMX生成的工程所包含的启动文件"startup_stm32f439xx.s"(Application/MDK-ARM工程文件夹下,见下图)中,已经存在RESET段。这和RTX5的启动文件"startup_stm32f439xx.s"(Deviece工程文件夹下,见下图)中的代码相冲突:

upload_downloader_1610940249302_42179088.png

将Application/MDK-ARM工程文件夹下的"startup_stm32f439xx.s"文件排除在编译之外:

右键点击Application/MDK-ARM工程文件夹下的文件"startup_stm32f439xx.s",

选中“Options for startup_stm32f439xx.s”菜单,弹出(单击图片可放大):

upload_downloader_1610940249302_25027256.png

勾选掉“include in Target Build",如上图(“include in Target Build"未勾选掉之前)。


编译工程,会出现如下错误:

Error: L6200E: Symbol SystemCoreClock multiply defined (by system_stm32f4xx_1.o and system_stm32f4xx.o).

Error: L6200E: Symbol AHBPrescTable multiply defined (by system_stm32f4xx_1.o and system_stm32f4xx.o).

Error: L6200E: Symbol APBPrescTable multiply defined (by system_stm32f4xx_1.o and system_stm32f4xx.o).

rror: L6200E: Symbol SVC_Handler multiply defined (by stm32f4xx_it.o and irq_cm4f.o).

(单击图片可放大)

upload_downloader_1610940249303_45105712.png

同样的,这是由于STM32CubeMX生成的工程所包含的文件"system_stm32f4xx.c"(Drivers/CMSIS工程文件夹下,见下图)中,已经存在上面编译错误中的段。这和RTX5的文件"system_stm32f4xx.c"(Deviece工程文件夹下,见下图)中的代码相冲突:

upload_downloader_1610940250218_80576118.png

将Drivers/CMSIS工程文件夹中的"system_stm32f4xx.c"排除在编译之外。

工程编译,会提示:

Error: L6200E: Symbol SVC_Handler multiply defined (by stm32f4xx_it.o and irq_cm4f.o).

Error: L6200E: Symbol PendSV_Handler multiply defined (by stm32f4xx_it.o and irq_cm4f.o).

Error: L6200E: Symbol SysTick_Handler multiply defined (by stm32f4xx_it.o and irq_cm4f.o).

同样的,将文件"stm32f4xx_it.c"排除在编译之外。

3.  RTX5示例演示

增加RTX5示例代码:

在"Application/MDK-ARM"列表上点击右键,在弹出的菜单中选中"Add New Item to Group 'Application/User'":

upload_downloader_1610940251158_15975779.png

弹出对话框:

upload_downloader_1610940251479_67736049.png

注意要防止这里的man.c文件存放路径和STM32CubeMX生成的main.c文件的路径相冲突。

在工程中排除掉"Application/User"下的main.c文件的编译。

最后的工程文件列表如下(红色框处的标注为排除在工程编译之外的文件):

upload_downloader_1610940251869_34153400.png

编译工程,提示:

STM32F429_176\STM32F429_176.axf: Error: L6218E: Undefined symbol _Error_Handler (referred from tim.o).

复制"Application/User"下的main.c中的_Error_Handler函数到新增的"Application/MDK-ARM"下的main.c文件中。

在main.c中新增任务,最后的代码如下:

/*----------------------------------------------------------------------------

 * Application main thread

  *---------------------------------------------------------------------------*/

void task1 ( void * argument )

{

 

    // ...

    for (;;){

        osDelay ( 30 );

    }

   

}

 

void task2 ( void * argument )

{

 

    // ...

    for (;;){

        osDelay ( 20 );

    }

   

}

 

int main ( void ) {

 

    // System Initialization

    SystemCoreClockUpdate ();

    #ifdef RTE_Compiler_EventRecorder

        // Initialize and start Event Recorder

        EventRecorderInitialize ( EventRecordError , 1U );

    #endif

    // ...

    osKernelInitialize ();               // Initialize CMSIS-RTOS

    osThreadNew ( task1 , NULL , NULL );     // Create application main thread

    osThreadNew ( task2 , NULL , NULL );     // Create application main thread

    osKernelStart ();                    // Start thread execution

    for (;;) {}

   

}

最后,在MDK的"Project"中,Clean Targets,再次全部编译。

注意,Clean Targets这一步是必须的,否则,调试启动时,无法跳转到最终所使用的main.c文件的main函数中。







来自:计算机科学 / 软件综合
29
 
7
已屏蔽 原因:{{ notice.reason }}已屏蔽
{{notice.noticeContent}}
~~空空如也
张静茹 作者
3年2个月前 修改于 3年2个月前 IP:山东
889305

例如串口同时在DMA发送和DMA接收,DMA接收到一半我要终止DMA的话,只能调用HAL_UART_DMAStop把接收DMA和串口DMA都停止。
换言之,不能单独停止DMA接收。
我理解的接收DMA和发送DMA是两个独立的操作,为什么不能单独停止? 


HAL_UART_DMAStop()函数的确是uart接收和发送同时关闭,找了好久终于找到只关闭接收的函数了。
只关闭接收的函数。HAL_UART_AbortReceive()


XXXXXXXXXXXXXXXXXXXXXXXX/module/forum/XXXXXXXXXXXXXXXXXXXXml

引用
评论
1
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
张静茹作者
3年2个月前 IP:山东
889307

Demo\XXXXXXXt(7): error: L6235E: More than one section matches selector - cannot all be FIRST/LAST.

工程中包含了不只一个启动文件

引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
张静茹作者
3年2个月前 IP:山东
889310

image.png

回头试试

引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
张静茹作者
3年2个月前 修改于 3年0个月前 IP:山东
889311

RTX + HAL 

HAL Tick选择其他定时器提供 SYS->Timebase Source

NVIC->取消SystemTickTimer 取消System service call via swl instruction 取消Pendable request for system service

Keil 中选择RTX 但不要选择启动代码,不然启动代码有两份

内存不足检查RTX默认分配内存太大


引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
张静茹作者
3年2个月前 IP:山东
889340


void Task1(void* args)
{
	osDelay(1000);
	char TxBf[] = "HelloDMA0";
	//HAL_UART_Transmit_DMA(&huart1, (uint8_t*)TxBf, sizeof(TxBf));
	while (1) {

		//HAL_DMA_RegisterCallback(&hdma_usart1_tx, HAL_DMA_XFER_CPLT_CB_ID, Uart1_DMA_TxComplete);
		HAL_UART_Transmit_DMA(&huart1, (uint8_t*)TxBf, sizeof(TxBf)-1);
		//osEventFlagsWait(Uart1_Recv_Event, 01, osFlagsWaitAny, osWaitForever);
		/*__HAL_DMA_CLEAR_FLAG(&hdma_usart1_tx, DMA_FLAG_TC4);
		while (__HAL_DMA_GET_FLAG(&hdma_usart1_tx, DMA_FLAG_TC4) == 0);*/
		while(huart1.gState != HAL_UART_STATE_READY)
		{}	
		
		osDelay(1);
	}
}

DMA发送字符串 串口助手显示数据错乱,原因是C语言字符最后有个\0  串口助手显示错乱

引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
warmonkey
3年2个月前 IP:广东
889341
引用张静茹发表于5楼的内容
DMA发送字符串 串口助手显示数据错乱,原因是C语言字符最后有个\0  串口助手显示错乱

取字符串长度是strlen(str)

引用
评论(1)
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
张静茹作者
3年2个月前 IP:山东
889381
#pragma SAVE           // save current optimization level
#pragma OPTIMIZE(7)    // disable function block optimization
void func (void)  {

}
#pragma RESTORE        // restore original optimization level

keil设置某段程序的优化等级,V6编译器仅支持按文件设置编译等级

引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
Mxxy
3年2个月前 IP:上海
889474

    STM32现在这个芯片涨价厉害的很啊

引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
张静茹作者
3年0个月前 IP:山东
892244

VisualGDB_新建工程无芯片可选.png VisualGDB_环境配置_编译错误解决方法.jpg

新建工程无芯片可选

引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
张静茹作者
3年0个月前 IP:山东
892245

编译错误.png

系统属性 Keil Setting 设置Arm CPU Type 



引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
张静茹作者
3年0个月前 IP:山东
892246

Toolchain选择arm-eabi时不能直接引用Keil的RTX操作系统,即使设置了头文件Include路径

引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
张静茹作者
3年0个月前 修改于 3年0个月前 IP:山东
892251

main.c

stm32f1xx_it.c

stm32f1xx_hal_msp.c

stm32f1xx_hal_timebase_tim.c

stm32f1xx_hal_gpio_ex.c

stm32f1xx_hal_tim.c

stm32f1xx_hal_tim_ex.c

stm32f1xx_hal.c

warning: 'armv4t' is unsupported in this version of the product

warning: 'arm7tdmi' is unsupported in this version of the product

stm32f1xx_hal_rcc.c

warning: 'armv4t' is unsupported in this version of the product

warning: 'arm7tdmi' is unsupported in this version of the product

stm32f1xx_hal_rcc_ex.c

warning: 'armv4t' is unsupported in this version of the product

warning: 'arm7tdmi' is unsupported in this version of the product

stm32f1xx_hal_gpio.c

warning: 'armv4t' is unsupported in this version of the product

warning: 'arm7tdmi' is unsupported in this version of the product

stm32f1xx_hal_dma.c

warning: 'armv4t' is unsupported in this version of the product

warning: 'arm7tdmi' is unsupported in this version of the product

stm32f1xx_hal_cortex.c

warning: 'armv4t' is unsupported in this version of the product

warning: 'arm7tdmi' is unsupported in this version of the product

stm32f1xx_hal_pwr.c

warning: 'armv4t' is unsupported in this version of the product

warning: 'arm7tdmi' is unsupported in this version of the product

stm32f1xx_hal_flash.c

warning: 'armv4t' is unsupported in this version of the product

warning: 'arm7tdmi' is unsupported in this version of the product

stm32f1xx_hal_flash_ex.c

warning: 'armv4t' is unsupported in this version of the product

warning: 'arm7tdmi' is unsupported in this version of the product

stm32f1xx_hal_exti.c

warning: 'armv4t' is unsupported in this version of the product

warning: 'arm7tdmi' is unsupported in this version of the product

system_stm32f1xx.c

warning: 'armv4t' is unsupported in this version of the product

warning: 'arm7tdmi' is unsupported in this version of the product

warning: 'armv4t' is unsupported in this version of the product

warning: 'arm7tdmi' is unsupported in this version of the product

warning: 'armv4t' is unsupported in this version of the product

warning: 'arm7tdmi' is unsupported in this version of the product

warning: 'armv4t' is unsupported in this version of the product

warning: 'arm7tdmi' is unsupported in this version of the product

warning: 'armv4t' is unsupported in this version of the product

warning: 'arm7tdmi' is unsupported in this version of the product

warning: 'armv4t' is unsupported in this version of the product

warning: 'arm7tdmi' is unsupported in this version of the product

fatal error: error in backend: Cannot select: intrinsic %XXXXXXXm.hint

PLEASE submit a bug report to XXXXXXXXXXXXXXXXX/developer-resources/ds-5-technical-support/ and include the crash backtrace, preprocessed source, and associated run script.

Stack dump:

0. Program arguments: C:\Keil_v5\ARM\ARMCLANG\bin\armclang.exe @VisualGDB/Debug/_1_/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc.gcc.rsp 

1. <eof> parser at end of file

2. Code generation

3. Running pass 'Function Pass Manager' on module 'D:/STM32/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc.c'.

4. Running pass 'ARM Instruction Selection' on function '@RCC_Delay'

0x773846D2 (0xE0000046 0x00000000 0x00000000 0x00000000), RaiseException() + 0x62 bytes(s)

0x00E78E76 (0x129E1928 0x02C4BE50 0x0002B3FA 0x076EFB98), ?HandleExit@CrashRecoveryContext@llvm@@QAEXH@Z() + 0x16 bytes(s)

0x002818F7 (0x01756590 0x00000000 0x00000024 0x00000004), ??8DelayImportDirectoryEntryRef@object@llvm@@QBE_NABV012@@Z() + 0x7597 bytes(s)

0x017564EC (0x00000000 0x00000024 0x00000004 0x017565DF), ?Legalize@SelectionDAG@llvm@@QAEXXZ() + 0x13C bytes(s)

0x01756590 (0x073AD078 0x00A4FE24 0x073AD050 0xFFFFFF00), ?Legalize@SelectionDAG@llvm@@QAEXXZ() + 0x1E0 bytes(s)

0x017565DF (0x129E1928 0x00000024 0x00000004 0x00000000), ?Legalize@SelectionDAG@llvm@@QAEXXZ() + 0x22F bytes(s)

0x01673683 (0x129E1898 0x1299F768 0x00000000 0x076EFB98), ?DoInstructionSelection@SelectionDAGISel@llvm@@AAEXXZ() + 0x253 bytes(s)

armclang: error: clang frontend command failed with exit code 70 (use -v to see invocation)

Product: MDK Professional 5.33

Component: ARM Compiler 6.15

Tool: armclang [5dd79400]


Target: arm-arm-none-eabi

armclang: note: diagnostic msg: 

********************


PLEASE ATTACH THE FOLLOWING FILES TO THE BUG REPORT:

Preprocessed source(s) and associated run script(s) are located at:

armclang: note: diagnostic msg: C:\Users\Game\AppData\Local\Temp\stm32f1xx_hal_rcc-68691d.c

armclang: note: diagnostic msg: C:\Users\Game\AppData\Local\Temp\stm32f1xx_hal_XXXXXXXXXXXXX

armclang: note: diagnostic msg: 


********************

Failed to compile stm32f1xx_hal_rcc.c. armclang.exe exited with code 70


========== Project Build Summary ==========

    STM32F103ZET6  built in 00:04

========== Build: 0 Succeeded, 1 Failed, 0 Skipped ==========

warning: 'armv4t' is unsupported in this version of the product

warning: 'arm7tdmi' is unsupported in this version of the product

fatal error: error in backend: Cannot select: intrinsic %XXXXXXXXXXXb

PLEASE submit a bug report to XXXXXXXXXXXXXXXXX/developer-resources/ds-5-technical-support/ and include the crash backtrace, preprocessed source, and associated run script.

Stack dump:

0. Program arguments: C:\Keil_v5\ARM\ARMCLANG\bin\armclang.exe @VisualGDB/Debug/_1_/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_cortex.gcc.rsp 

1. <eof> parser at end of file

2. Code generation

3. Running pass 'Function Pass Manager' on module 'D:/STM32/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_cortex.c'.

4. Running pass 'ARM Instruction Selection' on function '@__NVIC_DisableIRQ'

warning: 'armv4t' is unsupported in this version of the product

warning: 'arm7tdmi' is unsupported in this version of the product

fatal error: error in backend: Cannot select: intrinsic %XXXXXXXm.hint

PLEASE submit a bug report to XXXXXXXXXXXXXXXXX/developer-resources/ds-5-technical-support/ and include the crash backtrace, preprocessed source, and associated run script.

Stack dump:

0. Program arguments: C:\Keil_v5\ARM\ARMCLANG\bin\armclang.exe @VisualGDB/Debug/_1_/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_pwr.gcc.rsp 

1. <eof> parser at end of file

2. Code generation

3. Running pass 'Function Pass Manager' on module 'D:/STM32/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_pwr.c'.

4. Running pass 'ARM Instruction Selection' on function '@HAL_PWR_EnterSLEEPMode'

0x773846D2 (0xE0000046 0x00000000 0x00000000 0x00000000), RaiseException() + 0x62 bytes(s)

0x773846D2 (0xE0000046 0x00000000 0x00000000 0x00000000), RaiseException() + 0x62 bytes(s)

0x00E78E76 (0x12843520 0x02C4BE50 0x0002B3FA 0x076EF730), ?HandleExit@CrashRecoveryContext@llvm@@QAEXH@Z() + 0x16 bytes(s)

0x00E78E76 (0x129EC5B0 0x02C4BE50 0x0002B3FA 0x076919F0), ?HandleExit@CrashRecoveryContext@llvm@@QAEXH@Z() + 0x16 bytes(s)

0x002818F7 (0x01756590 0x00000000 0x00000024 0x00000004), ??8DelayImportDirectoryEntryRef@object@llvm@@QBE_NABV012@@Z() + 0x7597 bytes(s)

0x002818F7 (0x02C4BE50 0x0002B3FA 0x076919F0 0x129EC5B0), ??8DelayImportDirectoryEntryRef@object@llvm@@QBE_NABV012@@Z() + 0x7597 bytes(s)

0x017564EC (0x1285E4DC 0x0777F2C4 0x1289A010 0x076EF730), ?Legalize@SelectionDAG@llvm@@QAEXXZ() + 0x13C bytes(s)

0x1285E4D0 (0x0777F2C4 0x1289A010 0x076EF730 0x07748250) <unknown module>

0x1285E4DC (0x1289A010 0x076EF730 0x07748250 0x00000000) <unknown module>

0x129EC5B0 (0x0002B3FA 0x076919F0 0x129EC5B0 0x00000000) <unknown module>

0x0777F2C4 (0x076EF730 0x07748250 0x00000000 0x00000000) <unknown module>

0x02C4BE50 (0x076919F0 0x129EC5B0 0x00000000 0x12999598), ??_7?$parser@P6APAVScheduleDAGSDNodes@llvm@@PAVSelectionDAGISel@2@W4Level@CodeGenOpt@2@@Z@cl@llvm@@6B@() + 0xDC4 bytes(s)

0x1289A010 (0x0000000F 0x000001CB 0x00000001 0x00000000) <unknown module>

0x0002B3FA (0x129EC5B0 0x00000000 0x12999598 0x0000000C) <unknown module>

0x076919F0 (0x00000000 0x12999598 0x0000000C 0xFFFFE000) <unknown module>

0x07776A00 (0x000001CB 0x00000001 0x00000000 0x00000000) <unknown module>

0x129EC5B0 (0x03E8A5A8 0x00000002 0x0771D6D8 0x00000001) <unknown module>

0x129AB610 (0x00000002 0x0771D6D8 0x00000001 0x00000009) <unknown module>

0x03E8A5A8 (0x0771D6D8 0x00000001 0x00000009 0x0771D638), ?ID@SelectionDAGISel@llvm@@2DA

armclang: error: clang frontend command failed with exit code 70 (use -v to see invocation)

Product: MDK Professional 5.33

Component: ARM Compiler 6.15

armclang: error: clang frontend command failed with exit code 70 (use -v to see invocation)

Tool: armclang [5dd79400]


Product: MDK Professional 5.33

Component: ARM Compiler 6.15

Tool: armclang [5dd79400]

Target: arm-arm-none-eabi


Target: arm-arm-none-eabi

armclang: note: diagnostic msg: 

********************


PLEASE ATTACH THE FOLLOWING FILES TO THE BUG REPORT:

Preprocessed source(s) and associated run script(s) are located at:

armclang: note: diagnostic msg: C:\Users\Game\AppData\Local\Temp\stm32f1xx_hal_cortex-09d854.c

armclang: note: diagnostic msg: C:\Users\Game\AppData\Local\Temp\stm32f1xx_hal_XXXXXXXXXXXXXXXX

armclang: note: diagnostic msg: 


********************

项目属性 KeilSetting 中设置CPU Type

引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
张静茹作者
3年0个月前 修改于 3年0个月前 IP:山东
892386

切换V6 编译器时 FreeRTOS 编译报错

使用

STM32Cube_FW_H7_V1.8.0\Middlewares\Third_Party\FreeRTOS\Source\portable\GCC

替换

STM32Cube_FW_H7_V1.8.0\Middlewares\Third_Party\FreeRTOS\Source\portable\RVDS


定时器触发ADC DMA读不到数据时,要单独声明启动定时器

 HAL_TIM_Base_Start(&htim6); 


引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
张静茹作者
3年0个月前 修改于 3年0个月前 IP:山东
892875

引用RTX 系统 下载后无法调试 

在系统属性中Linker Memory Layout 配置ROM地址 Base ROM address Base RAM address


引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
张静茹作者
3年0个月前 IP:山东
892881

1、问题


KEIL compiler 设置为 “use default compiler version 5” 可以正确编译以下汇编和C混合代码,更改编译器为V6.12后不识别__ASM关键字,并对汇编语法报错。


 替换为


__ASM void MSR_MSP(uint32_t addr)

{

    MSR MSP, r0 

    BX r14

}



2、解决办法


6.12编译器对于汇编和C的混合代码格式做了要求,按照以下方式修改汇编代码,即可编译通过。


void MSR_MSP(uint32_t addr) 

{

    __ASM("MSR MSP, r0"); 

    __ASM("BX r14");

}

 


引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
张静茹作者
3年0个月前 修改于 3年0个月前 IP:山东
892883

Keil 添加RTX引用以后 调试时 永远卡在HardFault_Handler

RTX_Config.h 中 Global Dynamic Memory size 默认设置的32768 太大


 

//   <o>Global Dynamic Memory size [bytes] <0-1073741824:8>

//   <i> Defines the combined global dynamic memory size.

//   <i> Default: 32768



设置的太小会导致 任务不启动

引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
张静茹作者
3年0个月前 修改于 2年11个月前 IP:山东
892906

Keil 在线调试工程运行一切正常,正常运行无法启动

Keil勾选MicroLib ,printf 重定向错误

即便勾选MicroLib 如果重定向没有实现或实现错误 也会导致软件无法自行启动运行,但调试运行一切正常



STM32F103_MD HD 定义错误 全部重新编译

usb转串口导致 芯片不正常复位


引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
张静茹作者
2年11个月前 IP:山东
892943

Additional Memories 报错的话  先保存 再添加

C++

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

    <ExtraMemories>

        <ExtraMemoryDefinition>

            <Name>RAM_ITC</Name>

            <Address>0</Address>

            <Size>131072</Size>

            <Type>RAM</Type>

            <ContainsText>true</ContainsText>

            <ContainsData>true</ContainsData>

            <ContainsBSS>true</ContainsBSS>

            <PreserveUnusedSymbols>false</PreserveUnusedSymbols>

        </ExtraMemoryDefinition>

        <ExtraMemoryDefinition>

            <Name>RAM_DTC</Name>

            <Address>536870912</Address>

            <Size>131072</Size>

            <Type>RAM</Type>

            <ContainsText>true</ContainsText>

            <ContainsData>true</ContainsData>

            <ContainsBSS>true</ContainsBSS>

            <PreserveUnusedSymbols>false</PreserveUnusedSymbols>

        </ExtraMemoryDefinition>

    </ExtraMemories>


引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
张静茹作者
2年11个月前 IP:山东
892944

狗x的IDE 引用了一个库文件 死活都报找不到函数,找了一天时间才发现还需要右键设置Item Type 为库

而我以前引用都只是添加到工程里就可以的

引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
张静茹作者
2年11个月前 IP:山东
892986

Keil调试代码 在一些莫名其妙的位置卡住 赋值都会跑飞,也不进硬件异常中断


CUBE的调试端口设置错误

中断向量表设置错误


#ifdef VECT_TAB_SRAM

  SCB->VTOR = D1_AXISRAM_BASE  | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal AXI-RAM */

#else

  SCB->VTOR = FLASH_BANK1_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */

#endif


引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
张静茹作者
2年11个月前 IP:山东
893075
.text :
	{
		. = ALIGN(4);
		_stext = .;

		*(EXCLUDE_FILE(*main.o) .text .text*) //排除main.o

		*(.text)
		*(.text*)
		*(.rodata)
		*(.rodata*)
		*(.glue_7)
		*(.glue_7t)
		KEEP(*(.init))
		KEEP(*(.fini))
		. = ALIGN(4);
		_etext = .;

	} > FLASH	
	
	
	.qspi_text (NOLOAD) :
	{
		. = ALIGN(4);
		_sqspi_text = .;

		PROVIDE(__qspi_text_start = _sqspi_text);
		*(.qspi_text)
		*(.qspi_text*)
		*main.o (.text .text*) //lds main.o添加到外部flash
		. = ALIGN(4);
		_eqspi_text = .;

		PROVIDE(__qspi_text_end = _eqspi_text);
	} > QSPI
	




引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
张静茹作者
2年11个月前 修改于 2年11个月前 IP:山东
893263

STM32内部RAM在线调试配置方法及详细说明(基于Keil开发工具)

 

 

 




Ⅰ、
写在前面

本文主要讲述的内容:基于Keil开发工具下,STM32内部RAM在线调试配置方法,以及每一项配置的详细说明。如需要了解更多相关的文章,可以到我博客,或微信公众号查看。

 

让程序运行在RAM中调试代码有两优点:1.速度快;2.减少对芯片FLASH读写次数,增加芯片寿命。

 

本文牵涉的知识比较多,如果弄明白所有细节问题,对自己这方面的技能是一种很大的提升。

 

本文基于ST公司Cortex-M内核的STM32来讲述其配置方法,其实也适用于其他公司(如:TI、NXP等)的Cortex-M芯片,原理都是一样的。

 

 

本文内容已经整理成PDF文件,提供给大家下载:

 

XXXXXXXXXXXXXXXXXXXXX/s/1dEHFwlF
XXXXXXXXXXXXXXXXXXXX/s/1dEHFwlF

 

更多关于STM32的文章,可以进入我博客查看:

XXXXXXXXXXXXXXXXXXXt/ybhuangfugui
XXXXXXXXXXXXXXXXXXXt/ybhuangfugui

 

 


关于本文的更多详情请往下看。

 


Ⅱ、本文要点



1.主要内容

由于本文牵涉的内容比较多,我会按章节来讲述各项内容,大体分为:

l 实现STM32内部RAM调试的配置方法

l 每条配置的详细说明

l 网上配置方法说明及存在的不足

 


2.工程代码下载

 

为了方便大家学习,我将配置前(一般常用)工程和配置后工程分别打包上传至百度网盘供大家下载参考学习。配置前和配置后工程实现的功能都是一样的。本文以STM32F1系列芯片为例(其他芯片类似)。

 

配置前工程代码STM32F10x_Demo:

XXXXXXXXXXXXXXXXXXXXX/s/1gfx8J6b
XXXXXXXXXXXXXXXXXXXX/s/1gfx8J6b

 

配置后工程代码STM32F10x_Demo(RAM调试):

XXXXXXXXXXXXXXXXXXXXX/s/1cDXYQM
XXXXXXXXXXXXXXXXXXXX/s/1cDXYQM

 

注意:由于许多网盘近年来受到影响都相继停止服务或关闭了,如果网盘链接失效,可以微信公众号查看更新链接,或微信联系作者。

 

 


3.代码功能描述

上面提供下载的代码实现的功能是一样的,具体如下两点:

l 间隔500ms LED亮灭变化一次,串口打印数据“Demo..”一次。

l 串口中断接收数据,会将收到数据通过串口发送出去。

 

第一点是为了有一个状态显示,知道程序在运行。

第二点在本文中的作用也很大,就是使用了中断功能。由于RAM调试会牵涉到向量表,中断功能就会使用到向量表,如果没有配置正确,这里就不会响应中断,或者出错。

 


4.验证配置成功方法

本文提供的“STM32F10x_Demo”是断电后重新上电会继续运行代码;而“STM32F10x_Demo(RAM调试)”是断点之后程序丢掉了,也就是不能运行了【请更加LED及串口打印现象来判断】。

 

注意:使用RAM调试之前请将FLASH里面的数据擦除掉,否则使用RAM调试断电再上电,程序会从FLASH运行,会认为程序依然在运行,从而影响判断。

 



Ⅲ、RAM调试配置方法

本节主要讲述配置方法的过程,为什么这么配置,以及配置的原理将会在下一章节讲述。

 



1.修改内存地址

打开目标配置:Project -> Options for Target -> Target或“工程目标配置”点击快捷按钮。

 

将ROM和RAM地址映射到如下图地址。 我们使用STM32F103ZE芯片,该芯片的RAM大小为0x10000即64KB,我们这里平分RAM,即各自的大小为0x5000。

 

注意:配置的地址范围不能超过芯片实际的大小

外链图片已失效,请作者重新上传

 



2.配置向量表

同上,打开目标配置:Project -> Options for Target -> C/C++,使用宏定义
VECT_TAB_SRAM。如下图:

外链图片已失效,请作者重新上传

这里的宏定义是为了让向量表指向RAM(我们默认是指向ROM),重要的一个目的就是让中断向量表指向RAM,上面“代码功能”中断的意义就是为了验证向量表的正确性。

 

注意:这里的宏定义是在工具链中配置的,多个宏定义之间需要有“逗号”隔离开来。

 

其实这里的宏定义配置也可以在源代码中实现,打开system_stm32f10x.c文件下第127行的“VECT_TAB_SRAM”宏定义,如下图:

外链图片已失效,请作者重新上传

【个人建议:调试和非调试代码最好一致,也就是源代码不变】

 



3.调试配置

同上:
Project
 -> Options for Target -> Debug, 这里是关于调试的配置。

第一步:去掉“Load Application at Startup”前面的勾选项

第二步:导入RAM初始化文件。

外链图片已失效,请作者重新上传

 

 

RAM初始化文件里面内容如下:

FUNC void Setup (void) {

  SP = _RDWORD(0x20000000);

  PC = _RDWORD(0x20000004);

  _WDWORD(0xE000ED08, 0x20000000);

}

 

LOAD Objects\ExecutableFile.axf INCREMENTAL

Setup();

g, main

 

每一条语句具体意思请见源代码注释,这里提示的是Objects\ExecutableFile.axf

也就是输出路径输出文件名,它的路径与文件名与你工程配置需对应。

 



4.调试不更新目标程序

同上:Project -> Options for Target -> Utilities,不勾选“更新”。意思就是在线调试时,不更新芯片(下载FLASH)程序。

外链图片已失效,请作者重新上传

 

至此,STM32内部RAM在线调试配置方法就完成了,连接开发板就可以使用RAM在线调试代码了。

 

网上相关的问题还有其他无关的配置,我会在下面单独说明一下为什么不用配置那些。

 



Ⅳ、配置说明

上面配置过程已经知道了,这一节讲述一下为什么这样配置,以及这么配置的意思。

 


1.修改内存地址说明

外链图片已失效,请作者重新上传

内存地址为什么ROM设置为0x20000000,RAM设置为0x20005000。原因在于芯片的RAM其实地址就是0x20000000(没有猜错的话Cortex-M那芯片RAM起止地址都是0x20000000)。

 

至于大小嘛,就是看芯片型号了,我们这里平分大小,也可以不用平分大小。

 

这里分配的地址会直接影响输出的文件“XXXXXXXXXXXXXXXXXt”,也就是我们链接的时候需要使用到的
“XXXXXXXXXXXXXXXXXt”文件

 

查看“XXXXXXXXXXXXXXXXXt”文件的方法:Project -> Options for Target -> Linker,如下图。【需要编译之后才能输出“XXXXXXXXXXXXXXXXXt”文件,即编译后才能查看】

外链图片已失效,请作者重新上传

 

对比没有配置RAM调试(也就是没有修改地址)的工程如下图:

外链图片已失效,请作者重新上传

 

网上配置教程说要修改Linker下的地址,其实是多余的,详情请见下一章节

 


2.配置向量表说明

外链图片已失效,请作者重新上传

爱思考(或者会寻到问题)的朋友可能会发现,我
不宏定义VECT_TAB_SRAM这个参数,程序照常可以运行(LED变化、串口打印数据)。

 

其实这里的配置主要是针对“向量表”,比如中断向量表。如果当我们不宏定义VECT_TAB_SRAM这个参数,测试串口中断的时候,程序就会跑死,(暂停)程序会指向一个非法的地址,如下图:

外链图片已失效,请作者重新上传

 


3.调试配置说明

外链图片已失效,请作者重新上传

这个地方的配置很好理解,就是我们要将程序指针指向我们特定的地址(RAM)区域,这样好让程序执行我们指定地址里面的程序。

 

我们加载文件“XXXXXXXXXi”,因此不需要勾选“Load Application at Startup”这个选项。

 

加载文件的名称“XXXXXXXXXi”和网上一些教程命名一样,可以自己命名,只要后缀名一样就行。

 


4.调试不更新目标程序说明

外链图片已失效,请作者重新上传

这个地方其实就是在调试的时候更新(下载)芯片FLASH的代码,由于我们没有修改FLASH的烧写算法,这里就不勾选次选项。

 

当我们修改了FLASH的烧写算法(程序指向RAM),这里可以勾选上。

 

相比两者,我们选择不勾选该选项简单一点,因此这里选择不勾选。

 


Ⅴ、网上配置说明

笔者开始学习RAM调试的内容时,也是参考网上很多的教程,但是经过笔者亲自,并且多次测试发现网上的有些教程存在不足之处。本节主要是提出网上某些教程存在的不足或者多余之处。【若有不对之处敬请谅解】

 



1.修改Linker地址

Project -> Options for Target -> Linker

外链图片已失效,请作者重新上传

网上的配置,这里的地址基本上都是修改了的。

1.去掉勾选; 2.再次修改地址。

 

我刚开始学习配置时也是修改了的,但后面我再次配置时发现一个问题:地址前面为勾选。什么意思呢,就是没有使用这个配置的地址。

 

于是我就不配置(不修改)这里的地址进行验证,结果还是可以在RAM中调试,大量测试也没发现什么问题。

 

我再次查看Scatter File文件“XXXXXXXXXXXXXXXXXt”,发现不修改地址也是一样的。其实“XXXXXXXXXXXXXXXXXt”文件的地址是我上一章节里面说的,由Target里面的地址决定的。

 

因此,网上所配置的这里其实是多余的配置。

 



2.配置向量表

有很多教程使用了在main函数开始配置向量表,也就是在main函数开始出增加一条语句:NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);

 

这条语句其实是system_stm32f10x.c文件里面第265行的:SCB -> VTOR = SRAM_BASE | VECT_TAB_OFFSET;一样的意思。

 

因此,我个人觉得,项目中的调试代码和真正运行的源代码不能有差异。定义了VECT_TAB_SRAM这个宏定义,就没必要还在main函数里面增加一条语句。

 

细心的朋友可能会发现,我在“Ⅲ、RAM调试配置方法”这一章节中没有修改源代码,只是修改了配置。这样就保证了代码的一致性

 


3.修改编程地址

网上有很多教程是修改了下图中编程的地址,也就是修改了编程算法。

外链图片已失效,请作者重新上传

 

作为调试,本来就是运行在RAM中,还在这里配置,我觉得是多次一举。因此我们上面讲述的是没有勾选“Update Target Before Debugging”

 

 


Ⅵ、说明

STM32内部RAM调试代码时,复位不起作用,需要复位请重新链接运行。关于RAM在线调试配置还有许多未讲述完,请亲自配置并测试验证,你或许会明白更多有用知识。

 

以上总结仅供参考,若有不对之处,敬请谅解。

 


Ⅶ、最后

我的网站:XXXXXXXXXXXXXXXXXXXXXXXXXXXXX/
XXXXXXXXXXXXXXXXXXXXXXXXXXXXX

我的微信公众号(ID:strongerHuang)还在分享STM8、STM32、Keil、IAR、FreeRTOS、UCOS、RT-Thread、CANOpen、Modbus…等更多精彩内容,如果想查看更多内容,可以关注我的微信公众号。

 


引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
张静茹作者
2年11个月前 修改于 2年10个月前 IP:山东
893292

reset后程序异常,dump对比了 reset前后的内存变化 看到是 osRtxInfo

memset(&amp;amp;amp;osRtxInfo, 0, sizeof(osRtxInfo)); //问题解决


dump binary memory stm32h7dumpmemfiledata 0x24019a3c 0x24019d07

引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
张静茹作者
2年10个月前 IP:山东
893785

将代码烧写到sram中 需要在flash 中跳转到 sram中,不然reset后 程序无法运行



typedef  void (*pFunction)(void);

pFunction JumpToApplication;



/* Disable CPU L1 cache before jumping to the QSPI code execution */

    SCB_DisableICache();

    SCB_DisableDCache();

  /* Disable Systick interrupt */

  SysTick->CTRL = 0;


//HAL_DeInit();

__disable_irq();

  /* Initialize user application's Stack Pointer & Jump to user application */

  JumpToApplication = (pFunction) (*(__IO uint32_t*) (0x24000000 + 4));

__DSB();

__ISB();

  __set_MSP(*(__IO uint32_t*) 0x24000000);

__DSB();

__ISB();

__enable_irq();

  JumpToApplication();


引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
张静茹作者
2年10个月前 IP:山东
893810

u32 ltdc_lcd_framebuf[1280][800] __attribute__((section(".ARM.__AT_0xC0000000")));

u32 ltdc_lcd_framebuf[1280][800] __attribute__((at(0xC0000000)));


Keil AC6编译器 需要使用__attribute__((section(".ARM.__AT_0xC0000000")));

AC5编译器 使用 __attribute__((at(0xC0000000)));

GCC 如下




//E.g. int RAM_D1_DATA g_Initialized = 1;

#define RAM_D1_DATA __attribute__((section(".ram_d1_data")))

//E.g. int RAM_D1_BSS g_Uninitialized;

#define RAM_D1_BSS __attribute__((section(".ram_d1_bss")))


//E.g. int RAM_D2_DATA g_Initialized = 1;

#define RAM_D2_DATA __attribute__((section(".ram_d2_data")))

//E.g. int RAM_D2_BSS g_Uninitialized;

#define RAM_D2_BSS __attribute__((section(".ram_d2_bss")))

//E.g. int RAM_D3_DATA g_Initialized = 1;

#define RAM_D3_DATA __attribute__((section(".ram_d3_data")))


//E.g. int RAM_D3_BSS g_Uninitialized;

#define RAM_D3_BSS __attribute__((section(".ram_d3_bss")))



//E.g. int SDRAM_DATA g_Initialized = 1;

#define SDRAM_DATA __attribute__((section(".sdram_data")))


//E.g. int SDRAM_BSS g_Uninitialized;

#define SDRAM_BSS __attribute__((section(".sdram_bss")))



//E.g. void QSPI_TEXT func();

#define QSPI_TEXT __attribute__((section(".qspi_text")))


//E.g. int QSPI_DATA g_Initialized = 1;

#define QSPI_DATA __attribute__((section(".qspi_data")))


//E.g. int QSPI_BSS g_Uninitialized;

#define QSPI_BSS __attribute__((section(".qspi_bss")))



引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
张静茹作者
2年10个月前 IP:山东
893828

stm32 Malloc 申请到外部SDRAM 的内存

在LDS链接脚本中将HEAP段往前挪到 外部存储之前

引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
上官元枫_BD4VOT
6个月15天前 IP:江苏
925301

阅1

引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
张静茹作者
3个月10天前 IP:山东
927753

Cortex-M 处理器 hardfault 定位方法和步骤(基于Keil mdk)

一. 问题的产生

Hard fault (硬错误,也有译为硬件错误的)是在STM32上编写程序中所产生的错误,造成Hard Fault错误的可能原因较多,排除硬件问题,如何在代码量较大的情况下,快速定位造成的hardfault的问题代码,就成为比较关键的问题。

本文将基于STM32处理器(stm32f091),keil-MDK开发环境,总结hardfault的调试定位方法。在其他Cortex-M0 (m3,m4)内核处理器,和其他开发环境下,也可作为参考。

二. Cortex-M 处理器内核异常中断简介

1)错误种类

对于Cortex-M内核,架构采用错误异常的机制来检测问题,当核心检测到一个错误时,异常中断会被触发,并且核心会跳转到相应的异常终端处理函数执行,错误异常的终端分为以下四种:

HardFault
MemManage
BusFault
UsageFault

其中hardfault为最常见的错误类型,并且,在没有开启其他异常处理的情况下,默认进入hardfault异常中断处理函数:

void HardFault_Handler(void)
{
/* USER CODE BEGIN HardFault_IRQn 0 */
/* USER CODE END HardFault_IRQn 0 */
  while (1)
  {
    /* USER CODE BEGIN W1_HardFault_IRQn 0 */
    /* USER CODE END W1_HardFault_IRQn 0 */
  }
}
2) 可能的原因

从软件角度,产生hardfault的可能原因有:

(1) 数组越界
(2)野指针
(3)未初始化硬件却开始操作,或无中断服务函数等

(4)任务堆栈溢出

《ARM Cortex-M0权威指南》中提到,关于 Cortex M0+内核主要有以下几点引起 HardFault 的原因:


非法存储器访问
非对齐数据访问
从总线返回错误
异常处理中的栈被破坏
程序在某些 C 函数中崩溃
意外地试图切换至 ARM 状态
在错误的优先级上执行系统服务调用指令(SVC)

下面将以一个stm32f091上运行的数组越界代码为例,具体阐述定位步骤:

产生越界的代码段:

void StackFlow(void)
{

  int a[3],i;

  for(i=0; i<10000; i++)
  {

    a[i]=1;

  }
}
三. 人工查找hardfault 方法和步骤

方法1.查看寄存器

1)查看fault种类

通过菜单栏Peripherals >Core Peripherals >Fault Reports打开fault reports

upload_downloader_1702949813167_68063077.png

 

2)调试定位步骤

查看fault种类有时可能对解决问题并没有直接帮助,关键是如何定位在进入异常中断前执行的代码段,步骤如下:

a. 确定当前使用堆栈是MSP还是PSP

异常发生后会把进入异常前的 R0-R3,R12, LR, PC,PSR 寄存器值栈入 Main Stack 或Process Stack(取决于异常发生时使用的哪个栈)。 进入异常后链接寄存器 LR 中存放异常返回值 EXC_RETURN, 如果其 bit 2=0 那么用的就是 Main Stack,如果 bit 2=1,那么用的就是 Process Stack。

  upload_downloader_1702949812992_6410919.png

  upload_downloader_1702949813161_95694832.png

 

由下图可以看出,当前使用的堆栈为PSP

  upload_downloader_1702949812599_14694682.png

 

b.找到异常发生代码地址

在memory中,定位到堆栈地址:0x200020E0,依据:R0~R3、R12、LR、PC、XPRS 顺序,找到LR的值,即第6个寄存器值

  upload_downloader_1702949812563_65983676.png

 

LR = 0x0800632B

PC = 0x08006300

c.Disassembly中,查找定位代码

在反汇编窗口中点击右键,选中show disassembly at address 。

输入LR地址:为发生异常后调用的下一条指令的地址,可看到发生异常的为StackFlow()函数

  upload_downloader_1702949813214_3487211.png

 

 

输入PC地址:可以定位到发生异常的调用语句

  upload_downloader_1702949813111_8805558.png

 

方法2:调试步骤
在仿真状态下,调出Call Stack Window,可直接跳转到调用代码

  upload_downloader_1702949813001_32017377.png

 

四. 程序查找hardfault 方法和步骤

实际环境中,由于测试时产品常常无法连接调试器,故需要代码来定位目标语句地址,并通过一定手段保存:

在stm32中,需先修改启动文件startup_stm32f091xc.s:

HardFault_Handler\
PROC
MOVS r0, #4
MOV r1, LR
TST r0, r1
BEQ stacking_used_MSP
MRS R0, PSP
B get_LR_and_branch
stacking_used_MSP
MRS R0, MSP
get_LR_and_branch
MOV R1, LR
IMPORT hard_fault_handler_c
BL hard_fault_handler_c
ENDP
该段代码会判断当前堆栈使用的是MSP或PSP,然后将堆栈参数传递给hard_fault_handler_c函数,该函数定义如下:

void hard_fault_handler_c(unsigned int * hardfault_args, unsigned lr_value)
{
  unsigned int stacked_r0;
  unsigned int stacked_r1;
  unsigned int stacked_r2;
  unsigned int stacked_r3;
  unsigned int stacked_r12;
  unsigned int stacked_lr;
  unsigned int stacked_pc;
  unsigned int stacked_psr;
  stacked_r0 = ((unsigned long) hardfault_args[0]);
  stacked_r1 = ((unsigned long) hardfault_args[1]);
  stacked_r2 = ((unsigned long) hardfault_args[2]);
  stacked_r3 = ((unsigned long) hardfault_args[3]);
  stacked_r12 = ((unsigned long) hardfault_args[4]);
  stacked_lr = ((unsigned long) hardfault_args[5]);
  stacked_pc = ((unsigned long) hardfault_args[6]);
  stacked_psr = ((unsigned long) hardfault_args[7]);
  while(1)
  {
    printf ("[Hard fault handler]\n");
    printf ("R0 = %x\n", stacked_r0);
    printf ("R1 = %x\n", stacked_r1);
    printf ("R2 = %x\n", stacked_r2);
    printf ("R3 = %x\n", stacked_r3);
    printf ("R12 = %x\n", stacked_r12);
    printf ("Stacked LR = %x\n", stacked_lr);
    printf ("Stacked PC = %x\n", stacked_pc);
    printf ("Stacked PSR = %x\n", stacked_psr);
    printf ("Current LR = %x\n", lr_value);

  for(int i = 10000;i>0;i--)
  for(int j = 1000;j>0;j--);
  }

  //while(1); // endless loop
}

代码跑死后,会将R0~R3、R12、LR、PC信息通过串口打印,之后根据寄存器信息排查问题代码即可~

参考资料:

(1)XXXXXXXXXXXXXXXXXXXXt/geek_liyang/article/details/83510518

(2)XXXXXXXXXXXXXXXXXXXXt/Maple_Leaf_15/article/details/51443310

(3)XXXXXXXXXXXXXXXXXXXXXXXX/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXml

(4)XXXXXXXXXXXXXXXXXXXXt/Wang_yf_/article/details/75003611

(5)XXXXXXXXXXXXXXXXXXXXXXX/s/blog_XXXXXXXXXXXXXXXXXXXml

(6)XXXXXXXXXXXXXXXXXXXXt/guozhongwei1/article/details/88418760

(7)XXXXXXXXXXXXXXXXXXXXXXXXX/thread/306244

(8)XXXXXXXXXXXXXXXXXXX/appnotes/files/apnt209.pdf

(9)《ARM Cortex-M0权威指南》Joseph Yiu 著,宋岩 译


引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
张静茹作者
3个月10天前 IP:山东
927754

关于MDK仿真Fault Report

根据官方给出的进行翻译的,有兴趣的可以点链接看看



故障报告对话框

故障报告对话框显示故障的类型,用于故障的处理程序,相应的故障状态寄存器以及指示故障已发生的寄存器位。


1. 内存管理错误


MM_FAULT_ADDR包含导致内存故障的地址。

MM_FAULT_STAT包含以下内存管理故障状态寄存器设置:

当处理器尝试从不允许执行的位置提取指令时,将设置IACCVIOL。

当处理器尝试在不允许该操作的位置加载或存储时,将设置DACCVIOL。

MMARVALID当MM_FAULT_ADDR持有有效的故障地址设置。

当为异常返回而取消堆栈导致一个或多个访问冲突时,将设置MUNSTKERR。

堆叠例外条目导致一个或多个访问冲突时,将设置MSTKERR。


2. 总线故障


BUS_FAULT_ADDR包含导致总线故障的总线地址。

BUS_FAULT_STAT包含以下总线故障状态寄存器设置:

当处理器在预取指令时检测到指令总线错误并尝试发出有故障的指令时,将设置IBUSERR。

当发生数据总线错误时,将设置PRECISERR,并且为异常返回而堆叠的PC值指向引起故障的指令。

当发生数据总线错误时,将设置IMPRECISERR,但是堆栈帧中的返回地址与导致错误的指令无关。

当为异常返回而取消堆栈导致一个或多个BusFault时,将设置UNSTKERR。

当堆栈的异常条目引起一个或多个BusFault时,将设置STKERR。

BFARVALID当BUS_FAULT_ADDR持有有效的故障地址设置。


3. 使用错误错误

USAGE_FAULT_STAT包含以下使用故障状态寄存器设置:

当处理器尝试执行未定义的指令时,将设置UNDEFINSTR。

当处理器试图执行非法使用EPSR的指令时,将设置INVSTATE。

当处理器由于无效上下文或无效EXC_RETURN值而试图向PC非法加载EXC_RETURN时,将设置INVPC。

当处理器尝试访问协处理器时,将设置NOCP。不支持协处理器。

当处理器进行未对齐的内存访问时,将设置UNALIGNED。

DIVBYZERO当处理器已执行与0除数SDIV或UDIV指令被设定。


4. 硬故障

HARD_FAULT_STAT包含以下硬故障状态寄存器设置:

VECTBL设置为指示在异常处理期间读取的向量表上的 BusFault

强制设置为指示强制HardFault,通过配置优先级的故障无法处理的升级产生的,或者是因为优先或因为它被禁用

DEBUGVT保留供调试使用。


5. 调试错误

DBG_FAULT_STAT包含以下调试故障状态寄存器设置:

当处理器暂停时,将设置为“ HALTED”。

遇到软件断点时设置BKPT。

发生观察点匹配时,将设置DWTTRAP。

触发向量捕捉时,将设置VCATCH。

断言EDBGRQ行时设置EXTERNAL。


引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论

想参与大家的讨论?现在就 登录 或者 注册

所属专业
上级专业
同级专业
张静茹
进士 学者 机友 笔友
文章
138
回复
1857
学术分
1
2010/12/30注册,2个月0天前活动
暂无简介
主体类型:个人
所属领域:无
认证方式:手机号
IP归属地:未同步
文件下载
加载中...
{{errorInfo}}
{{downloadWarning}}
你在 {{downloadTime}} 下载过当前文件。
文件名称:{{resource.defaultFile.name}}
下载次数:{{resource.hits}}
上传用户:{{uploader.username}}
所需积分:{{costScores}},{{holdScores}}下载当前附件免费{{description}}
积分不足,去充值
文件已丢失

当前账号的附件下载数量限制如下:
时段 个数
{{f.startingTime}}点 - {{f.endTime}}点 {{f.fileCount}}
视频暂不能访问,请登录试试
仅供内部学术交流或培训使用,请先保存到本地。本内容不代表科创观点,未经原作者同意,请勿转载。
音频暂不能访问,请登录试试
支持的图片格式:jpg, jpeg, png
插入公式
评论控制
加载中...
文号:{{pid}}
投诉或举报
加载中...
{{tip}}
请选择违规类型:
{{reason.type}}

空空如也

加载中...
详情
详情
推送到专栏从专栏移除
设为匿名取消匿名
查看作者
回复
只看作者
加入收藏取消收藏
收藏
取消收藏
折叠回复
置顶取消置顶
评学术分
鼓励
设为精选取消精选
管理提醒
编辑
通过审核
评论控制
退修或删除
历史版本
违规记录
投诉或举报
加入黑名单移除黑名单
查看IP
{{format('YYYY/MM/DD HH:mm:ss', toc)}}