嵌入式驱动开发笔记(裸机程序篇)---准备工作

来源:互联网 发布:fp6601q数据手册 编辑:程序博客网 时间:2024/06/01 09:35

开发平台(Fedora14,VMware8,Win7,Source Insight)

学习前提 (ARM 汇编,C,makefile)

交叉编译器 arm-linux-gcc-4.5.1

运行平台(TINY210:Cortex-A8)


准备工作:

1.在VMware8下安装Fedora14     (so easy la)

2.安装交叉编译器 arm-linux-gcc

2.1 mkdir /tmp

2.2tar xvzf arm-linux-gcc-4.5.1.tgz   –C /tmp

2.3vim /root/.bashrc

编辑/root/.bashrc 文件,注意“bashrc ”前面有一个“. ”,修改最后一行为

export PATH=$PATH:/tmp/opt/FriendlyARM/toolschain/4.5.1/bin/,注意路径一定要写对,否则将不会有效。 

2.4 arm-linux-gcc -v 


让我们开始吧:


既然是裸机程序,那就和单片机程序差不多了,无非就是设置设置寄存器的事。

TINY210启动流程,是先运行内部的IROM中固话的代码(类似与BIOS)进行一些必要的初始化,执行完后硬件会自动读取SD卡或NANDFLSAH中的前16K代码到IRAM中。这前16K代码中的前16字节保存了一个叫校验和的值。在进行数据拷贝的时候,他会检测待运行的des.bin文件(我们的单片机程序)中1的个数是否和这个校验和相等,若相等则继续运行程序,否则停止运行。所以我们要在我们的单片机程序前加上一个16字节的头部,形成一个16K的Buffer。

所以,我们的单片机程序编写流程应该如下:

1.分配16K的Buffer

2.将src.bin文件写入到Buffer的第16字节起的地方

3.计算出校验和(src.bin文件中1的个数)

4.将校验和写入到Buffer前16字节的8到11字节中

5.将16K的Buffer拷贝到最终程序中des.bin



我们将编写一个C程序来实现上面的功能,来引导开发板上点后执行我们的bin程序,我暂且命名为mkv210_image.c,我们以后都要一直用到这个程序。

/* 在BL0阶段,Irom内固化的代码读取nandflash或SD卡前16K的内容, * 并比对前16字节中的校验和是否正确,正确则继续,错误则停止。 */#include <stdio.h>#include <string.h>#include <stdlib.h>#define BUFSIZE                 (16*1024)#define IMG_SIZE                (16*1024)#define SPL_HEADER_SIZE         16#define SPL_HEADER              "S5PC110 HEADER  "int main (int argc, char *argv[]){FILE*fp;char*Buf, *a;intBufLen;intnbytes, fileLen;unsigned intchecksum, count;inti;// 1. 检测输入参数个数是否正确if (argc != 3){printf("Usage: mkbl1 <source file> <destination file>\n");return -1;}// 2. 分配16K的bufferBufLen = BUFSIZE;Buf = (char *)malloc(BufLen);if (!Buf){printf("Alloc buffer failed!\n");return -1;}memset(Buf, 0x00, BufLen);// 3. 读源bin到buffer// 3.1 打开源binfp = fopen(argv[1], "rb");if( fp == NULL){printf("source file open error\n");free(Buf);return -1;}// 3.2 获取源bin长度fseek(fp, 0L, SEEK_END);fileLen = ftell(fp);fseek(fp, 0L, SEEK_SET);// 3.3 源bin长度不得超过16K-16bytecount = (fileLen < (IMG_SIZE - SPL_HEADER_SIZE))? fileLen : (IMG_SIZE - SPL_HEADER_SIZE);// 3.4 buffer[0~15]存放"S5PC110 HEADER  "memcpy(&Buf[0], SPL_HEADER, SPL_HEADER_SIZE);// 3.5 读源bin到buffer[16]nbytes = fread(Buf + SPL_HEADER_SIZE, 1, count, fp);if ( nbytes != count ){printf("source file read error\n");free(Buf);fclose(fp);return -1;}fclose(fp);// 4. 计算校验和 // 4.1 从第16byte开始统计buffer中共有几个1a = Buf + SPL_HEADER_SIZE;for(i = 0, checksum = 0; i < IMG_SIZE - SPL_HEADER_SIZE; i++)checksum += (0x000000FF) & *a++;// 4.2 将校验和保存在buffer[8~15]a = Buf + 8;*( (unsigned int *)a ) = checksum;// 5. 拷贝buffer中的内容到目的bin// 5.1 打开目的binfp = fopen(argv[2], "wb");if (fp == NULL){printf("destination file open error\n");free(Buf);return -1;}// 5.2 将16k的buffer拷贝到目的bin中a = Buf;nbytes= fwrite( a, 1, BufLen, fp);if ( nbytes != BufLen ){printf("destination file write error\n");free(Buf);fclose(fp);return -1;}free(Buf);fclose(fp);return 0;}
编译 gcc mvk210_image.c -o mkmini210


关于Makefile:

led.bin: start.o arm-linux-ld -Ttext 0x0 -o led.elf $^ arm-linux-objcopy -O binary led.elf led.bin arm-linux-objdump -D led.elf > led_elf.dis gcc mkv210_image.c -o mkmini210 ./mkmini210 led.bin 210.bin %.o : %.S arm-linux-gcc -o $@ $< -c %.o : %.c arm-linux-gcc -o $@ $< -c  clean: rm *.o *.elf *.bin *.dis –f
第一步 执行arm-linux-gcc -o $@ $< -c 命令将当前目录下存在的汇编文件和C 文件编译成.o文件; 

第二步 执行arm-linux-ld -Ttext 0x0 -o led.elf $^将所有.o文件链接成elf 文件,-Ttext 0x0 表示程序的运行地址是0x0,由于目前我们编写的代码是位置无关码,所以程序能在任何一个地址上运行; 

第三步 执行arm-linux-objcopy -O binary led.elf led.bin将elf 文件抽取为可在开发板上运行的bin 文件; 
第四步 执行arm-linux-objdump -D led.elf > led_elf.dis 将elf 文件反汇编后保存在dis 文件中,调试程序时可能会到; 
第五步 mkmini210 处理led.bin 文件,mkmini210 由mkv210_image.c编译而来


最后一步:

我们需要将我们最终的210.bin文件烧写到SD卡中去,用到shell编程

新建write2sd

#!/bin/shsudo dd iflag=dsync oflag=dsync if=210.bin of=/dev/sdb seek=1

注意#!不是注释,而是声明用的那种shell,/dev/sdb是Fedora上挂载sd卡的设备节点


做完如上工作,我们终于完成了裸机程序的准备工作,似乎没有单片机那么简单,上来直接写代码,用IDE直接编译下载马上就能看到效果。但高级货本身就是复杂的。

下一节我们将要正式写一个裸机程序了,你会发现他真的就是单片机程序,完全和操作系统没有任何关系,你不会被进程,线程,内存管理,进程通信这些坑爹的东西搅晕,你将进入一个纯净的ARM世界





原创粉丝点击