AT91SAM7S

news/2024/11/9 10:04:41/

将程序执行到C文件的main函数

一.背景

当有了techorICE仿真器与AT91SAM7S64实验板后,像拿到一个不熟悉的普通单片机一样,希望能够写个小程序在里面跑跑,来开始第一步!在做这个实验前,我快速的阅读了AT91SAM7S64数据手册和《ARM体系结构与编程》(我认为这本书非常不错),还有techorICE仿真器的使用手册,并着重阅读了ADS软件、仿真器的使用以及起动代码方面的知识,因为这些都是马上要用到的。

二.实验目的

运用ADS编写一个小程序,使程序能够从起始的汇编代码运行到C程序的main()函数(这也可称作非常简单的起动代码),并通过仿真器连接目标板,最终能够在AT91SAM7S64里正确运行。

三.实验程序和参数设置

1>连接器的选项设置

选项设置如图2-1所示。因为在AT91SAM7S64FLASH存储器的地址是以0x0开始,而SRAM的地址是以0x00200000开始,所以我将下图中的RO BaseRW Base分别设置成了0x00x00200000。其它设置请参考有关书籍。

 

 

2-1. 选项设置图

2>启动代码

ARM应用系统中,芯片复位后,在进入C语言的main()函数前,都要执行一段启动代码。该代码一般都是用汇编语言编写,用来完成系统运行环境和应用程序的初始化,详情请参考有关书籍。由于本实验的目的很简单,就是想让程序复位后,进入main()函数,所以有些初始化代码尽量精简,留下了下述代码。另外,__mainC语言的内部库函数,可以在进入用户main()之前完成内部RAM的初始化工作,类似KeilC51中的startup.a51。当执行完__main这段代码后,再跳转到main()函数。

AREA init,CODE,READONLY

 CODE32

Mode_USR  EQU  0x10 ;CPSR中各种处理器模式对应的控制位

I_Bit   EQU  0x80 ;CPSR中的中断禁止位

F_Bit   EQU  0x40

USR_Stack  EQU  0x00203000 ;定义RAM的最高地址,无重映射

ENTRY

                B           InitReset        ; 0x00 Reset handler

undefvec         B           undefvec        ; 0x04 Undefined Instruction

swivec           B           swivec          ; 0x08 Software Interrupt

pabtvec          B           pabtvec          ; 0x0C Prefetch Abort

dabtvec          B           dabtvec          ; 0x10 Data Abort

rsvdvec          B           rsvdvec          ; 0x14 reserved

irqvec           B   irqvec   ; 0x18 IRQ

fiqvec      B   fiqvec        ; 0x1c FIQ

InitReset

 MSR CPSR_c,#Mode_USR | I_Bit | F_Bit ;改成用户模式且禁止IRQFIQ中断

 LDR SP,=USR_Stack

 IMPORT  __main                  

 b         __main  ;跳转到__main执行,它位于C运行时库中                               

 END

3>C语言主函数

C语言主函数中做了一个死循环,如下述所示。

int main(void)

{

  while (1);

}

四.出现的问题与解决方法

当完成上述操作后,先用软件仿真,很快达到了目的,但将程序通过仿真器在目标板运行时出现了下述问题。

1> 当执行单步运行时,PC一直停留在0x0处,而且Debug Log窗口中显示RDI Warning 00148: Can't set point

原因是仿真器在ROM中设置的断点数是有限的,且单步运行时内部还要占用断点。可以使用Option->Config Processor打开Processor Properties-ARM7TDMI窗口,且按照下图设置以关断相应的断点。

 

 

2> 装载的代码与实践程序不一样

原因是由于程序没有装载到AT91SAM7S64FLASH ROM里,在调试器中显示的是FLASH ROM中原先就有的程序。因为在连接器的选项设置中,将RO BaseImage entry point指向了0地址,而在AT91SAM7S64的这段空间为FLASH ROM区,而仿真器不能直接将代码下载到FLASH ROM里。用仿真器只能将代码下载到AT91SAM7S64的内部SRAM里进行调试,必须将ARM Linker->Output->Simple image->RO BaseImage entry point0,改成SRAM的地址0x002000000

3>在软件仿真的情况下,执行B __main指令,能使程序跳到C文件的main函数,但用硬件仿真时,还没执行到main函数时就进入了异常中断。

原因是执行B __main指令后,程序先跳到__main库函数的入口,再进行一些初始化操作,最后再跳入用户的main函数。但在初始化过程中,由于堆栈或其它原因造成程序出错。有两种方法可以解决这个问题。第一:将B __main指令直接改成B main,使程序不进行初始化而直接跳入用户的main()函数。第二:合理初始化堆栈。由于考虑到刚接触ARM和将问题简单化,我选择了第一种方法。

1> 无论作输入用的I/O口电平如何变化,管脚状态寄存器(AT91C_PIOA_PDSR)的内容始终为0,即I/O口的输入功能没起作用。

原因是AT91SAM7Sxx内部集成了功率管理控制器,用它来控制所有外设的时钟以达到优化功耗的目的。所以只有使能了PIO的外围时钟,PIO外设才会工作,才能读入输入管脚的状态。那么为什么PIO作为输出时不需要使能外围时钟呢?我个人认为这与内部外设在数字电路上的实现有关,输出功能只需要组合逻辑电路(不用时钟)就能实现,而输入功能则需要用到时序逻辑电路(需要时钟)才能实现。

因此,必须在main()函数的开头增加如下两条时钟使能的语句:

*AT91C_PMC_SCER = AT91C_CKGR_MOSCEN;//使能系统时钟寄存器的处理器时钟

*AT91C_PMC_PCER = 1 << AT91C_ID_PIOA; //使能PIOA外围时钟

 

 

I2C: 无论写入任何数据,读出来都是同样的数,表明数据没有写入(在调试时对其写操作,器件没有产生应答)。
原因是24C02的写保护管脚没有接地,内部的数据被写保护了。注意:有些厂家的EEROM的该管脚处于悬空时为不保护状态,而有些厂家的EEROM会处于保护状态,因此在用之前一定要仔细阅读厂家的数据手册,或不要将该脚悬空。

2> 对24WC02写的数据和读的数据不一样。
原因是I2C的时钟太快。在本实验程序中,可以减少twi.h中的AT91C_TWI_CLOCK常量的数值。或者直接在程序中修改TWI时钟波形发生寄存器TWI_CWGR。
3> 当写入16字节数据,再读出16字节数据时,最后一个字节总为0。
原因是TWI Master Mode Register的IADRSZ(器件内部地址长度)设成了两个字节(Two-byte),要将改成一个字节(One-byte)。

2> 对24WC02写的数据和读的数据不一样。
原因是I2C的时钟太快。在本实验程序中,可以减少twi.h中的AT91C_TWI_CLOCK常量的数值。或者直接在程序中修改TWI时钟波形发生寄存器TWI_CWGR。
3> 当写入16字节数据,再读出16字节数据时,最后一个字节总为0。
原因是TWI Master Mode Register的IADRSZ(器件内部地址长度)设成了两个字节(Two-byte),要将改成一个字节(One-byte)。

五.总结

1> 在用仿真器时,必须将程序下载到AT91SAM7S64的内部SRAM中,而不是Flash ROM

2> 从汇编代码进入C文件函数时,可以直接使用C语言中的标号(可参考书中混合编程部分),如执行B main则直接跳到C语言的main()函数入口。

3> 在起动代码中,可以调用__main()库函数进行存储器的初始化,也可以自己编写更有效的代码进行初始化,在初始化后就可以使用B __main指令直接跳转到Cmain()函数。

三.出现的问题与解决方法

1> 状态寄存器中的发送准备位(TXRDY)和发送空标志位(TXEMPTY)一直为0,表示发送器未准备好和缓冲区不空。

原因是发送器复位后还未使能。不能同时进行发送器(或接收器)复位与使能操作(*AT91C_US0_CR= 0x15c),这样使能操作会无效,必须将它们分开,即先进行复位(*AT91C_US0_CR= 0x10c),再进行使能(*AT91C_US0_CR = 0x50)。

2> 串口接收、发送的数据不对

原因是系统主时钟和分频后的时钟计算错误,引起波特率也计算错误。很有必要深入研究关于时钟的产生、分频及波特率计算等内容。

3> 每次从串口调试软件收到的数据中,低四位正确,高四位错误。

原因是将*AT91C_US0_MR =0x8c0;写成了*AT91C_US1_MR =0x8c0;,而引起通讯模式根本不对。可以说这是一个非常低级的错误,但它却花费了我很久的时间才找到症结所在。在找原因的过程中,使我对串口相关的(如各种时钟的产生、波特率的计算等)内容有了更深刻的理解。

1> CPU进不了中断,即跳不到IRQ中断向量入口地址。
原因是打开了Memory窗口,观察中断相关的寄存器。AXD软件为了在Memory窗口中刷新这些寄存器值,在程序运行过程中会访问CPU中相应寄存器值。当中断源触发后,在跳到IRQ的中断入口之前,IRQ的中断向量寄存器AIC_IVR就因为上述原因被读过,这时CPU就认为已经完成对IRQ中断的处理,因此
就不再跳转到IRQ中断入口。

2> 刚一执行“MSR CPSR_c,#Mode_USR”语句使能IRQ中断,CPU就立即产生IRQ中断。
原因当上一次产生IRQ中断后,没有读PIO的中断状态寄存器,将其清零。因为中断状态寄存器置1时表示自从上一次读取此寄存器,至少检测到了一次电平变化。所以当没有读该寄存器时,该状态位会一直保持着。又因为在重新装载程序进行调试时,没有复位目标CPU,所以当使能IRQ中断后,由于PIO中断状态寄存器为1的原因而产生中断。

出现的问题与解决方法
1> 在调试过程中,(特别是全速运行)有时会进入Undefined Instruction及Data Abort等异常。
原因是由地址重映射命令引起。有时在重新装载程序而没有复位目标CPU时(此时目标CPU仍处于重映射状态),再次执行了重映射命令。

 

1> ADS软件编译后不能产生二进制等目标文件
第一、 可以用DOS命令手工生成二进制文件。
第二、 在“DebugRel Settings”中,将“Target->Target Settingsr->Post-linker”项的“None”修改成“ARM fromELF”,再在“DebugRel Settings”中的“Linker->ARM fromELF->Output format”中设置成Plain binary。

四.总结

 在本实验中串口为异步模式,波特率的计算如下式所示:

Baudrate = SelectedClock/(8(2-Over)CD)

其中在USART模式寄存器(AT91C_US0_MR)中设置SelectedClockMCKOver1则上式变成如下所示:

Baudrate = SelectedClock/(8(2-Over)CD) = MCK/16CD

Master Clock RegisterAT91C_PMC_MCKR)中将MCK设置为Main Clock且不分频,即为外部振荡时钟(接在XINXOUT管脚间的晶振)的频率,因为外部晶振是18.432MHz,所以MCK就为18432000,则上式变成如下所示:

Baudrate=SelectedClock/(8(2-Over)CD) = MCK/16CD = 18432000/(16*30) = 38400

 

 五.总结
1> 当执行地址重映射命令,使进入重映射后,如果再次执行该命令会使它恢复重映射前的状态。


http://www.ppmy.cn/news/468813.html

相关文章

关于BASE编码 16 32 36 58 64 58 91

base编码有很多种&#xff0c;常用的有&#xff1a; base16 base32 base64 base85 base36 base 58 base91 还有base 92 前面几种 16、32&#xff0c;64、85 可以用 base64来调用 不过得先pip install base64 然后 import base64 调用时&#xff0c;有统一的格式…

Day11:麦卡锡91函数(McCarthy 91)

Day11&#xff1a;麦卡锡91函数&#xff08;McCarthy 91&#xff09; 一. 问题背景&#xff1a; McCarthy 91 是一个递归的函数表达式如下&#xff1a; 函数的意思是当输入一个大于 100 的数字 n 时返回 n-10&#xff0c;当 n<10 的时候递归的对 n 进行运算&#xff0c;但…

计算机网络管理-网络管理软件SNMPc软件的下载,安装和使用教程说明

⬜⬜⬜ &#x1f430;&#x1f7e7;&#x1f7e8;&#x1f7e9;&#x1f7e6;&#x1f7ea;(*^▽^*)欢迎光临 &#x1f7e7;&#x1f7e8;&#x1f7e9;&#x1f7e6;&#x1f7ea;&#x1f430;⬜⬜⬜ ✏️write in front✏️ &#x1f4dd;个人主页&#xff1a;陈丹宇jmu &am…

数学基础-标量,向量,张量

前言 数学中&#xff0c;如何描述事务&#xff0c;以棍子为例子&#xff1a; 棍子的长度棍子方向棍子转向… 标量 单纯的形容事务的一个特征&#xff0c;如果体积&#xff0c;长度。 向量 指具有大小&#xff08;magnitude&#xff09;和方向的量。它可以形象化地表示为带…

推荐一些简单却很实用的工具,快收藏起来吧

第一个工具&#xff1a;remove.bg 这是一个在线抠图的神器&#xff0c;它能够帮助你轻松地消除图片中的背景。相信很多人都知道&#xff0c;手动抠图真的很累&#xff0c;抠着抠着就会觉得烦躁。但是&#xff0c;使用这个神器&#xff0c;你只需要点击上传图片&#xff0c;就能…

Python一些可能用的到的函数系列51 将markdown转为html

说明 将markdown直接转为pdf稍微有点麻烦&#xff0c;我们先看怎么转成html 内容 import markdown extensions [markdown.extensions.admonition, markdown.extensions.extra,markdown.extensions.tables] mkd markdown.Markdown(extensionsextensions)# 将markdown文本转…

ntr模式_ntr什么意思?

NTR全称New Type destroyeR system&#xff0c;即新人类毁灭系统&#xff0c;为《高达UC》中「UC」计划核心的RX-0系列机体所搭载的特殊OS系统。该系统可以对敌性精神感应MS所散发出的感应波进行探知&#xff0c;从而激发机体的形态变化&#xff0c;进入「毁灭模式」&#xff0…

ntr模式_妻3砂夜子NTR模式纯爱路线

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 看了下贴吧里面的图片流程&#xff0c;然后到夜祭海夕里才3级&#xff0c;所以发个自己打的流程出来&#xff0c;我测试了一下是没问题的。具体自己可以试试。对于前面只有单选的那些就不说了&#xff0c;NTR剧情会有发生但都无关…