飞凌开发板:S3C6410 之裸机程序烧写

发布时间:2024-09-06  

学习ARM时,看到三星ARM11 的官方手册上写道:S3C6410具备一个内部SRAM的缓冲器,叫做“STEPPINGSTONE”,支持NAND FLASH的系统引导。当系统启动时,NAND FLASH存储器的前4KB将自动被载入到“SETPPINGSTONE”中,然后系统自动执行这些载入的引导代码。(默认的话该存储区应该被映射到地址空间0处)。


于是一直就想写个裸机程序,长度不超过4KB,存放在NAND FLASH的最开始,这样每次系统上电从NAND FLASH启动时,都会把这段代码拷贝到被映射到地址0x0 处的“STEPPINGSTONE”处。这个应该是bootloader 的雏形吧,一上电就执行的程序。可是在裸机环境下一直找不到烧写NAND FLASH的方法。买了个JLink,貌似在Windows 下据说不能烧写NAND FLASH,尚未验证。网上大部分方法都是针对Uboot 烧写内存,通过USB或者串口,网络。没有看到写道NAND FLASH的方法。没办法,只能凑活着写道内存中,先看看自己的程序是不是写对了。突然有一天,翻翻韦东山老师的书:《嵌入式Linux应用开发完全手册》上一张,降到Uboot中怎么从内存烧写东西到NAND FLASH中去。突然灵机一动,可以将程序先烧到内存中,在从内存中烧到NAND FLASH中去。最后,NAND FLASH中的Bootloader (Uboot)会被覆盖掉,上电就会自动运行自己的裸机程序,而非Bootloader。


想法有了,就去实现下:为此写了个小程序,来验证下。改程序的思路是:四个按键对应四个LED,按键按下,LED亮;松开LED灭。


三个程序如下:


 1 #define KEYCON  (*(volatile unsigned long *)0x7F008830)

 2 #define KEYDAT  (*(volatile unsigned long *)0x7F008834)

 3 

 4 /* 设置Key0 - Key4 为输入状态*/

 5 void KeyConfigure()

 6 {

 7         KEYCON = 0x0;

 8 }

 9 

10 /*只是最简单的查询按键状态,没有消抖功能,毕竟只是验证用*/

11 int KeyStatus()

12 {

13         return KEYDAT;

14 }


extern int KeyStatus();

extern void KeyConfigure();


#define LEDCON  (*(unsigned long int *)0x7F008820)

#define LEDDAT  (*(unsigned long int *)0x7F008824)


int main(void)

{

        LEDCON = 0x1111; //GPM低四位全部输出

        KeyConfigure();


        while (1)

        {

                LEDDAT = KeyStatus() & 0xf; //

        }

}


 1 .global _start

 2 

 3 _start:

 4 

 5         /*设置协处理器*/

 6         ldr r0, =0x70000000

 7         orr r0, r0, #0x13

 8         mcr p15, 0, r0, c15, c2, 4

 9 

10         /* 关闭看门狗定时器 */

11         ldr             r0, =0x7E004000

12         ldr             r1, =0x0

13         str             r1, [r0]

14 

15         ldr             sp, = 8*1024

16         bl main

17 

18 halt:

19         b halt


 1 CC = arm-linux-gcc

 2 LD = arm-linux-ld

 3 OBJDUMP = arm-linux-objdump

 4 OBJCOPY = arm-linux-objcopy

 5 

 6 OBJ     = start.o key.o led.o

 7 

 8 led.bin : led.elf

 9         $(OBJCOPY) -O binary led.elf led.bin

10         $(OBJDUMP) -d led.elf > led.dis

11         cp led.bin ~/nfs_root/ 

12 ##### cp 命令的意思是我把 NFS 文件系统放在了家目录下的nfs_root 里面

13 

14 led.elf : $(OBJ)

15         $(LD) -o led.elf -Ttext 0x0 $(OBJ)

16 

17 led.o : led.c

18         $(CC) -fno-stack-protector -c -o $@ $<

19 

20 key.o : key.c

21         $(CC) -fno-stack-protector -c -o $@ $<

22 

23 start.o : start.s

24         $(CC) -fno-stack-protector -c -o $@ $<

25 

26 

27 clean :

28         rm $(OBJ) led.elf led.bin led.dis


根据上述四个文件,make 即可生成索要烧写的纯二进制文件 led.bin


啰嗦下,之所以使用NFS文件系统通过Uboot和网络烧写二进制文件到内存,而非通过传统的USB烧写,是应为我xxx在64bit的win7 中装不上DNW的USB驱动,穿不了文件。不要问我为什么不用兼容性更好的XP。我是4G的内存,XP只能3G左右的内存,32bit的Win7估计也就3.5G的内存,老子总不能让浪费4G的内存不用吧?再说了,微软不是要放弃XP吗?懒得折腾换到XP了,所以只好用网络烧写了(PS:懒得吐槽windows了)。


至于怎么在Linux主机上开启NFS系统,详见上述韦东山老师的书。(PS:大家不要被我的开发环境给搞晕了,一会Win7一会儿linux的。我主要是在ubuntu上用ARM-linux* 那一套开发的,用的Ubuntu开发环境是在Win7上 用ssh  远程登录操控的,这样一个Ubuntu 主机可以多用户操作,是在是很方便。只是用了下Win7的串口跟开发板相连,应为Ubuntu主机离我很远。所以只能通过交换机 + Ubuntu 主机 + Win7 主机 + 开发板架构了。之所以不用虚拟机,感觉速度太慢,受不了。)


闲话少说:开发板烧写过Uboot 后,上电停留在Uboot状态,退出到命令行输入方式,设置Uboot的网络参数,来和Ubuntu主机通过NFS文件系统烧写程序。


 1 printenv : 

 2    bootdelay=1

 3    baudrate=115200

 4    ethaddr=00:40:5c:26:0a:5b

 5    ipaddr=192.168.2.111

 6   serverip=192.168.2.100

 7   gatewayip=192.168.2.1

 8   netmask=255.255.255.0

 9   stdin=serial

10   stdout=serial

11   stderr=serial

12 

13 上述打印的网络参数中,只有 ipaddr , serverip, gatewayip, netmask 需要设置。我的Ubuntu 主机IP地址为 10.11.52.249, 子网掩码为 255。255.0.0,网关为10.11.52.1

14 所以可以设置开发板的IP地址为 10.11.52.248, 子网掩码和网关筒主机即可。

15 用 setenv name value 命令即可

16 setenv ipaddr 10.11.52.248

17 setenv serverip 10.11.52.249

18 setenv gateway 10.11.52.1

19 setenv netmask 255.255.0.0

20 然后保存:saveenv 即可


然后即可将上面生成的led.bin 烧写到内存中去。


nfs 0x50000000 10.11.52.249:/home/cat/nfs_root/led.bin

@用法解析

nfs 内存地址 nfs网络文件地址

烧写完后,即可通过uboot 的nand 命令将0x50000000的内存内容烧写到Nand FLASH中去


 1 @ 擦除NANDFLASH

 2 nand erase   0x0      0x200000

 3 命令   擦除   nand偏移   擦除长度

 4 

 5 @ 写NANDFLASH 

 6 nand write     0x50000000 0x0            0x20000000

 7 命令   写          内存地址     nand 偏移       写长度

 8 

 9 @ 读NANDFLASH 到终端,可以跟反汇编文件对比是否正确

10 nand   dump        0x0

11 命令       读       从该offset的一个扇区的内容   


然后上电,设置开发板从Nand FLASH启动,即可看到上电不会执行Uboot(被裸机程序覆盖掉了),而是直接执行裸机程序了。


注:


 1 (1)start.s 中设置协处理器的原因是ARM11的采用的架构是arm1136jzf-s把memory和Peripheral接口分开了,你需要在初始化时告诉cpu,

    哪些地址范围是属于Peripheral的,否则它就当memory访问,当然就访问不到属于Peripheral 区间的IO口寄存器。

    可以通过ARM11的协处理器cp15来告诉CPU外设寄存器的地址,在ARM11芯片架构手册上可以看到怎样实现该操作:

 2 

 3   CRn Op1 CRm Op2

 4 

 5    c15    0    c2     0 Data Memory Remap R/W 0x01C97CC8 page 3-162

 6                         1 Instruction Memory Remap R/W 0x01C97CC8 page 3-162

 7                         2 DMA Memory Remap R/W 0x01C97CC8 page 3-162

 8                         4 Peripheral Port Memory Remap R/W 0x00000000 page 3-162

 9 

10       如果不设置的话,在Uboot下烧写到内存中运行没问题,因为Uboot已经替你设置好了,但是烧写到NAND FLASH中去的话会出现问题,因为没有Uboot替你设置这些东西。

11 (2)  烧写NAND FLASH时一定要先擦除再烧写,因为nand由于结构的特殊性,只能先充电,再放电,不能直接对每一位置高置低。


因此规定,进行nand写入操作前,必须对nand进行擦除操作。擦除就是充电,对每一位置高,写入0xFF,而写入动作就是对特定位进行放电的操作了,这样才能得到正确的数据。


 


文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>