hhpsr1990 发表于 2020-4-19 23:42:25

S3C2440A之ARM学习

问题1:关于Nor/Nand启动判断的问题:



视频讲解是用写0到,取出还是0则Nand启动,视频例程:
mov r1, 0
ldr r0,
str r1,
ldr r2,
cmp r1, r2
//如果r1 != r2, nor启动
ldr sp, =0x40000000 + 4096
//如果r1 == r2, nand启动
moveq sp, #4096
streq r0,
如果:拨码开关为Nor启动,Norflash地址中数据原本
即为0,Nor启动不能写入,但cmp r1, r2时,r1==r2依然
成立,系统是否会判断为Nand启动?有没有影响?怎么判断?


答:1>【传说】hceng(1307410945):不会为0的,因为你的代码烧在nor/nand 0地址上,既然有代码,就不会为0;   


hexdump xx.bin 你会看到 首个数据 不会是0的;


正因为 0地址的数据是有用的,所以才会先保存到r0,最后再从r0恢复: ldr r0,    ->   streq r0,


nand启动才会修改,nor不会。 也就是说 nor启动,下次还能启动,,先nand启动就废了


你试试 去掉streq r0, 理论上 下次就启动不了,,我没试,我是从理论上分析的。。。帮忙试下 告诉结果。。。==

2>会 可以改下代码先判断nor中第一个是否和写入的相同
3>这个跟判断 大小段端一个原理差异处 区分


问题2:裸板实验操作流程:Windows环境下编写start.S、*.c、Makefile文件,文件上传到Ubuntu环境(即主机)并编译连接生成*.bin文件,把.bin文件通过DOS系统的命令行工具烧写到开发板Norflash/Nandflash,把开发板启动开关调至相应的启动开关,关闭电源拔掉eop烧写器,重新上电,观察开发板现象。
程序烧写到什么位置啦(即程序的存储位置)?Norflash/Nandflash?
芯片有多种启动方式,而这些启动方式都可以由配置引脚来选择。芯片在启动时读取这些配置引脚的电平,就可以判断从那种方式启动。通常在研发阶段的实验板或者很多学习板(如:JZ2440)通常采用开关或跳线帽等方式来将配置引脚的电平置为高电平或置为低电平。在出厂时, 配置引脚一般通过上下拉电阻来设置电平。
从NOR FLASH启动:


    从NOR FLASH启动时,由前面的图1,由nGCS0控制的bank0直接连接了nor flash,而bank0能访问的地址范围为:256M(0X00000000----0X08000000),JZ2440开发板使用的nor flash大小为2M(0X00000000----0X00200000),从而S3C2440芯片的物理地址(0X00000000----0X00200000)就由nor flash来占据。


    选择从NOR FLASH启动,上电,S3C2440芯片就会去运行nor flash上地址为0x0处的指令。从后面的实验中,可以清楚的知道,读nor flash可以像读内存那样读,但是要用额外的命令向nor flash写入数据。如果nor flash像内存那样读和那样写,那nor flash完全可以被内存所替代。


(摘录自:博客园-韦东山https://www.cnblogs.com/weidongshan/p/6689728.html)
由此可知,(1)DOS环境下命令行工具烧写设置决定了.bin文件的烧写到开发板的存储位置(即Norflash、Nandflash),因此,不管是Nor/Nand启动,地址一定不为空(即地址内的数据一定不为0);
(2)S3C2440的启动方式则由OM0和OM1引脚(开发板具体通过拨码开关控制)来选择。因此,当程序烧写到Norflash而选择Nandflash启动开发板不会有现象,Nandflash同理。
(3)执行程序时,通过在程序中对已知启动方式的判断,来设置栈区地址(个人理解程序开头对启动方式进行判断的作用就是干这个的)。程序执行是从0x0地址开始:(假设Nand启动)Nandflash中已经存有代码,地址数据不为0,因此,通过【写0到,然后取出与0比较:如果r1 != r2, nor启动;如果r1 == r2, nand启动;假设r1 == r2】则表示程序存储在Nandflash(以地址0x0开始)且前4k映射到SRAM,栈区在SRAM顶部,地址为4096;    (假设Nor启动)Norflash中已经存有代码,地址的存储空间不可进行写操作且数据不为0。Nor启动,则程序直接在Norflash启动,栈区地址也在SRAM顶部,地址为(0x40000000+4096)。因此,杜绝了Nand/Nor启动时地址的空间未被赋值0时原本数据为0的可能性。
(此即问题1的答案)


问题3:Nor启动,SRAM除了存储寄存器sp之类,还有别的作用吗?


问题4:ARM中Makefile的规则、语法、函数及实例


1.Makefile的说明:


1)功能【gcc -Werror -Iinclude-c-oc.oc.c-MD-MF   .c.o.d】来自gcc,和Makefile本身无关


2)当工程中文件(包括 .c/ .h/ .s ...)路径发生变化后,需要【make distclean】一次,再重新make(为什么?)


3)当工程文件(包括 .c/ .h/ .s ...)只执行了内容修改,直接make即可重新编译生成.o文件,原来的依赖可直接用(?)


2. arm-led工程:include/s3c2440_soc.h、led.c、Makefile、start.S四个文件


实现功能:单灯流水、双灯流水、三灯流水,循环


实验结果:完全实现预定功能,可参考成功arm-Makefile例程如下:






问题5:变量/函数的声明、定义、初始化的作用和区别?


(1)变量:声明是告诉编译器有这么个变量,但并不实现。定义就是实现这个变量,真正在内存(堆或栈中)为此变量分配空间


声明简单的说就是 定义变量类型但不为其分配空间。




定义就是指定变量类型,然后分配空间并为其初始化。
(2)函数:声明嘛表示有这么个函数了,定义就是具体实现了,举个例子:
函数声明:
int fun(int a, int b);    //a,b为形参


函数定义:
int fun(int a,int b)
{ int c;
c=a+b;


return c; }


函数调用(即函数初始化):


fun(3, 5);      //3, 5为实参






声明就象是定义的头部,比较简略,函数是用来调用的,如果函数定义部写到调用的位置后面,执行到调用位置,后面根本没执行就找不到了,当然报错了,就要在前面加声明,表示有这个函数,反之先写函数体,后调用声明就用不了,不在同一源文件,道理也是如此




//声明在函数外,声明后面的函数(无论main还是其他函数)都可以调用                //声明在函数内部,只能在本函数内,声明后面的区域可以调用   
问题6:UART特殊功能模块的寄存器操作机理和使用疑难的问题
    6.1 配置UART的几个寄存器:
UBRDIVn寄存器:设置波特率,S3C2440 UART的时钟源有两种选择:PCLK、UEXTCLK、FCLK/n,其中n的值通过UCON0-UCON2联合设置


ULCONn寄存器:设置传输格式


UCONn寄存器:它用于选择UART时钟源、设置UART中断方式


UFCONn寄存器、UFSTATn寄存器,UFCONn寄存器:用于设置是否使用FIFO,设置各FIFO的触发阙值,即发送FIFO中有多少个数据时产生中断、接收


      FIFO中有多少个数据时产生中断。并可以通过设置UFCONn寄存器来复位各个FIFO。读取UFSTATn寄存器可以知道各个FIFO是否已经满,其中有多少个数据。


UMCONn寄存器、UMSTATn寄存器:这两类寄存器用于流量控制,具体看数据手册UTRSTATn寄存器:它用来表明数据是否已经发送完毕、是否已经接收到数据


UERSTATn寄存器:用来表示各种错误是否发生


UTXHn寄存器:CPU将数据写入这个寄存器,UART即会将它保存到缓冲区中,并自动发送出去


URXHn寄存器:当UART接收到数据时,CPU读取这个寄存器,即可获得数据。


    6.2
问一个关于串口的问题:
int puts(const char *s)
{
while(*s)
{
putchar(*s);
s++;
}
}
当字符串结束,*s=0,跳出while()循环
问:为什么字符串结束后, *s一定等于0?
答:对于字符串,程序是当做字符数组处理的,在数组的结尾,程序会自动加一位元素''作为结束标志,因此,*s = ‘’,即为空,为假,跳出循环
    6.3 UART0作调试打印功能时,输入之后再PC机串口工具回显输出乱码的问题


答:可能的原因有种,


    01:波特率设置不对,导致此的可能原因有:


          a)UBRDIV0设置或计算错误;


            b)UCON0位时钟选择错误:


            UCON0位,选择 PCLK,UEXTCLK 或 FCLK/n 给 UART 波特率。


            UBRDIVn = (int)(被选时钟 / (波特率 × 16) ) – 1;            00 = PCLK10 = PCLK01 = UEXTCLK11 = FCLK/n


            (如果希望选择 FCLK/n,应该在选择或取消选择 FCLK/n 后加上“NOTE”的代码。)


void uart0_init(void)
{
//设置UART0输出输入引脚
GPHCON &= ~((3<<4)|(3<<6));
GPHCON |= ((2<<4)|(2<<6));
//GPHUP &= ~((1<<2)|(1<<3));    //该句屏蔽不影响串口的操作,为什么要写?操作GPF4,5,6时问什么不需要设置?
//设置波特率
UCON0 = 0x00000005;    //若UCON0 = 0x00000003,则PC机串口工具无输出显示
UBRDIV0 = 26;
//设置数据格式
ULCON0 = 0x00000003;    //8n1

}


      c)时钟分频寄存器CLKDIVN = 0b101 = 5,设置错误


/*设置时钟分频寄存器CLKDIVN = 0b101 = 5*/
ldr r0, = 0x4c000014
mov r1, #5      //若#5改为 #3 ,则PC机串口工具输出乱码
str r1,
/*如果 HDIVN 不为 0,CPU 总线模式应该使用以下指令使其从快总线模式改变为异步总线模式(S3C2440
*不支持同步总线模式)
*/
MRCp15, 0,r0,c1,c0,0
ORRr0,r0,#0xc0000000

小鑫鑫 发表于 2020-4-20 00:03:03

qysxhb 发表于 2020-4-20 07:30:41

kingboy100 发表于 2020-4-20 07:43:11

dfgdfg

kingboy100 发表于 2020-4-20 07:44:09

wangy2000 发表于 2020-4-20 08:57:18

谢谢分享

h09721 发表于 2020-6-8 08:47:49

tiny2010 发表于 2020-12-7 08:56:39

tiny2010 发表于 2021-7-14 08:43:57

tiny2010 发表于 2021-7-15 08:53:50

页: [1] 2 3
查看完整版本: S3C2440A之ARM学习