嵌入式系统的概念:以应用为中心, 以计算机技术为基础, 软硬件可裁减, 适应应用系统对功能,可靠性,成本,体积,功耗严格要求的专用计算机系统;
交叉编译: 开发工具是主机上运行的程序, 生成的程序是目标机的程序;
应用领域: 工业控制, 交通管理, 信息家电, 家庭智能管理, POS网络及电子商务, 环境工程与自然, 机器人.
组成部分: 微处理器, 外围硬件, 嵌入式操作系统, 应用程序, (开发环境);
最小系统: 处理器, 内存, 时钟, 电源和复位;
常见的嵌入式系统扩展部件:
内存类:SRAM, NOR FLASH, SDRAM, NAND FLASH;
通讯类:网络芯片, USB芯片, CAN总线芯片, IIC接口芯片
其他类:AD/DA, 传感器, LCD/LCM,
几种内存类芯片的对比:
SRAM, 线性读写, 地址数据总线扩展,可运行代码,读写数据,速度快, 贵;
NOR FLASH, 线性读, 写要时序, 地址数据总线扩展, 固化代码和数据, 运行代码, 只读数据, 较贵;
SDRAM, 线性读写, 特殊内存控制器扩展, 可运行代码,读写数据, 便宜;
NAND FLASH, 时序读写, GPIO或普通总线方式扩展, 适用于大规模读写数据,不能字节方式读写, 便宜;
典型器件:
NOR FLASH: SST39VF160, 16bit*1M空间, 也即2M;
SDRAM: HY57V641620, 4Banks*16bit*1M空间, 也即8M;
ARM, Advanced RISC Machines, 1991年成立于英国剑桥; 巧合的是, LINUX也诞生在这一年;
ARM的7种运行模式:
非特权模式|------------------特权模式--------------------------------------
------非异常模式-----|-----------------异常模式----------------------------
用户模式 系统模式 中断模式,快中断模式, 管理模式, 终止模式, 未定义模式
内存结构模型:冯诺依曼结构和哈佛结构;后者分2个独立的内存空间:指令空间和数据空间;
ARM的工作状态, ARM态, THUMB态; BX指令可以切换;
ARM的存储器格式, 可设为大端格式或小端格式;
ARM寄存器组织, 37个32bit寄存器,其中:
31个通用寄存器:未分组R0~R7, 分组R8~R14(R13为堆栈指针寄存器SP, R14为子程序链接寄存器LR), 程序计数器PC(R15);
6个为状态寄存器, CPSR+5*SPSR;
ARM的7种异常:
0X0-reset, 0X4-undefined, 0X8-swi, 0XC-prefetch abort, 0X10-data abort, 0X14-保留, 0X18-irq, 0X1C-fiq;
异常优先级排序:
1.RESET 2.DATA ABORT 3.FIQ 4.IRQ 5.PRE ABORT 6.UNDEF, SWI
子程序及异常返回指令:
BL MOV PC, R14
SWI MOVS PC, R14_svc
UDEF MOVS PC, R14_und
FIQ SUBS PC, R14_fiq, #4
IRQ SUBS PC, R14_irq, #4
PABT SUBS PC, R14_prefetch, #4
DABT SUBS PC, R14_dataabt, #8
ARM对异常的响应:
下一条指令存入LR->CPSR复制到相应的SPSR保存->设置CPSR模式位->禁止中断位->调整到异常处理向量;
ARM从异常返回:
LR的值减去相应的偏移量送到PC中, SPSR复制到CPSR中, 同时也恢复了中断禁止位;
ARM的内核系列: ARM7, ARM9, ARM9E, ARM10E, AMR11, SecurCore, StrongARM/Xscale, Cortex
ARM的体系结构:ARMV4T->ARMV5TE->ARMV6->ARMV7
ARM的命名规则:
E: 增强DSP T:支持Thumb J:支持Jazzle S:可综合的内核
第一个数字代表系列名:7,9,10,11
第二个数字: 2带MMU 4带MPU 6无MMU和MPU
第三个数字: 0标准Cache 2减小的Cache 6可变的Cache
ARM7TDMI: T支持Thumb D支持片上Debug M内嵌硬件乘法器Mul I嵌入式ICE
目前主要使用的ARM内核有:
ARM7TDMI(s3c44BOX, s3c4510, lpc2000系列) ARM720T ARM920T(s3c2410, s3c2440) XSCALE(pxa255)
ARM核心处理器的使用:
内存控制单元, 中断控制单元, GPIO, 定时器, UART;
ARM指令分类:
跳转指令, 数据处理指令, 乘法指令, 加载/存储指令, 状态寄存器指令, 协处理器指令, Thumb指令集;
mcu 微控制器 mpu 微处理器 dsp 数字信号处理器 soc 片上系统
PC上: IO在南桥 内存控制在北桥
嵌入式最小系统: 处理器, 内存, 时钟, 电源和复位
级联/对联线(交叉线) 1<->3 2<->6 双绞线
电压, 内正外负
DB9 公母线, 串口延长线
DB25 公母线, 并口延长线
JTAG 20根线 简易调试器 Joint Test Action Group
计算机上串口DB9公头, VGA口是14芯母头, 并口DB25母头;
TAP Test Access Point
PCB 单层->双层->四层->六层->十层
ISP系统编程,即In System
Programming,简单地说就是指待编程的单片机在实验板(目标板)上,不用拆下来用编程器进行编程,只需利用ISP编程接口,通过下载线就可把程
序代码下载到单片机内部,ISP技术是对传统编程技术的一大革新。通过ISP技术,我们在烧写程序的时候就不用频繁拔插芯片,只要鼠标点击即可把程序写入
单片机,彻底告别以前那样用编程器反复烧写拨插芯片的烦恼。
芯片选型(15-30天)->画原理图(7-14天)->画板(2天)->制板(7-10天)->采购期间(可提前并行)->焊接/调试(5-30天)
焊接原则: 逐步添加, 电源, CPU, 由小系统开始, 逐步调试;
封装名称: BGA QFP
addr 21bit->2 * K * K = 2M * data 16bit ->4M bytes
编译器: 状态机->输入条件 - 状态迁移 - 结束条件
memory map / mem map / system memory map / special register
实验准备: 烧写工具-二进制程序-硬件连接-硬件驱动安装
给开发板烧写程序:
安装giveio.sys->并口驱动->JTAG
lumit-sjf4510-1.1.0.exe 烧写工具/VC编写 从0x0开始烧写程序进flash.
安装ADS, Arm Development Suite, 用armcc命令看是否安装成功.
ADS发展历史: SDT->ADS->RealView
IDE集成开发环境: Integrated Develop Eviroment: Edit(vi), Compile(gcc), Debug(gdb), Run(shell),
Project Management(make & Makefile)
项目工程文件: *.mcp
Arm可执行文件: axf
ADS使用流程: 建工程->建文件->Add to Project->Compile(生成. o文件)->Project /make/生成axf文件
AXD Debug->Option->Select target->Arm;
Reset开发板->打开BanYan Deamon File->AutoDetect->发现Sangsung 4510->启动AXD->Configure Target
->选Banyan dll->load image/选image文件axf.
ARM体系结构和指令集:
中断->来自外部事件 陷阱->内部出错或软中断
文字池的概念: mov R0, 0xdata(32bit) 指令存放数据地址与当前指令地址的差值; 数据存放地就是文字池;
BSS段: 全局变量, 不带初值的变量保存在该段, 会被赋值为0;
编译时: 指针, 变量名是在编译是存在; 到运行时就消失了;
运行时: 逻辑, 运算变成了内存单元;
计算机的本质是指令和数据;
运算符, 逻辑, 变量在编译时变成相对地址, 连接后, 变量就成了绝对地址;
BSS段, 编译时只保存起始和结束位置, 所以BSS段数组的大小不影响编译后文件大小;????
变量与其存储关系//运行时变量与代码的关系//段的概念,elf中分段存储//运行时函数与变量的关系;
ADS工具集: armcc, armasm, armar, armcpp, armlink, armfromelf
编译时出错: 有行号显示 链接时出错: 无行号显示
armasm *.s -o *.o 生成o文件 也可, armcc -c *.c 生成o文件
armlink -entry 0x8000 -o *.axf *.o
AXD *.axf 启动AXD, 装入axf.
超级终端设置: com1, 19600, 8, N, 1, N
JTAG: 通过并口, 不是传整个axf文件, 而是代码段和数据段, 调试
断电->去JTAG, 试验用串口下载->dn/发送文本/uue->下载完毕, GO运行;
uue下到板子上也成了bin文件, 变成uue只是为了方便串口的字符传送;
fromelf uuencode
axf-------->bin------->uue
也是elf文件 | 通过串口下到ram运行
可JTAG, banyan |
AXD运行 |-------->code + data这才是cpu上真正运行的东西
C语言, 4个参数以内, R0, R1, R2, R3, 返回值放在R0;
uuencode * . bin * . uue
armlink -ro-base 0x9000 -entry 0x9000 demo.o -o demo.axf
编译器决定偏移地址; 放在任何位置都能成功执行的, 位置无关代码???
PIC -> Position Independent Code
fromelf -bin -output demo. bin demo. axf
fromelf -c -s -o demo. lst demo. axf
uuecode demo. bin demo. uue
分层模型可移植性强. 弊端, 效率低了;
驱动的本质: 牺牲效率, 增强可移植性; 保存现场的开销, 入栈出栈/用户态系统态切换开销;
区分工作模式为了支持异步事件的处理; 区分权限(特权)为了操作系统支持用户态和系统态;
dirty data 无效数据, 被污染的数据
未定义指令: 二进制兼容, 未定义异常解决 /源码兼容, 编译器改造???
软中断的主要作用是实现系统调用; svc常用 sys使用较少
系统态可改CPSR???
linux有近200个系统调用, 系统调用号在R0存放, open #1, close #2, write #5, read #6;
RST, IRQ, FIQ是外部引发异常;
处理之前打开CPSR的I位;
ldmfd sp! , { r0~r3, pc}^ 该语句中^是恢复cpsr的作用;
FIQ比IRQ更快的原因:
1. 寄存器R8~R14, 不用保存; 2. 优先级更高; 3. 最异常向量表最后, 不用跳转;
更改CPSR->PC值赋给LR->恢复CPSR;???
各种异常返回时, 对返回地址的调整方式不同; 数据异常为什么-8??? -4可以让语句本身被再执行一遍;
cpsr_cxsf 后面四个字母代表了cpsr的各个位段;
INTMSK &= ~(( 1 << 21 ) | ( 1 << 0)) ;
import __main 引入一个外部符号 entry | __int| 申明一个入口
中断int0<-->引脚的关系是确定的还是设置的??
STMFD 批量移动 LDMFD 批量恢复
一些位操作技巧:
( value & ( 1 << i)) ? 1 : 0;
value = value | ( buf[i] << i );
*IOPDATA | 0x00000010;
*IOPDATA &( ~ 0x00000010) ;
driver的操作一般是带BUF的.
static的变量, 外部文件无法用extern来引用, 因而确保数据的有效范围, 外部可通过函数操作静态变量;
中断的各层控制: 设备级IOMOD->CPU级MASK & PENDING->用户级CPSR;
数据段rw_base 代码段ro_base 设置的地址是运行时应该在位置;
bin文件不保留地址间的空洞; 0x1000->4k 0x8000->32k
已初始化的全局变量在数据段, 未初始化的全局变量在BSS段???
bootloader必须设两个参数: ro = 0x0 rw = sdram 10M
加载地址: load addr 执行地址: execute addr
ro_limit ro_base 是编译器内部变量, 直接使用
remap 内存重映射
A应用程序与Bootloader的区别:
B先执行, A后执行
B存储在flash, A存在RAM中;
B靠自己加载, B靠A加载;
Ro在flash上, Rw在Ram;
ARM_ARM手册
异常向量表放在flash中较安全, 放在ram中速度较快;
GNU TEXT DATA BSS 其中的只读数据ro_data也在RO段
??? RO RW ZI
ROMCON RAMCON的设置, 片选, 原理图关系;
BOOTLOADER的相关级别: ARM CORE 37个寄存器->DEVICE外设寄存器->compiler提供一些变量
BIC清零指令 1100->C->12
SYSCFG 87FFFFA0->3FE0000
BOOTLOADER的两项重要功能: flash write & auto loadder
看看__main与main之间的代码在作什么?
寄存器->设置寄存器Bank地址->访问该地址产生相应的片选信号;
Refextcon->0x000083fd->0x3fdc000->nECS3 + nWE ->SEG7_CS
数据宽度设置的意义何在, 难道是配合不同硬件而设??? nmake管理项目文件; ro_base=0x8000, entry=0x8000
s3c4510的地址范围0~64M; entry 可能是供AXD使用, ro_base 生成的bin文件会用到;
烧写进flash, 下载进ram; init段, 在执行一段后就被回收掉; arm core 有37寄存器;
结构体空洞, sizeof()可以测出; pack可强制紧凑, 让机器不对齐;
semihosting 半主机方式/截获swi;
__main ->__rt_entry ->main;
ld scripts ->scatter分散 file =linux下的链接脚本; armlink . . . -scatter . . . scatter . . .
定义变量的顺序注意对齐, 防止空洞产生;
当程序从__main进入时: rw 全局变量有初值, ro 全局变量有初值;
当程序从c_entry进入时: rw 全局无初值, ro 全局有初值; ???
void __rt_entry(void)
{
main();
}
因为修改了系统库函数, 如fputc(), 所以不能使用编译器默认的__rt_entry(因为lib初始化的部分有冲突), 所以必须自己实现__rt_entry();
指定makefile中, -first startup.o确定从此处启动;
ldr Rn, =0x1234 ==> mov Rn, #0x1234
ldr Rn, =main ==> mov Rn, #0x8000 ->main的地址
axd下可运行, UUE下去后无法正常运行-->设入口地址, 设startup. o即可;
cmd [][5] = { "abc", "cde", "fgh" }; 定义列宽;
定义char *aa; printf ( "%x\n", (unsigned int) aa );
xmodem协议时, 发送后面的数字在超级终端不显示了->因为超级终端的工作模式变成了xmodem协议通讯;
验证一些概念, 比如ZI在文件中的位置, 实验设计????
如何把应用程序写成bootloader???
movs pc, lr 字母s表示, 若目标是pc, 则用CPSR<-SPSR
x86有四个模式, 为什么要用模式, 安全, 稳定/权限管理;
异常发生时的行为:
1. PC ->FIG_LR
2. CPSR->FIG_SPSR
3. 跳转中断向量表;
4. 修改CPSR, 关中断;
硬件的原子操作, 不可被打断;
BL, 中断, 硬件会保存真实PC->LR;
向量表->stub->do_irq entry_armv. s
b指令编译时, 二进制码保存的是相对地址;
bootloader的向量表在内核跑起来之后被系统覆盖;
模式位5位, 后4位正好是中断向量地址; 模式从IRQ到SVC;
栈是往下压的, stm存储是往上加的, 所以栈指针先减去一个值就是开了空间出来;
adrsvc ne, lr, 3f f表示往前进方向找, b表示往后退方向找;
ldr lr, =c_entry;
mov pc, lr
或
ldr pc, =c_entry;
led_api. c若不包含led_api. h, 则函数申明或函数体应出现在调用前;
两种跳转: ldr pc, =c_entry 全范围, 绝对跳 b c_entry 范围有限, 相对跳;
main. c有必要初始化一些外设, 关声音及显示等;
地址的设置:
romcon0->0x12040060
romcon1->0x10842060
dramcon0->0x10000398
dramcon1->0x10040398
将基地址由8000/c000->0/4000后bootloader可以启动;
带MMU, 程序员看到的, CPU看到的地址都是虚地址, 发到地址总线上的是实地址;
内存映射和内存保护功能; MMU + 页表;
arm_linux: linux(约100M) + patch(约100k); 带MMU的arm上运行;
实时的概念: 确定性, 在可预见的时间内, 不一定是越快越好;
ARM的优势: 高性能, 低功耗, 低成本;
rtai -> real time app interface
linux与UCOS的对比:
linux->100+M, 5500+文件, driver+net+fs
uc/os->15~20文件, 只有schedulor调度器;
链接把相对地址换成绝对地址(定址), 全局变量也由相对到绝对; Ld需加上库;
xxd data. bin /nm demo查看符号表 /file add.o查看文件信息 /strip demo去除符号表
objdump -d *. o ->lst文件
arm-elf-gcc -elf2flt hello.c -o hello
com1 19200 8N1 NONE硬件流控
sudo minicom com11
实验开发板准备:
minicom->reset开发板->ipcfg 192.168.168.101->load->下载完后, run
pc准备:
tftp->connect 192.168.168.101->binary->put image.net.ram
开发板若运行了uclinux系统, 也可从PC上ftp程序;
ifconfig eth0 192.168.168.100 /ifconfig eth0 up
中断一般是异步的, 异常一般是同步的;
命令系列:
gcc -s main.c
as -o main.o main.s
gcc -o demo main.o
ar -rv libmath.a *.o
gcc -o demo libmath.a *.o
nm main.o /objdump -d main.o /objcopy -o binary --only-section=. text demo text. bin
readelf -a main.o
bootloader:
;/*************************************************************************/
;/* Format of the Program Status Register */
;/*************************************************************************/
;/* */
;/* 31 30 29 28 7 6 5 4 3 2 1 0 */
;/*+---+---+---+---+--ss--+---+---+---+---+---+---+---+---+ */
;/*| N | Z | C | V | | I | F | T | M4 ~ M0 | */
;/*+---+---+---+---+--ss--+---+---+---+---+---+---+---+---+ */
;/* */
;/* Processor Mode and Mask */
;/* */
;/*************************************************************************/
;
Mode_USR EQU 0x10
Mode_FIQ EQU 0x11
Mode_IRQ EQU 0x12
Mode_SVC EQU 0x13
Mode_ABT EQU 0x17
Mode_UND EQU 0x1B
Mode_SYS EQU 0x1F
MASK_MODE EQU 0x0000003F
MODE_SVC32 EQU 0x00000013
I_BIT EQU 0x80 ; when I bit is set, IRQ is disabled
F_BIT EQU 0x40 ; when F bit is set, FIQ is disabled
ASIC_BASE EQU 0x03ff0000
;SYSTEM MANAGER REGISTERS
ARM7_SYSCFG EQU (ASIC_BASE+0x0000)
ARM7_CLKCON EQU (ASIC_BASE+0x3000)
ARM7_EXTACON0 EQU (ASIC_BASE+0x3008)
ARM7_EXTACON1 EQU (ASIC_BASE+0x300c)
ARM7_EXTDBWTH EQU (ASIC_BASE+0x3010)
ARM7_ROMCON0 EQU (ASIC_BASE+0x3014)
ARM7_ROMCON1 EQU (ASIC_BASE+0x3018)
ARM7_ROMCON2 EQU (ASIC_BASE+0x301c)
ARM7_ROMCON3 EQU (ASIC_BASE+0x3020)
ARM7_ROMCON4 EQU (ASIC_BASE+0x3024)
ARM7_ROMCON5 EQU (ASIC_BASE+0x3028)
ARM7_DRAMCON0 EQU (ASIC_BASE+0x302c)
ARM7_DRAMCON1 EQU (ASIC_BASE+0x3030)
ARM7_DRAMCON2 EQU (ASIC_BASE+0x3034)
ARM7_DRAMCON3 EQU (ASIC_BASE+0x3038)
ARM7_REFEXTCON EQU (ASIC_BASE+0x303c)
; controller registers
ARM7_INTMODE EQU (ASIC_BASE+0x4000)
ARM7_INTPEND EQU (ASIC_BASE+0x4004)
ARM7_INTMASK EQU (ASIC_BASE+0x4008)
ARM7_INTOFFSET EQU (ASIC_BASE+0x4024)
ARM7_INTPENDTST EQU (ASIC_BASE+0x402c)
ARM7_INTPRI0 EQU (ASIC_BASE+0x400C)
ARM7_INTPRI1 EQU (ASIC_BASE+0x4010)
ARM7_INTPRI2 EQU (ASIC_BASE+0x4014)
ARM7_INTPRI3 EQU (ASIC_BASE+0x4018)
ARM7_INTPRI4 EQU (ASIC_BASE+0x401C)
ARM7_INTPRI5 EQU (ASIC_BASE+0x4020)
ARM7_INTOSET_FIQ EQU (ASIC_BASE+0x4030)
ARM7_INTOSET_IRQ EQU (ASIC_BASE+0x4034)
; I/O Port Interface
ARM7_IOPMOD EQU (ASIC_BASE+0x5000)
ARM7_IOPCON EQU (ASIC_BASE+0x5004)
ARM7_IOPDATA EQU (ASIC_BASE+0x5008)
; IIC Registers
ARM7_IICCON EQU (ASIC_BASE+0xf000)
ARM7_IICBUF EQU (ASIC_BASE+0xf004)
ARM7_IICPS EQU (ASIC_BASE+0xf008)
ARM7_IICCNT EQU (ASIC_BASE+0xf00c)
;/*************************************************************************/
;/* SYSTEM MEMORY CONTROL REGISTER EQU TABLES */
;/*************************************************************************/
;***************Init***************
rEXTDBWTH EQU 0x00003001
rROMCON0 EQU 0x02000060
rROMCON1 EQU 0x60
rROMCON2 EQU 0x60
rROMCON3 EQU 0x60
rROMCON4 EQU 0x60
rROMCON5 EQU 0x60
rSDRAMCON0 EQU 0x12008380
rSDRAMCON1 EQU 0x00
rSDRAMCON2 EQU 0x00
rSDRAMCON3 EQU 0x00
rSREFEXTCON EQU 0xCE278360
;************Memory Remap**************
rEXTDBWTH_R EQU 0x00003001
rROMCON0_R EQU 0x12040060
rROMCON1_R EQU 0x60
rROMCON2_R EQU 0x60
rROMCON3_R EQU 0x60
rROMCON4_R EQU 0x60
rROMCON5_R EQU 0x60
rSDRAMCON0_R EQU 0x10000380
rSDRAMCON1_R EQU 0x00
rSDRAMCON2_R EQU 0x00
rSDRAMCON3_R EQU 0x00
rSREFEXTCON_R EQU 0xCE278360
;/***************************************************************/
END
;**************************************************************
;
; This an simple implementation of bootloader for S3C4510B
; Hope it is useful to you.
;
; Enjoy it!
;
;**************************************************************
AREA Init, CODE, READONLY
CODE32
GET snds.s
ENTRY
start
;Part 1
;***************************************************************
;disable interrupts in CPU and switch to SVC32 mode
MRS r0, cpsr
BIC r0, r0, #MASK_MODE
ORR r0, r0, #MODE_SVC32
ORR r0, r0, #I_BIT
ORR r0, r0, #F_BIT
MSR cpsr_c, r0
LDR r2, =ARM7_INTMASK ;R2->interrupt controller
MVN r1, #0 ;&FFFFFFFF
STR r1, [r2] ;disable all interrupt soucres
LDR r2, =ARM7_INTPEND ;R2->interrupt pend register.
MVN r1, #0 ;&FFFFFFFF
STR r1, [r2] ;clear all interrupt flags.
;Part 2
;****************************************************************
LDR r0, =ARM7_SYSCFG
LDR r1, =0x87ffffA0 ;config SYSCFG
STR r1, [r0] ;Cache & WB disabled
;Part 3
;***************************************************************
; Import some important variables for later use
IMPORT |Image$$RO$$Base|
IMPORT |Image$$RO$$Limit|
IMPORT |Image$$RW$$Base|
IMPORT |Image$$RW$$Limit|
IMPORT |Image$$ZI$$Base|
IMPORT |Image$$ZI$$Limit|
;Part 4
;****************************************************************
;Initalize the memory as followa:
; FLASH @ 0 ~ 2 M
; SDRAM @ 2 ~ 18M
LDR r1, =rEXTDBWTH ;EXTDBWTH
LDR r2, =rROMCON0 ;ROMCON0 @ 0M ~ 2M
LDR r3, =rROMCON1 ;ROMCON1 @ DISABLED
LDR r4, =rROMCON2 ;ROMCON1 @ DISABLED
LDR r5, =rROMCON3 ;ROMCON1 @ DISABLED
LDR r6, =rROMCON4 ;ROMCON1 @ DISABLED
LDR r7, =rROMCON5 ;ROMCON1 @ DISABLED
LDR r8, =rSDRAMCON0 ;SDRAMCON0 @ 2M ~ 18M
LDR r9, =rSDRAMCON1 ;SDRAMCON1 @ DISABLED
LDR r10,=rSDRAMCON2 ;SDRAMCON2 @ DISABLED
LDR r11,=rSDRAMCON3 ;SDRAMCON3 @ DISABLED
LDR r12,=rSREFEXTCON
LDR r0, =ARM7_EXTDBWTH
STMIA r0, {r1-r12}
;Part 5
;***************************************************************
;Self copy from FLASH to SDRAM
LDR r0, =|Image$$RO$$Base|
LDR r1, =|Image$$RO$$Limit|
LDR r2, =|Image$$RW$$Base|
LDR r3, =|Image$$RW$$Limit|
SUB r1, r1, r0
SUB r3, r3, r2
ADD r1, r1, r3
LDR r2, =0x200000 ;@2M
COPY
LDR r3, [r0], #4
STR r3, [r2], #4
SUBS r1, r1, #4
BNE COPY
;Part 6
****************************************************************
;Remap the memory
; FLASH @ 16 ~ 18M
; SDRAM @ 0 ~ 16M
LDR r1, =rEXTDBWTH_R ;EXTDBWTH
LDR r2, =rROMCON0_R ;ROMCON0 @ 16M ~ 18M
LDR r3, =rROMCON1_R ;ROMCON1 @ DISABLED
LDR r4, =rROMCON2_R ;ROMCON2 @ DISABLED
LDR r5, =rROMCON3_R ;ROMCON3 @ DISABLED
LDR r6, =rROMCON4_R ;ROMCON4 @ DISABLED
LDR r7, =rROMCON5_R ;ROMCON4 @ DISABLED
LDR r8, =rSDRAMCON0_R ;SDRAMCON0 @ 0M ~ 16M
LDR r9, =rSDRAMCON1_R ;SDRAMCON1 @ DISABLED
LDR r10,=rSDRAMCON2_R ;SDRAMCON2 @ DISABLED
LDR r11,=rSDRAMCON3_R ;SDRAMCON3 @ DISABLED
LDR r12,=rSREFEXTCON_R
LDR r0, =ARM7_EXTDBWTH
STMIA r0, {r1-r12}
;Part 7
;*****************************************************************
; Copy RW & ZI to SDRAM
LDR r0, =|Image$$RO$$Limit|
LDR r1, =|Image$$RW$$Base|
LDR r3, =|Image$$ZI$$Base|
CMP r0, r1
BEQ %1
0 CMP r1, r3 ; Copy init data
LDRCC r2, [r0], #4
STRCC r2, [r1], #4
BCC %0
1 LDR r1, =|Image$$ZI$$Limit| ; Top of zero init segment
MOV r2, #0
2 CMP r3, r1 ; Zero init
STRCC r2, [r3], #4
BCC %2
;Part 8
;***********************************************************************
;Set stack pointer & jump to c function
LDR sp, =0x800000
IMPORT loadkernel
LDR pc, =loadkernel
END
#include "typdef.h"
extern char kernel[];
void loadkernel()
{
int i;
char *to;
char *from;
void (*fp)(void);
fp = (void (*)(void))0x8000;
to = (char*)0x8000;
from = (char*)kernel;
for(i = 0; i < 2097152; i++){
*to = *from;
to++;
from++;
}
(*fp)(); //把控制权交给kernel。
return;
}
第一部分 Bootloader启动代码分析
文件名:Init.s
;**************************************************************
; This an simple implementation of bootloader for S3C4510B
;**************************************************************
详细分析:
代码段声明
AREA Init, CODE, READONLY
运行在ARM模式
CODE32
包含一个外部文件,主要是一些声明
GET snds.s
声明程序大入口
ENTRY
start
;Part 1
;***************************************************************
;disable interrupts in CPU and switch to SVC32 mode
第一部分 设置CPSR寄存器
读取CPSR寄存器内容到R0寄存器
MRS r0, cpsr
对R0当中最后6位清0,MASK_MODE的值为0b0000 0000 0000 0000 0000 0000 0011 1111
BIC r0, r0, #MASK_MODE
将R0或上MODE_SVC32的值0b 0000 0000 0000 0000 0000 0000 0001 0011
ORR r0, r0, #MODE_SVC32
将R0的bit 7置1,对应的CPSR位是IRQ禁止位
ORR r0, r0, #I_BIT
将R0的bit 6置1,对应的CPSR位是FIQ禁止位
ORR r0, r0, #F_BIT
将设置好的R0的值赋予CPSR,系统切换到SVC模式,并且禁止IRQ ,FIQ中断;
MSR cpsr_c, r0
设置INTMASK寄存器
禁止所有中断源
LDR r2, =ARM7_INTMASK ;R2->interrupt controller
MVN r1, #0 ;&FFFFFFFF
STR r1, [r2] ;disable all interrupt soucres
清除所有INTPEND中的中断标志,通过给相关位写1来清除
LDR r2, =ARM7_INTPEND ;R2->interrupt pend register.
MVN r1, #0 ;&FFFFFFFF
STR r1, [r2] ;clear all interrupt flags.
;Part 2
;****************************************************************
第二部分:设置SYSCFG寄存器状态为:cache disabled , write buffer disabled, 8K BYTE SRAM, internal SRAM 起始地址为0X3FE0000,special Register 起始地址为0X3FF0000,sync. DRAM;
LDR r0, =ARM7_SYSCFG
LDR r1, =0x87ffffA0 ;config SYSCFG
STR r1, [r0] ;Cache & WB disabled
;Part 3
;***************************************************************
; Import some important variables for later use
第三部分:导入一些重要的变量备用
导入RO段基地址
IMPORT |Image$$RO$$Base|
导入RO段结束地址
IMPORT |Image$$RO$$Limit|
导入RW段基地址
IMPORT |Image$$RW$$Base|
导入RW段结束地址
IMPORT |Image$$RW$$Limit|
导入ZI段基地址
IMPORT |Image$$ZI$$Base|
导入ZI段结束地址
IMPORT |Image$$ZI$$Limit|
;Part 4
;****************************************************************
;Initalize the memory as followa:
; FLASH @ 0 ~ 2 M
; SDRAM @ 2 ~ 18M
第四部分:设置内存地址空间,FLASH 设置在0 – 2M,数据宽度为8BIT,SDRAM 设置在2 – 18M,数据宽度为32BIT;
设置各内存的数据总线宽度
0X3001=0b 0000 0000 0000 0000 0011 0000 0000 0001
其中DSD0设为11,将SDRAM数据宽度设为32BIT
DSR0设为01,将FLASH数据宽度设为8BIT
LDR r1, =rEXTDBWTH ;EXTDBWTH
设置FLASH 的地址范围设为0M-2M,normal ROM 模式
0x02000060=0b0000 0010 0000 0000 0000 0000 0110 0000
LDR r2, =rROMCON0 ;ROMCON0 @ 0M ~ 2M
其他ROM BANK的地址范围设为0 – 0,也就是不使用
LDR r3, =rROMCON1 ;ROMCON1 @ DISABLED
LDR r4, =rROMCON2 ;ROMCON1 @ DISABLED
LDR r5, =rROMCON3 ;ROMCON1 @ DISABLED
LDR r6, =rROMCON4 ;ROMCON1 @ DISABLED
LDR r7, =rROMCON5 ;ROMCON1 @ DISABLED
设置SDRAM 的地址范围2M – 18M
0x12008380=0b0001 0010 0000 0000 1000 0011 1000 0000
LDR r8, =rSDRAMCON0 ;SDRAMCON0 @ 2M ~ 18M
其他DRAM BANK地址范围设置为0 – 0, 也就是不使用
LDR r9, =rSDRAMCON1 ;SDRAMCON1 @ DISABLED
LDR r10,=rSDRAMCON2 ;SDRAMCON2 @ DISABLED
LDR r11,=rSDRAMCON3 ;SDRAMCON3 @ DISABLED
设置EXTERNAL I/O BANK的基地址为0X3600000,accessible to memory bank, enable DRAM refresh
0xCE278360=0b1100 1110 0010 0111 1000 0011 0110 0000
LDR r12,=rSREFEXTCON
将上面设置的值批量写入相应的寄存器
LDR r0, =ARM7_EXTDBWTH
STMIA r0, {r1-r12}
;Part 5
;***************************************************************
;Self copy from FLASH to SDRAM
第五部分:从FLASH 自拷贝到 SDRAM
将RO段基地址放入R0寄存器
LDR r0, =|Image$$RO$$Base|
将RO段结束地址放入R1寄存器
LDR r1, =|Image$$RO$$Limit|
将RW段基地址放入R2寄存器
LDR r2, =|Image$$RW$$Base|
将RW段结束地址放入R3寄存器
LDR r3, =|Image$$RW$$Limit|
计算出RO段的长度,并存入R1寄存器
SUB r1, r1, r0
计算出RW段的长度,并存入R3寄存器
SUB r3, r3, r2
计算出RO+RW段的长度,并存入R1寄存器
ADD r1, r1, r3
将目标空间的地址存入R2寄存器
LDR r2, =0x200000 ;@2M
开始拷贝工作
COPY
读出R0指向的内存地址的内容到R3,并将R0的值加4,指向下一个地址
LDR r3, [r0], #4
将R3的内容写入到R2指向的地址空间,并将R2的值加4,指向下一个地址
STR r3, [r2], #4
将R1的数值减区4
SUBS r1, r1, #4
如果R1的值不为0,表示还没拷贝完全,重复进行上面三步
BNE COPY
;Part 6
****************************************************************
;Remap the memory
; FLASH @ 16 ~ 18M
; SDRAM @ 0 ~ 16M
第六部分:内存重映射,设置内存地址空间,FLASH 设置在16 – 18M,数据宽度为8BIT,SDRAM 设置在0 – 2M,数据宽度为32BIT;
设置各内存的数据总线宽度
0X3001=0b 0000 0000 0000 0000 0011 0000 0000 0001
其中DSD0设为11,将SDRAM数据宽度设为32BIT
DSR0设为01,将FLASH数据宽度设为8BIT
LDR r1, =rEXTDBWTH_R ;EXTDBWTH
设置FLASH 的地址范围设为16M-18M,normal ROM 模式
0x12040060=0b0001 0010 0000 0100 0000 0000 0110 0000
LDR r2, =rROMCON0_R ;ROMCON0 @ 16M ~ 18M
其他ROM BANK的地址范围设为0 – 0,也就是不使用
LDR r3, =rROMCON1_R ;ROMCON1 @ DISABLED
LDR r4, =rROMCON2_R ;ROMCON1 @ DISABLED
LDR r5, =rROMCON3_R ;ROMCON1 @ DISABLED
LDR r6, =rROMCON4_R ;ROMCON1 @ DISABLED
LDR r7, =rROMCON5_R ;ROMCON1 @ DISABLED
设置SDRAM 的地址范围0M – 16M
0x10000380=0b 0001 0000 0000 0000 0000 0011 1000 0000
LDR r8, =rSDRAMCON0_R ;SDRAMCON0 @ 0M ~ 16M
其他DRAM BANK地址范围设置为0 – 0, 也就是不使用
LDR r9, =rSDRAMCON1_R ;SDRAMCON1 @ DISABLED
LDR r10,=rSDRAMCON2_R ;SDRAMCON2 @ DISABLED
LDR r11,=rSDRAMCON3_R ;SDRAMCON3 @ DISABLED
设置EXTERNAL I/O BANK的基地址为0X3600000,accessible to memory bank, enable DRAM refresh
0xCE278360=0b1100 1110 0010 0111 1000 0011 0110 0000
LDR r12,=rSREFEXTCON_R
将上面设置的值批量写入相应的寄存器
LDR r0, =ARM7_EXTDBWTH
STMIA r0, {r1-r12}
重映射完成,程序开始在SDRAM中运行
;Part 7
;*****************************************************************
; Copy RW & ZI to SDRAM
第七部分:拷贝RW段到执行地址,ZI段初始化为0
把RO段的结束地址放入R0寄存器
LDR r0, =|Image$$RO$$Limit|
把RW段的基地址放入R1寄存器
LDR r1, =|Image$$RW$$Base|
把ZI段的基地址放入R3寄存器
LDR r3, =|Image$$ZI$$Base|
比较R0与R1的值,若相等则RW段不需要搬移
CMP r0, r1
BEQ %1
若R0与R1的值不等,则进行RW段的搬移
比较R1与R3的值,若相等表明RW段已经搬移完成
0 CMP r1, r3 ; Copy init data
若R1
LDRCC r2, [r0], #4
若R1 STRCC r2, [r1], #4
比较R1与R3的值,若R1 BCC %0
把ZI段的结束地址放入R1寄存器
1 LDR r1, =|Image$$ZI$$Limit| ; Top of zero init segment
MOV r2, #0
给ZI段空间清0
2 CMP r3, r1 ; Zero init
若R3 STRCC r2, [r3], #4
若R3 BCC %2
;Part 8
;***********************************************************************
;Set stack pointer & jump to c function
第八部分:设置堆栈指针,然后程序跳往loadkernel执行;
给SP寄存器设置0X800000,也就是堆栈指针设为8M
LDR sp, =0x800000
导入loadkernel标号备用
IMPORT loadkernel
将loadkernel标号的地址值装入PC寄存器,也就是程序跳转到loadkernel执行
LDR pc, =loadkernel
END
第二部分 综合实验二驱动代码分析
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1.蜂鸣器驱动代码分析
/*
* beep_driver.c - beep driver ( low-level )
*
*/
包含头文件beep_driver.h
#include "beep_driver.h"
Open函数,将相应IO设置为输出态
/*
; hardware connection
; PIO16 (gpio)
; 1 (beep)
; so output value = 0x00010000 = (0b0000 0000 0000 0001 0000 0000 0000 0000)
*/
传入参数:无
传出参数:无
返回值:0
/* set beep related gpio */
int beep_open( void )
{
将与蜂鸣器相连的PIO16设为输出态
0x00010000 = 0b0000 0000 0000 0001 0000 0000 0000 0000
// set gpio's direction: set IOPMOD register mode bit to 1 = output
IOPMOD = IOPMOD | 0x00010000;
return 0;
}
Read函数,不做什么操作,返回count参数值
int beep_read( char * buf, int count )
{
// do nothing
return count;
}
write函数,将buf中的前count个数据逐个输出到IO口上
传入参数:buf, count
传出参数:无
返回值:count
/*
if buf[i] == 0 BEEP_OFF
else BEEP_ON
*/
int beep_write( char * buf, int count )
{
int i;
for( i = 0; i < count; i++ )
{
根据buf[i]的值设置IOPDATA寄存器,控制IO输出
if( buf[i] )
若buf[i]为1,输出高电平
IOPDATA = IOPDATA | 0x00010000;
Else
若buf[i]为0,输出低电平
IOPDATA = IOPDATA & (~0x00010000);
}
return count;
}
ioctl函数,不作任何操作,返回0
int beep_ioctl( unsigned int cmd, unsigned long arg )
{
// do nothing
return 0;
}
Release函数,不作任何操作,返回0
int beep_release( void )
{
// do nothing
return 0;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2.拨段开关驱动代码分析
/*
* dip4_driver.c - dip4 driver ( low-level )
*
*/
包含头文件dip4_driver.h
#include "dip4_driver.h"
Open函数,将相应IO设置为输入态
/*
; hardware connection
; PIO0 PIO1 PIO2 PIO3 (gpio)
; 1 2 3 4 (dip4)
; so output value = 0x0000000f = (0b0000 0000 0000 0000 0000 0000 0000 1111)
*/
传入参数:无
传出参数:无
返回值:0
/* set dip4 related gpio */
int dip4_open( void )
{
将PIO0 PIO1 PIO2 PIO3设置为输入态
~0x0000000f = 0b1111 1111 1111 1111 1111 1111 1111 0000
// set gpio's direction: set IOPMOD register mode bit to 0 = input
IOPMOD = IOPMOD & (~0x0000000F);
return 0;
}
Read函数,将4为IO的值读入到buf中
传入参数:buf, count
传出参数:buf
返回值:count,错误返回-1
int dip4_read( char * buf, int count )
{
int i = 0;
int dip4_value;
若count超出范围,返回-1,表示出错
// the count has exceeds the count of our board
if( count > DIP4_NUM )
return -1;
从IOPDATA的低4位读取数据
// get low-4-bits of IOPDATA
dip4_value = IOPDATA & 0x0F;
将每位的状态依次保存到 buf中
for( i = 0; i < count; i++ )
buf[i] = (dip4_value & ( 1 << i ))? 1 : 0;
return count;
}
write函数,不做什么操作,返回count参数值
int dip4_write( char * buf, int count )
{
// do nothing
return count;
}
ioctrl函数,不做什么操作,返回0
int dip4_ioctl( unsigned int cmd, unsigned long arg )
{
// do nothing
return 0;
}
release函数,不做什么操作,返回0
int dip4_release( void )
{
// do nothing
return 0;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3.按钮中断驱动代码分析
/*
* int0_driver.c - int0 driver ( low-level )
*
*/
包含头文件
#include "int0_driver.h"
#include "led_api.h"
Open函数,将PIO8设为输入态
/*
; hardware connection
; PIO8 (gpio)
; 1 (int0)
; so output value = 0x00000100 = (0b0000 0000 0000 0000 0000 0001 0000 0000)
*/
传入参数:无
传出参数:无
返回值:0
/* set int0 related gpio */
int int0_open( void )
{
将PIO8设为输入态
0x00000100 = 0b0000 0000 0000 0000 0000 0001 0000 0000
// set gpio's direction: set IOPMOD register mode bit to 0 = input
IOPMOD = IOPMOD & (~0x00000100);
设置INTMSK寄存器,将0位及21位清0,打开中断
// unmask the switch interrupt ...........
INTMSK &= ~((1<<21) | (1<<0));
return 0;
}
read函数,不做什么操作,返回count参数值
int int0_read( char * buf, int count )
{
// do nothing
return count;
}
write函数,不做什么操作,返回count参数值
int int0_write( char * buf, int count )
{
// do nothing
return count;
}
Ioctl函数,对中断相关寄存器作一些控制操作
传入参数:cmd, arg
传出参数:无
返回值:0
int int0_ioctl( unsigned int cmd, unsigned long arg )
{
switch( cmd )
{
打开PIO8中断使能
// Enable interrupt request and Unmask PIO8 interrupt
case INT0_ENABLE_INTERRUPT:
IOPCON |= INT0_IO_ENABLE;
break;
给INTPND相应位写1清除中断标志
// clear int 0 pending interrupts
case INT0_CLEAR_INTERRUPT:
INTPND |= INT0_MASK;
break;
设置INT0为上升边沿触发中断
// set rising edge interrupt
case INT0_RISING_EDGE_INTERRUPT:
IOPCON |= INT0_IO_RISING_EDGE;
break;
设置INT0为下降边沿触发中断
// set falling edge interrupt
case INT0_FALLING_EDGE_INTERRUPT:
IOPCON |= INT0_IO_FALLING_EDGE;
break;
设置INT0为上升及下降边沿触发中断
// set both edge interrupt
case INT0_BOTH_EDGE_INTERRUPT:
IOPCON |= INT0_IO_BOTH_EDGE;
break;
设置INT0为active high模式
// set as active high
case INT0_ACTIVE_HIGH:
IOPCON |= INT0_IO_ACTIVE_HIGH;
break;
default:
break;
}
return 0;
}
release函数,不做什么操作,返回0
int int0_release( void )
{
// do nothing
return 0;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4.发光二级管驱动代码分析
/*
* led_driver.c - led driver ( low-level )
*
*/
包含头文件
#include "led_driver.h"
定义静态数组用于保存各个LED的开关状态
static char led_status[LED_NUM];
open函数,设置相应位为输出态,并设初始值为0,给相应状态数组清0;
传入参数:无
传出参数:无
返回值:0
/* set led related gpio */
int led_open( void )
{
/*
; hardware connection
; IO17 IO04 IO05 IO06 (gpio)
; D6 D7 D8 D9 (led)
; so output value = 0x00020070 = (0b0000 0000 0000 0010 0000 0000 0111 0000)
*/
unsigned int * IOPMOD = (unsigned int *)0x03FF5000;
unsigned int * IOPDATA = (unsigned int *)0x03FF5008;
int i;
// set IOPMOD register mode bit to 1 = output ( refer to um_s3c4510b_rev1.pdf , page 12-2)
*IOPMOD = *IOPMOD | 0x00020070;
// set IOPDATA register bit to 0 , initial led status = ALL_OFF
*IOPDATA = *IOPDATA & (~0x00020070);
for( i = 0; i < LED_NUM; i++ )
led_status[i] = 0;
return 0;
}
Read函数,从状态数组中读出各位状态到buf
传入参数:buf, count
传出参数:buf
返回值:count, 错误返回-1
int led_read( char * buf, int count )
{
int i = 0;
// the count has exceeds the count of our board
if( count > LED_NUM )
return -1;
for( i = 0; i < count; i++ )
buf[i] = led_status[i];
return count;
}
Write函数,将buf中的数据输出到相应的IO位上面,并设置相应的状态数组位
传入参数:buf, count
传出参数:无
返回值:count,错误返回-1
int led_write( char * buf, int count )
{
int i = 0;
unsigned int * IOPDATA = (unsigned int *)0x03FF5008;
// the count has exceeds the count of our board
if( count > LED_NUM )
return -1;
for( i = 0; i < count; i++ )
{
// save the write value for led_read
led_status[i] = buf[i];
// set IOPDATA register
switch (i)
{
case 0:
// buf[0] = IO 6
*IOPDATA = buf[i]? (*IOPDATA | 0x00000040) : (*IOPDATA & (~0x00000040));
break;
case 1:
// buf[1] = IO 5
*IOPDATA = buf[i]? (*IOPDATA | 0x00000020) : (*IOPDATA & (~0x00000020));
break;
case 2:
// buf[2] = IO 4
*IOPDATA = buf[i]? (*IOPDATA | 0x00000010) : (*IOPDATA & (~0x00000010));
break;
case 3:
// buf[3] = IO 17
*IOPDATA = buf[i]? (*IOPDATA | 0x00020000) : (*IOPDATA & (~0x00020000));
break;
default:
break;
}
}
return count;
}
ioctl函数,不做什么操作,返回0
int led_ioctl( unsigned int cmd, unsigned long arg )
{
// do nothing
return 0;
}
release函数,不做什么操作,返回0
int led_release( void )
{
// do nothing
return 0;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5.七段数码管驱动代码分析
/*
* seg7_driver.c - seg7 driver ( low-level )
*
*/
包含头文件
#include "seg7_driver.h"
open函数,不做什么操作,返回0
/* set seg7 related gpio */
int seg7_open( void )
{
// do nothing
return 0;
}
read函数,不做什么操作,返回count参数值
int seg7_read( char * buf, int count )
{
// do nothing
return count;
}
Write函数,将buf中传入的数据对应各段显示出来
传入参数:buf, count
传出参数:无
返回值:count,错误返回-1
int seg7_write( char * buf, int count )
{
int i = 0;
int seg7_value = 0;
若大于显示范围返回-1,表示出错
// the count has exceeds the count of seg7
if( count > SEG7_NUM )
return -1;
将buf中的各个数据合并为单个显示数据
for( i = 0; i < count; i++ )
seg7_value = seg7_value | (buf[i]? ( 1 << i ) : 0) ;
往0x03fdc000写显示数据,数码管作相应显示 //允许往0x03fdc000 - 0x03fe0000范围写
由于写入地址范围正好是external i/o bank3所在地址范围,因而使得necs3片选脚使能;
该设置使得external i/o bank0基地址为0X3FD0000
// write the value to 7 segment leds
SEG7 = seg7_value;
return count;
}
ioctl函数,不做什么操作,返回0
int seg7_ioctl( unsigned int cmd, unsigned long arg )
{
// do nothing
return 0;
}
release函数,不做什么操作,返回0
int seg7_release( void )
{
// do nothing
return 0;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6.定时器中断驱动代码分析
/*
* timer_driver.c - timer_0 driver ( low-level )
*
*/
包含头文件
#include "timer_driver.h"
#include "led_api.h"
Open函数,清楚中断标志,打开定时器
传入参数:无
传出参数:无
返回值:0
/* set timer related gpio */
int timer_open( void )
{
关闭定时器
// disable timer_0
TMOD = 0;
清除中断标志
// Clear pending interrupts
INTPND = 0x00000000; ?应该是0xFFFFFFFF
打开定时器
// enable timer 0
TMOD = 1;
return 0;
}
read函数,不做什么操作,返回count参数值
int timer_read( char * buf, int count )
{
// do nothing
return count;
}
write函数,不做什么操作,返回count参数值
int timer_write( char * buf, int count )
{
return count;
}
Ioctl函数,对定时器进行各项功能设置
传入参数:cmd, arg
传出参数:无
返回值:0
int timer_ioctl( unsigned int cmd, unsigned long arg )
{
switch( cmd )
{
用arg值设置定时器的中断溢出时间
// set interrupt counter
case TIMER_SET_COUNTER:
TDATA0 = *(unsigned int *)arg;
break;
打开INTMSK中相应的中断使能位
// Enable interrupt request and Unmask timer_0 interrupt
case TIMER_ENABLE_INTERRUPT:
INTMSK &= ~((1 << 21) | (1 <<10) );
break;
给INTPND相应位写1清除中断标志
// clear timer 0 pending interrupts
case TIMER_CLEAR_INTERRUPT:
INTPND |= 1 << 10;
default:
break;
}
// do nothing
return 0;
}
release函数,不做什么操作,返回0
int timer_release( void )
{
// do nothing
return 0;
}
信息点滴:
sudo aptitude remove softname -purge 删除配置文件
char buf[10] = "hello"; //内容可修改
strcpy( buf, "china" ); //给数组赋值
开源软件
想象力比知识更重要
windows下拷贝长文件名, 在浏览器地址框里拷贝下地址
全局变量, main中定义, 其他要用的c文件用extern引用;
nm查看, objdump -c 查看反汇编
超级终端无法通讯有可能是xp中有个ups进程需要关闭;
linux中如何局部放大屏幕???
对一个概念的学习: 什么是它?为什么要有它?怎么用它?
ext2ifs_1_10c. rar 在win下读分区
word: 插入->引用->目录及索引/可设置自动目录;
9.15是软件自由日;
对于问题: 罗列可能性, 逐条验证, 减少重复绕弯;
调汇编: 看代码, 断点, 点灯
调C: 条件编译, 断言, 断点, 出入口printf
rtlinux被windriver风河收购;
vxworks->Toruado开发工具->RMB50W
BSP板级支持包;
MIPS 百万指令/秒
手机中操作系统: sybian: Nokia /Wince: 高端,界面 /Linux: Moto,低端应用
SKYEYE MINIGUI有一定国际影响力的开源软件;
lisoleg -> linux source learn group //zhangfeng | laotie
lwip ->轻量级IP协议栈
龙芯电脑-mips-linux-gcc
常用的波特率: 9600 19200 115200
服务比实际产品更挣钱;