LED 基本上是学习每款芯片(驱动级别的)的第一步。好,我们看点灯实验

webee的电路图接法是:

可以看到控制led信号低时,LED灯亮。而控制这些管脚的是GPJ2_0-GPJ2_3。

看芯片手册,以GPA0为例

其实控制GPIO的功能有6个寄存器,表格中前4个是在正常模式下,而后2个是断电状态(并非CPU断电,而是处于某种低功耗状态)。

正常:

GPA0CON:控制输入输出及其他功能的

GPA0DAT:input时是pin管脚的状态,而输出时能控制pin管脚的输出。

GPA0PUD:上下拉控制,一般用于输入模式

GPA0DRV:控制电流驱动能力,控制倍数输出。

低功耗:

GPC0CONPDN:控制低功耗输入输出状态。

GPC0PUDPDN:控制上拉下拉等。

我们现在只讨论正常模式下。

在讨论正式代码之前,先了解一下210启动的细节(摘抄webee210):

210的内存映射:

对应的表格:

由上面二个图可知, S5PV210 含有一个大小为 64KB 的 IROM,起始地址为0xD0000000,结束地址为 0xD000FFFF;含有一个大小为 96KB 的 IRAM,起始地址为 0xD0020000,结束地址为 0xD0037FFF;内存起始地址为 0x20000000,有二个内存块,DRAM0 和 DRAM1 大小分别为 512MB、1024MB。

S5PV210 启动流程分析
根据三星公司的《S5PV210_UM_REV1.1》手册可知,S5PV210 启动过程
主要可分为 3 个阶段。
1 S5PV210 上电复位后将从 IROM 处执行已固化的启动代码 -------BL0
2 在 BL0 里初始化过程中对启动设备进行判断,并从启动设备拷贝 BL1(最大
16KB ) 到 IRAM 处 , 即 刚 才 所 说 的 0xD0020000 开 始 的 地 址 , 其 中
0xD0020000~0xD0020010 的 16 字节为 BL1 的校验信息和 BL1 尺寸,并对
BL1 进行校验,校验通过转入 BL1 进行执行,BL1 继续初始化,并拷贝 BL2
(最大 80KB)到 IRAM 中并对其校验,通过后转入 BL2。
3 BL2 完成一些比较复杂的初始化,包括 DRAM 的初始化,完成后将 OS 代码
拷贝到 DRAM 中,并跳到 OS 中执行并完成启动引导。
30图 3.4 启动过程示意图
BL0 固化代码主要完成以下初始化:
1 关闭看门狗;
2 初始化 icache;
3 初始化栈;
4 初始化堆;
5 初始化块设备拷贝功能;
6 设置系统时钟;
7 拷贝 BL1 到 iRAM;
8 检查 BL1 的校验和,如果失败则第二启动模式(安全启动模式),校验成功
则跳到 0xD0020000(IRAM)处执行。
其中 0xD0020000 ~ 0xD0020010 里的 16 字节头部信息是什么呢?这 16 字
节信息用户是不能随便设置的!!
在《S5PV210_iROM_ApplicationNote_Preliminary_20091126》文档中规定
16 字节的头部信息必须为:
地址       内容
0xD002_0000  BL1 的大小
0xD002_0004  必须写为 0
0xD002_0008  CheckSum
0xD002_000C  必须写为 0
校验和的计算方法:
for(count = 0;count < dataLength; count++)
{
buffer = (*(volatile u8*))(uBLAddr + count);
CheckSum = CheckSum + buffer;
}
count:是一个循环索引变量

dataLength :BL1 的大小,以字节为单位
buffer:   从 BL1 里读一个 1 字节的数据
CheckSum: BL1 的校验总和

如何生成 16byte 的头部信息?
在从启动设备(如: NAND FLASH / SD 卡)拷贝 BL1 的前 16K 数据到 IRAM
时,这 16K 数据中的前 16byte 中保存了校验和的值以及 BL1 的大小,在拷贝过
程中 CPU 会计算出当前 bin 文件中含’1’的个数,然后与校验和进行比较,如果
二者相等则继续运行程序,否则,不执行。

启动流程弄好之后没就是程序了:

start.s

.globl _start
_start:                             @因为这里的标号是程序的入口,一定要用 _start ,@否则链接器将找不到程序的入口ldr r1, =0xE0200280         @设置GPJ2CON的bit[0:15],让GPJ2_0、GPJ2_1、GPJ2_2、GPJ2_3                                       ldr r0, =0x00001111            @都作为输出引脚 str r0, [r1]ldr r1, =0xE0200284      @设置GPJ2DAT的bit[0:3],让GPJ2_0、GPJ2_1、GPJ2_2、GPJ2_3                                    mov r0, #0                  @引脚输出低电平,LED亮       str r0, [r1]
halt:                               @让CPU一直执行这条指令,防止PC指针跑飞b halt

makefile:

%.o : %.S    arm-linux-gcc -o $@ $< -c
%.o : %.c   arm-linux-gcc -o $@ $< -c   led.bin: start.o    arm-linux-ld -Ttext 0 -o led.elf start.oarm-linux-objcopy -O binary led.elf led.bin arm-linux-objdump -D led.elf > led.disgcc -o mktools mktools.c   ./mktools led.bin new_led.bin
clean:  rm *.o *.elf *.bin *.dis mktools
load:dd iflag=dsync oflag=dsync if=new_led.bin of=/dev/sdb seek=1

mktools.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;int        BufLen;int      nbytes, fileLen;unsigned int    checksum, count;int     i;// 1. 3个参数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;
}

这个代码的总体思路是将start.s 编译成为 led.elf 其中链接地址是0,然后将转为2进制输出到led.bin,后编译mktoos.c 生成可执行文件mktools,然后通过可执行文件将led.bin 加上头信息,并扩增为16K生成new_led.bin。然后执行

make load 就可以将new_led.bin 下载到sd卡的第一个扇区。好将SD插入210板子上,上电,可以看到4个led全部被点亮了。

可是这样不爽发现没,跑马灯没有,其实汇编也可以实现,但是有C环境我还是用C了。改一下start.s,这中间需要设置堆栈。

.global _start_start:ldr sp, =0xD0037D80                @设置栈,以便调用c函数        bl  led_flow_water              @调用c函数,LED闪烁,之所以用led_flow_water,@是想说明这与名字无关,不一定用mainhalt:                               @让CPU一直执行这条指令,防止PC指针跑飞b halt
</pre><p></p><p style="text-align:left">0xD0037D80是SVCStack的结束地址。但是这个不是必须的,其实可以是下图的中的任意的地址,但是要注意不要覆原来的程序。</p><img src="https://img-blog.csdn.net/20151222224317821?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" /><p style="text-align:left">led.c</p><p style="text-align:left"></p><pre name="code" class="cpp">#define    GPJ2CON     (*(volatile unsigned long *) 0xE0200280)
#define     GPJ2DAT     (*(volatile unsigned long *) 0xE0200284)#define     GPJ2_0_OUT  (1<<0)
#define     GPJ2_1_OUT  (1<<4)
#define     GPJ2_2_OUT  (1<<8)
#define     GPJ2_3_OUT  (1<<12)#define        GPJ2_0_ON   ~(1<<0)
#define     GPJ2_1_ON   ~(1<<1)
#define     GPJ2_2_ON   ~(1<<2)
#define     GPJ2_3_ON   ~(1<<3)#define        GPJ2_0_OFF  (1<<0)
#define     GPJ2_1_OFF  (1<<1)
#define     GPJ2_2_OFF  (1<<2)
#define     GPJ2_3_OFF  (1<<3)/* 延时函数 */
void delay(int count)
{while (count--);
}/* 流水灯函数 */
void led_flow_water()
{unsigned int i = 0;GPJ2CON |= (GPJ2_0_OUT | GPJ2_1_OUT | GPJ2_2_OUT | GPJ2_3_OUT);   // 配置引脚while (1){       GPJ2DAT = ~(1<<i);   //GPJ2DAT的值依次为 1110B 1101B 1011B 0111B ,不断循环i++;                                          if (i == 4)i = 0;delay(0x100000);}
}

很简单的函数。

makefile

%.o : %.S    arm-linux-gcc -o $@ $< -c
%.o : %.c   arm-linux-gcc -o $@ $< -c   led.bin: start.o  led.o     arm-linux-ld -Ttext 0 -o led.elf $^arm-linux-objcopy -O binary led.elf $@  arm-linux-objdump -D led.elf > led.disgcc -o mktools mktools.c   ./mktools $@ new_led.bin
clean:  rm *.o *.elf *.bin *.dis mktools
load:dd iflag=dsync oflag=dsync if=new_led.bin of=/dev/sdb seek=1

S5PV210 裸机开发驱动之LED灯相关推荐

  1. (exynos4412)Tiny4412裸机开发-点亮LED灯

    1. 前言 Tiny4412开发是友善之臂推出的Android.Linux学习开发板,CPU采用三星的EXYNOS4412,32位芯片,属于Cortex-A系列,主频是1.5GHZ,可以运行ubunt ...

  2. 点亮stm32开发板的led灯

    点亮stm32开发板的led灯 简述 我使用的是STM公司stm32f103系列开发板,我们通过看原理图,对LED进行操作,以实现led灯的控制.(对于小白来说很有作用哈!废话不说,上料!) 1.查看 ...

  3. linux字符设备led驱动源码,字符设备驱动控制LED灯

    开发板:龙芯1B PC:Ubuntu 13.10 本程序为字符设备驱动,提供控制led灯功能,如要实现控制需要自己写应用程序,打开驱动文件就可控制led灯,led灯通过gpio控制 #include ...

  4. 驱动操作控制LED灯

    控制LED灯: 驱动如何操作寄存器 rgb_led灯的寄存器是物理地址,在linux内核启动之后, 在使用地址的时候,操作的全是虚拟地址.需要将物理地址 转化为虚拟地址.在驱动代码中操作的虚拟地址就相 ...

  5. FS210开发平台板载LED灯控制实验

    作者:朱老师,华清远见嵌入式学院讲师. 目 录 1.实验目的 - 2 -         2.实验设备 - 2 -         3.实验内容 - 2 -         4.实验步骤 - 3 - ...

  6. 基于stm32通过HC_05(ZS-040)蓝牙模块用手机控制stm32开发板上led灯的亮灭

    文章目录 前言 一.HC-05蓝牙是什么? 二.应用实例步骤 1.使用AT指令对蓝牙的初始化 2.打开手机蓝牙助手查看是否搜索到该蓝牙 3.用蓝牙模块代替TTL连接stm开发板 4.创建项目开始配置相 ...

  7. 【离线语音专题④】安信可VC离线语音开发板二次开发语音控制LED灯

    系列文章目录 [离线语音专题①]安信可最新离线语音模组VC系列出厂固件使用教程--SDK开源? [离线语音专题②]安信可语音开放平台的使用--VC系列SDK的获取 [离线语音专题③]安信可VC系列离线 ...

  8. 简单SOPC实例开发任务——控制led灯闪烁

    任务1:基于nios ii处理器系统控制一个led灯闪烁 硬件系统: Nios ii处理器 4KB片内ROM存储器用于存储程序代码以及程序运行空间: 4KB片内RAM存储器用于变量存储(R/W数据): ...

  9. android驱动例子(led灯控制),android驱动例子(LED灯控制)

    --作者:赖玉平(Peter Lai)aulyp@163.com 本例子,讲述在android2.1上完全自已开发一个驱动去控制硬件口并写应用测试该驱动,通过这样一个例子,解析android下的驱动开 ...

最新文章

  1. JAVA IF判断语句
  2. nodejs http.get 方法可以 request 不行
  3. 如何选择漏电保护器规格型号_施工现场三级电箱如何配置?图示详解,清晰明了!...
  4. mysql relay bin 主库_MySQL主库binlog(master-log)与从库relay-log关系代码详解
  5. gridview databind 会导致页面刷新马_Innodb批量页面刷盘情况下的quot;两次写quot;
  6. c ++查找字符串_C ++异常处理| 查找输出程序| 套装1
  7. Java集合系列---HashMap源码解析(超详细)
  8. dvd打开显示服务器失败,9g、10g和11G PowerEdge服务器未启动的e1000故障安全错误
  9. Ingenious Lottery Tickets 模拟
  10. [2018.09.12 T1] 下落的圆盘
  11. 基本磁盘转换动态磁盘,再转换为基本磁盘,分区数据丢失
  12. 加糖加冰加牛奶——装饰模式
  13. 一起捉妖 ios12.3更新了location不用了 怎么办
  14. 计算机打印范围如何设定,cad如何设定打印范围
  15. Mongo数据库简介
  16. INV模块常用表结构
  17. python numpy安装失败_Mac下安装Python的numpy库失败的解决方法
  18. 使用了未经检查或不安全的操作_基建安全质量“四不两直”检查现场检查表
  19. 实验A---- ADFA的可判定性
  20. python新手教程全套_Python入门教程完整版(懂中文就能学会)

热门文章

  1. excel下拉菜单vba_一站式提供不同的Excel下拉菜单
  2. 一个简单的宿舍管理系统
  3. GooglePhoto设置壁纸----壁纸裁剪界面配置
  4. 如何找到google主题的壁纸
  5. html弹出式登录窗口(DIV悬浮窗口)实现
  6. Interconnection
  7. java项目如何发送邮件
  8. Java播放声音文件
  9. 微信小程序开发(四)入门之打卡功能开发
  10. win10找不到oracle11g客户端,win10操做系统下oracle11g客户端/服务端的下载安装配置卸载总结...