我有一个带有特殊类型FLASH存储器的Cortex M3部件.该部分在此FLASH上启动,但我需要运行一个函数来优化FLASH的速度.执行此操作的唯一方法是跳转到RAM并在那里执行这些功能(因为如果在正在优化的FLASH上运行,函数将崩溃).
ARM允许分散加载.这是一个解决方案,因为我可以将函数放入RAM并在我到达main后运行它们.但是我不想在没有优化的FLASH的情况下执行所有的分散加载.所以我想在main之前运行该函数,这意味着从重置处理程序,或从SystemInit(从重置处理程序调用).
我写了一些位于ROM中的汇编函数.在启动时,我调用我写的Relocate函数,然后将其他函数复制到RAM,然后我跳转到它们.这很有效.
我的问题是:
在.s文件中,我有我将重新定位的函数.要使用这些重定位函数,我加载PROC标签,然后减去(FLASH - RAM)的偏移量.这感觉不便携.是否有另一种方法来计算重定位函数的正确PROC地址?例如:
foo PROC
...
...
ENDP
Run Code Online (Sandbox Code Playgroud)foo从0x24000000的ROM开始,我需要将其移动到0x8000的RAM.有没有办法声明foo存在于0x8000,即使它必须存储在ROM中?或者有没有办法声明foo_reloc生活在0x8000?这也适用于THUMB代码,因为foo可能从0x24000001开始,需要在0x8001处调用.
谢谢,Nachum
我正在使用STM32F107 cortex m3微控制器。我正在为项目使用Keil uvision IDE。我有一个在起始位置即正确运行的应用程序0x0800 0000。如果我将起始位置更改0x0800 4000为应用程序,则无法正常工作。我使用此函数对向量表的位置进行了如下更改:
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x8004000)
Run Code Online (Sandbox Code Playgroud)
即更改SCB->VTOR = 0x8004000到此位置。
但是即使执行完此中断也不会发生。我应该做更多的事情来使这个项目起作用吗?
在Cortex M3上,一段代码如何确定是否启用了中断,即I程序状态寄存器中的位状态(由cpsid和操纵cpsie)?在较旧的ARM上,我能够读取cpsr寄存器,但似乎不再可能.
我需要这些信息,因为我有一个从main和中断调用的函数,它需要以原子方式执行某个操作,而中断则被禁用.实质上:
bool interrupts_enabled = InterruptsEnabled();
if (interrupts_enabled) {
__disable_irq();
}
Critical Code;
if (interrupts_enabled) {
__enable_irq();
}
Run Code Online (Sandbox Code Playgroud)
另外,我想知道I执行中断时标志的行为.执行中断是否会设置I标志,以防止嵌套?默认情况下是否启用了中断嵌套,如何防止嵌套?
是什么原因Cortex-M3的初始堆栈指针值位于0x0,复位处理程序位于0x4?这个的设计理由是什么?
为什么ARM人员不能像重置处理器那样将0x0留给重置处理程序,然后在重置处理程序内初始化SP?
现在我正在尝试了解 STM32F103x 的启动顺序。如您所知,这是基于 cortex-m3。所以我试图找到这个启动的概念,比如 STM32F103x .. 但是我在文档中找不到任何地方我在哪里可以在ARM 内存映射上找到作为 STM32 的启动序列?
因为我想知道系统内存实际上是做什么的?
目前。我试图了解 cortex m3 地址映射中的系统内存。大多数示例都说“有 2 个区域,例如 0x08000000 闪存区域和 0x1FFFF000 系统内存区域。
我知道闪存区域正在为执行文件保存,而系统内存正在为引导加载程序保存。
例如,我可以从在 Keil uVision 中使用 startup_CMSDK_CM3.s 和 startup_CMSDK_CM3.c 的构建生成一个十六进制二进制文件。然后我通过使用JTEG将一个十六进制二进制文件放入STM32 MCU中到闪存区域的0x0800_0000而不是系统内存区域。
我不确定系统内存和闪存之间的区别,我想知道“系统内存和区域实际上有什么作用?”
刚刚从eBay上购买了这些ARM Cortex-M3 LPC1768迷你主板之一.它基本上是一个突破板.
但是,基于它带来的小文档,我已经确定它有一个类似于恩智浦 LPC1700辅助USB引导加载程序(AN10866)应用笔记所描述的USB引导加载程序.
这两个文档(应用笔记和电路板文档)都表明要构建用户程序,使其起始地址为0x2000.因为USB引导加载程序已经是0x0并占用8K.
这两个文档还显示了如何在Keil uVision中执行此操作的屏幕截图(请参阅应用说明的第14页),但我计划使用GNU工具链(Yagarto + Eclipse + OpenOCD).
在使用GNU工具链进行编译时,如何指定起始地址0x2000,以便它能够与USB引导程序一起正常工作?
我想创建一个调试工具来帮助我更好地调试我的应用程序。我正在工作(没有操作系统)。在 Atmel 的 SAM3 上使用 IAR 嵌入式工作台。
我有一个看门狗定时器,它会在超时的情况下调用特定的 IRQ(这将在发布时被软件重置替换)。在 IRQ 处理程序中,我想打印出(UART)堆栈跟踪,看门狗超时发生的确切位置。
我查看了网络,并没有找到该功能的任何实现。
任何人都知道如何处理这种事情?
编辑:好的,我设法从堆栈中获取返回地址,所以我确切地知道 WDT 超时发生的位置。展开整个堆栈并不像最初出现的那样简单,因为每个函数将不同数量的局部变量压入堆栈。
我最终得到的代码是这样的(对于其他人,可能会发现它有用)
void WDT_IrqHandler( void )
{
uint32_t * WDT_Address;
Wdt *pWdt = WDT ;
volatile uint32_t dummy ;
WDT_Address = (uint32_t *) __get_MSP() + 16 ;
LogFatal ("Watchdog Timer timeout,The Return Address is %#X", *WDT_Address);
/* Clear status bit to acknowledge interrupt */
dummy = pWdt->WDT_SR ;
}
Run Code Online (Sandbox Code Playgroud) 我正在尝试理解初始化代码如何与Keil(realview v4)一起用于STM32微控制器.具体来说,我试图了解堆栈是如何初始化的.
在ARM网站上的文档中,它提到startup_xxx.s中的一个例程,__user_initial_stack_heap不应该使用超过88个字节的堆栈.你知道这个限制来自哪里吗?
似乎当重置处理程序调用System_Init时,它正在C环境中执行一些函数,我相信这意味着它正在使用某种形式的临时堆栈(它分配了一些自动变量).但是,所有这些堆栈项目一旦返回就应该超出范围,然后调用从__main哪里__user_initial_stack_heap调用.
那么为什么__user_initial_stack_heap不要使用超过88个字节的这个要求呢?剩下的__main使用了大量的堆栈还是什么?
任何与启动序列相关的cortex-m3堆栈架构的解释都会很棒.
单击板上或 Kiel 上的重置按钮后,有没有办法保留一些 ram 值或全局变量
我正在使用 STM32L152ZE
在发生异常时,我已经停留了一段时间来设置回调.
我有这个测试代码:
void main()
{
long * bad = (long*)0x0A000000; //Invalid address
//When the following line gets executed
//it causes an error and the debugger sends me to an assembly file.
*bad = 123456789;
}
Run Code Online (Sandbox Code Playgroud)
我发送的程序集文件看起来像这样(真实文件的片段):
.macro DEFAULT_ISR_HANDLER name=
.thumb_func
.weak \name
\name:
1: b 1b /* endless loop */
.endm
DEFAULT_ISR_HANDLER SRC_IRQHandler /*Debugger stops on this line*/
Run Code Online (Sandbox Code Playgroud)
据我所知,DEFAULT_ISR_HANDLER是一个定义无限循环的宏.我想要做的是在C文件中定义我自己的函数,我可以在发生异常时调用,而不是调用DEFAULT_ISR_HANDLER宏中定义的whats.
我的问题是,如何在该程序集中定义一个调用特定C函数的宏?
希望我解释自己.欢迎任何有关此主题的信息或指示.
如果它是相关的我使用GCC ARM编译器v5.4_2016q3
谢谢,艾萨克
编辑
我正在使用Cortex-M3.
直到现在我才意识到我在谈论处理器异常.根据数据表,有一个包含16种异常类型的列表.
显然,它的工作方式是将所有异常类型重定向到宏,后者又调用一些拇指函数,然后调用无限循环(根据代码中的DEFAULT_ISR_HANDLER).
我想要做的是在C文件中定义我自己的函数,为方便起见,所以每次出现任何类型的处理器异常时,我都可以控制如何继续.