我正在为TM4C123GX发现板编写程序。我正在使用Keil uVision并使用模拟器进行调试。我正在尝试使用SysTick处理程序切换GPIODATA寄存器中的值以使外部LED闪烁。 TM4C使用地址掩码将位存储到GPIODATA,我使用变量(PB5_MASK)来保存掩码值。我的问题是
我的问题是:尽管给出了初始值(0xF0),为什么变量(PB5_MASK)初始化为0?为什么同一个变量(PB5_MASK)有两个地址(0x2000.0000& 0x2000.0004)?
my_Variables.s:
AREA My_Variables, CODE, READWRITE
PB5_MASK DCD 240;0x000000F0
END
main.s:
;Include constants I define to main
INCLUDE my_Constants.s
;Include variables I define to main
INCLUDE my_Variables.s
AREA |.text|, CODE, READONLY
;THUMB
EXPORT __main
ENTRY
;This subroutine initializes GPIO
GPIO_Init PROC
;Push LR onto stack first
PUSH {LR}
;write "high" to data register for port F pin 1 to turn on red LED. GPIODATA
LDR r0, =AHB_PORTB
LDR r1,[r0,#GPIODATAPB5]
;address for PB5_MASK here is 0x2000.0000, but...
LDR r2, =PB5_MASK ;get RAM address of PB5 mask (pointer)
;reads 0x0 unless I put in the value myself
LDR r3,[r2] ;get the value of PB5 mask
ORR r3, r3, #0xF0
STR r3,[r2]
ORR r1, r1, r3 ;Set PB5 to 'high'
STR r1,[r0,#GPIODATAPB5]
;LDR r1,[r0,#GPIODATAPB5]
;Pop LR and return to __main
POP {LR}
BX LR
ENDP
startup_rvmdk.s:
;includes constants I define to startup file
INCLUDE my_Constants.s
;Include variables I define to startup file
INCLUDE my_Variables.s
SysTick_Handler PROC
EXPORT SysTick_Handler
;write "high" to data register for port F pin 1 to turn on red LED. GPIODATA
LDR r0, =AHB_PORTB
;... address for PB5_MASK here is 0x2000.0004
LDR r1, =PB5_MASK ;Get RAM address of PB5 mask value
LDR r2,[r1] ;Grab value of PB5 mask
EOR r2, r2, #0xF0 ;Toggle mas to toggle PB5
STR r2,[r1] ;Store the toggled mask to properly toggle next time
STR r2,[r0,#GPIODATAPB5]
;LDR r2,[r0,#GPIODATAPB5]
;return to __main
BX LR
ENDP
这些是片段。如果需要整个代码,请告诉我。谢谢!
编辑:这是一个类似问题的链接。我还必须在调试时输入自己更改的地址,但是没有解决方案有两个地址的变量
ARM Assembly storing registers to memory
编辑:因此,使用IMPORT / EXPORT解决了2个地址对同一变量的问题,但我仍然坚持使用未初始化的变量问题。
我无法理解从哪里开始使用bootloader。我想要的是我的变量在RAM中初始化。我试着查看TivaWare附带的示例,我看到Reset_Handler调用__main,它调用其他子程序,如_main_after_scatter等。我找不到__main在哪里?我最初认为__main是我应该编写代码的地方(比如main())。 __main是一个只做它自己的子程序吗?如果是这样,我在哪里编写代码?抱歉有多个问题,但它们都是相关的。
答案 0 :(得分:1)
正如彼得·科德斯在评论中指出的那样,你将变量定义为两次。
默认情况下,装配模块中的对象是本地的。为了在两个或更多模块之间共享变量,您必须在一个编译单元中定义它,用GLOBAL
或EXPORT
标记符号(它们是相同的),然后使用{{1 }}或EXTERN
在其他模块中,以使它们在那里可见。
关于您的其他问题,变量应在程序启动时 初始化。
这个嵌入式系统没有加载器,程序直接写入板载闪存,并从那里执行。代码和常量数据都在flash中,变量在RAM中静态分配,但是没有任何内容可以填充RAM中变量的初始值,除非你的代码这样做。
工具链供应商提供了一个启动功能,它正是这样做,将初始值从flash复制到ram,零变量没有显式初始化,做一些内务处理,并将控制转移到用户的IMPORT
功能程序。这个启动函数在Keil工具链中被称为main
,如果你想要初始化变量,你应该从重置处理程序调用它。