-
Notifications
You must be signed in to change notification settings - Fork 36
Home
Welcome to the LASO wiki!
You can see free ebook about ARM Development of my work at http://www.lumit.org
《源码开放学ARM》 电子书 Learn ARM with Source Open http://www.lumit.org/LASO
- 如何在ubuntu下搭建开发环境
How to build dev environment on ubuntu - 如何实现SD卡启动第一个闪灯程序
How to blink led on tiny210 board - 如何实现时钟配置和串口输出字符
How to make uart putchar using SDBOOT
- 移植 lumit Bootloader 到 Tiny210 上获得初步成功!
可以支持类似 uboot 的 md / mw 命令 (查看修改内存)
可以支持 loadb / loadx / go 命令 (下载bin文件/xmodem协议/执行bin程序)
可以支持nand read / write 命令 (read 无问题, write 还在调试) - 下一步计划尝试 DDR2 SDRAM 的初始化
-
创建了 ARM-Codes/tiny210-linux-codes 目录,上传了相关代码。
https://github.com/limingth/ARM-Codes/tree/master/tiny210-linux-codes -
tiny210 DDR2 SDRAM 已经初始化成功,是从 uboot 中找到的初始化代码 mem_setup.S
目前实现从 NandFlash 4M 位置处读出 Linux Kernel ,并启动输出 Uncompressing Linux... done, booting the kernel. 应该还需要给 Kernel 传递参数就可以自己来启动 kernel 了
How to boot linux kernel from nand flash
- 借鉴 s3c2440 启动 Linux 的参数和数据结构,完成了启动 linux kernel 的功能,增加了 bootm 命令。
根据经验,Linux 的加载和启动地址放到了 SDRAM + 0x8000 的地方
#define LINUX_BOOT_ADDR 0x20008000
根据 http://blog.csdn.net/liukun321/article/details/7383669 ,tiny210 的 mach type id 设为 3466
#define MACH_TYPE_TINY210 3466
How to boot linux kernel from nand flash - 代码已整理上传至 https://github.com/limingth/ARM-Codes/tree/master/tiny210-linux-codes/9-linux-demo
- 中断代码移植成功!
可以通过tiny210 开发板的 K1 按键 (左上角BACK键) 的 falling edge 触发中断,IRQ handler 输出 '+' 表示中断处理完毕。
代码已上传至
https://github.com/limingth/ARM-Codes/tree/master/tiny210-linux-codes/app1-EINT-demo
中断理论可参考
http://www.lumit.org/LASO/zh/chp9-4.html
在 armcc 中的内嵌汇编语法不能支持,需要移植到 start.s 汇编中。
这个代码的 bin 文件,需要依靠 bootloader 下载到开发板的 0x21000000 之后,通过 go 0x21000000 执行。
How to enable Interrupt handler with K1 button - 定时器中断代码移植成功!
每隔 1s 进行一次 beep ,同时输出 '+' 。定时器外部时钟 PCLK_PSYS 为 66Mhz,中断源 Timer0 为 VIC0 21号。
代码已上传至
https://github.com/limingth/ARM-Codes/tree/master/tiny210-linux-codes/app2-timer-demo
- LCD 驱动代码移植成功!
代码已上传至
https://github.com/limingth/ARM-Codes/tree/master/tiny210-linux-codes/app3-lcd-demo
LCD 驱动原理简单说明 How to init LCD and draw lines - 实现了一个 Linux 下的寄存器值查看器,方便了解 Linux 对 SFR 寄存器的配置值。
How to get the Value of SFR after Linux booting
- 开始调试 audio(IIC/IIS/WM8960) 驱动,争取实现 wav 播放
-
查了 N 多资料,终于解决了 audio wm8960 播放出声音的问题,用 wav 文件测试,基本能听出音乐来,但还需要优化。
下面是网上找到的一些比较好的资料:
http://xboot.org/forum.php?mod=viewthread&tid=3074&page=1&authorid=490
http://xboot.org/thread-3074-1-1.html http://code.google.com/p/maxwit/ http://read.pudn.com/downloads138/sourcecode/embed/594016/44b0/123.c__.htm http://www.sectop.com/post/86.html http://www.sectop.com/post/94.html http://www.52rd.com/Blog/Detail_RD.Blog_hecrics_4314.html http://www.diybl.com/course/6_system/linux/Linuxjs/20100116/191743.html http://blog.chinaunix.net/uid-22950545-id-2600582.html http://www.docin.com/p-259094649.html http://wenku.baidu.com/view/755f4c69561252d380eb6ebf.html (检测耳机插拔) -
最后解决问题的关键还是在于 IIS 寄存器的配置,之前用的参数是 linux 启动之后的值。详见
https://github.com/limingth/LASO/wiki/8-How-to-init-IIS-and-IIC-to-make-wm8960-chip-play-wav-file
后来经过测试,发现 linux 启动的 IIS 配置,clock 实际上是不对的,需要运行一个音视频程序之后的值,才是对的。
据高人指点,说这样的设计,是为了在平时不播放音频的时候,降低 clock 可以省电。
-
昨晚跑通的程序,白天起来再运行就挂了。 但如果用 linux 下的程序再跑一遍,然后 reset 板子,再运行就又能成功。
推测大概是因为 wm8960 芯片被 linux 初始化过之后,能够正常工作了。 reset 板子并没有 reset wm8960,因此程序才能成功。
于是继续研究 wm8960 芯片的内部寄存器的设置,同时参考了 高人提供给我的 wm8976 芯片的初始化配置值,进行类比替换。
通过上面的调试方法,把对播放有用的寄存器再自己重新设置一遍,终于最后能够自己初始化 wm8960 芯片并播放声音了。 -
结论:wm89xx 之类的芯片,本身 reset 之后,寄存器的默认值是不能工作的。
初始化内部寄存器,需用通过 IIC 总线,实现一个 IIC_write(chip_addr, reg_addr, reg_data) 函数。
内部寄存器中,必须要设置的寄存器包括 reset, power, clock, mute, audio interface, volume, mixer control 这些。 -
测试:Windows-XP-启动-862K.wav 下载到 0x22000000,用 IIS 的 polling 方式,发送音频数据,音乐播放成功!
-
代码已上传至 https://github.com/limingth/ARM-Codes/blob/master/tiny210-linux-codes/app4-audio-demo/
下一步计划调试 触摸屏驱动,SD/MMC 控制器,USB 控制器,争取实现读取 SD 卡 和 u盘的 FAT 文件系统。
- 开始移植 SD 卡驱动代码。 创建 wiki A How to init SD card and read sd file of FAT fs
- 基本实现读取 SD 卡上的 FAT32 文件系统。 fat.c 移植于 uboot 中的实现, sdhc.c 移植于 6410 开发板裸板的 sd 卡驱动。 移植需要解决的关键问题是需要得到 SD block 0 在偏移 0x1C6 到 0x1C9 这 4 个字节的偏移量 part_offset 。 ( 一个本来无关紧要的小bug,耽误了最开始的2天时间。看来以后日志还是要多写,以免做到后面忘记了前面做过的改动。)
- 现在是通过 autocmd 来进行加电后的自动启动 (显示bmp图片和播放wav音乐)。 char * autocmd[] = {"sdload tian.bmp 0x21800000", "draw 0x21800000", "sdload today.wav 0x23000000", "play 0x23000000"};
- 目前对bmp和wav文件的解析只是简单用了一下数据的偏移量 offset ,没有对文件头进行解析,留待以后再完善了。 添加了一个 boot.ini 文件,为了以后能够和友善之臂的 FriendlyARM.ini 兼容,但还没有具体实现。
dm9000 驱动参考 http://www.cnblogs.com/timkyle/archive/2012/04/04/2412637.html
- 解决了 LCD 驱动闪烁的问题,原因是 clock source 的选择不对,VIDCON0 寄存器差了一个 bit CLKSEL_F [2] Selects the video clock source. linux 下的配置是用 1 = SCLK_FIMD 改成 0 = HCLK 就成功了,不再闪烁。
- 解决了 LCD 驱动中 Framebuffer 里面 4个字节交换 SWAP 的问题,原因是设置 WINCON0 寄存器差了一个 bit WSWP_F [15] Specifies the Word swap control bit. 默认 0 = Swap Disable 修改为 1 = Swap Enable 就成功了。
- 更新后的 LCD 驱动 demo 程序上传至 https://github.com/limingth/ARM-Codes/tree/master/tiny210-linux-codes/app3-lcd-demo
- https://github.com/limingth/ARM-Codes/tree/master/tiny210-linux-codes/b-superboot-demo 可以实现加电后的自启动 BL1 是 b-superboot-demo.bin; BL2 是 bootloader/bootloader.bin make b 可以将这2个bin文件烧写到 SD卡上,分别写入 block 1 和 block 0x1DC000 两个位置。 BL1 实现把 BL2 加载到 0x20A00000 位置处,然后跳转到 0x20A00000 ,然后执行 BL2 (0x20A00000 是基于 linux 内核会被加载到 0x20008000 位置,长度为 8M 字节,因此需要留出足够空间) BL2 实现 3 秒内用户按键进入 shell 中,进行命令操作。 3 秒内无用户按键则进入到 autocmd 方式自动执行命令。
- 完成了对 boot.ini 的解析,能够实现 SD 卡 bin 文件的自动加载执行。初步模拟实现了 superboot.bin 的类似功能。
- 新增了几个 demo 程序,完成了从 SD 卡读取 wav 和 bmp 文件的功能。
app5-sd-demo https://github.com/limingth/ARM-Codes/tree/master/tiny210-linux-codes/app5-sd-demo
app6-sd-fat-demo https://github.com/limingth/ARM-Codes/tree/master/tiny210-linux-codes/app6-sd-fat-demo
app7-sd-fat-lcd-demo https://github.com/limingth/ARM-Codes/tree/master/tiny210-linux-codes/app7-sd-fat-lcd-demo
app8-sd-fat-audio-demo https://github.com/limingth/ARM-Codes/tree/master/tiny210-linux-codes/app8-sd-fat-audio-demo
app9-sd-fat-lcd-audio-demo https://github.com/limingth/ARM-Codes/tree/master/tiny210-linux-codes/app9-sd-fat-lcd-audio-demo
- 完成 prj1-dpf-basic 和 prj2-dpf-timer 两个demo程序。
- 开始研究 pl330 dmac 的驱动实现。
- 尝试移植 linux 源码中的 pl330.c
- setup prj3-dpf-dma
-
DMA memtomem 单次传输成功。
PL330 的DMA驱动和以往驱动的不同之处:
s3c2440/s3c6410 处理器内部的 DMA 都是提供特殊功能寄存器 SFR 对 DMA 进行编程,但 PL330 不是这样。
PL330 DMA 的基本工作原理是:
a) DMA 有自己的特殊指令集,基本是1-6个字节不定长,主要有 DMAMOV/DMALD/DMAST/DMAGO
b) DMA 的驱动主要包含两个工作:DMAGO 指令的本身的执行,是通过写 S5PV210 芯片的 DBGCMD/DBGINST0/DBGINST1 这3个寄存器实现的。
c) linux 下的 pl330.c 是可以参考使用的驱动,主要包含了一系列 _emit_MOV/_emit_LD/_emit_ST 等类似指令的接口。
这些接口完成类似编译器的工作,把一个DMA操作函数,转换为存放在 buf 数组里面的二进制指令。
d) 驱动编程的关键在于形成 buf 内部的正确机器指令,然后通过对 DBGCMD/DBGINST0/DBGINST1 这3个寄存器进行编程,完成跳转到 buf 执行指令。 -
DMALP/DMALPEND 还未成功,仍在调试
- DMALP/DMALPEND 在 memtomem 传输实验成功,可以完成 256 字节以内的循环复制功能。
- 开始尝试 memtodev 的传输,通过 Mem -> Uart 进行测试
-
连续几天都没有进展,终于今天获得了成功。 Mem -> Uart 调试出来了。 简单说一下,PL330 分为2组 interface: secure 和 no-secure 。 前者用于 memtomem,后者用于 memtodev。 2组 interface 对应于 2组 SFR,首地址分别为 0xfa200000 和 0xe0900000 ,因此用于执行 binary code 的 DBGCMD 寄存器也不一样。 之前一直没调出来,就是这里的问题。
-
代码中增添了 tzpc.S 用于进行 tzpc_init 初始化,这是因为 UART 需要用到 tzpc2
-
PL330 指令为不定长指令,共20条,常用的就是 MOV, LD/LDP, ST/STP, LP/LPEND, FLUSHP, SEV, END, NOP, GO 这几条。
BC 01 01 0A 80 02,
35 08,
BC 00 00 00 00 20,
BC 02 20 00 90 E2,
20 03, 30 08, 04,
29 08,
35 08,
39 07,
34 50,
00这段代码是通过 DMA 将源地址0x20000000的4字节数据发送到串口UTXH寄存器 (0xE2900020)
- tiny210 裸机版数码相框基本调试成功,加电后从SD卡启动,读取 boot.ini 配置文件,前台程序循环播放 wav 背景音乐,后台定时器中断每隔2秒启动一次 DMA mem传输到LCD 帧缓冲 fb_addr,用来显示 bmp 图像文件。使用 DMA 后效果改进明显,两幅图片切换时,声音播放连续流畅,完全没有停顿现象。
- 赶在父亲节完成了一个可以让自己基本满意的数码相框功能。测试了一下,循环播放3首wav歌曲,显示7张bmp图片,程序运行稳定,而且改进了 DMA 的指令,从一层循环指令变成两层循环指令,这样使得中断handler中生成DMA指令buf的时间延迟显著减少。
- 代码下载 https://github.com/limingth/ARM-Codes/tree/master/tiny210-linux-codes/prj3-dpf-dma
- 下一步计划,实现 jpeg 图片解码功能,实现 hdmi 高清显示接口,能够通过家里的液晶电视浏览数码相机上的图片。
-
开始调试 JPEG 图片显示功能,参考资料 http://blog.csdn.net/skykill2000/article/details/6192313
http://blog.csdn.net/yuyin86/article/details/6148652 -
关于 YUV -> RGB YUV 4 2 0 yuv: 0xFF 4C 55 4C mem: 4C 55 4C FF
(4C, 55, FF)
(4C, 55, FF)
y = 0x4c u = 0x55 v = 0xff
r = 76 + 1.4 * (0xFF-128) = 76 + 177.8 = 253.8
g = 76 - 0.344 * (0x55 - 128) - 0.71414 * (0xFF-128) = 76 - 0.344 * (-43) - 0.71414 * (127) = 76 + 14.792 - 90.69 = 0
b = 76 + 1.772 * (0x55-128) = 76 + 1.772 * (-43) = 76 - 76 = 0
- JPEG图片解码功能基本调出来了,能够显示 YUV420 格式的RawData
- 测试了一下 iphone4s 拍摄的 JPEG 图片(3264x2448) 显示基本正常,需要做一个显示比例(480x272)的像素映射。
- 目前是用软件把 yuv 转换成 rgb 显示的,不过 LCD 应该可以支持 yuv 直接显示,但这个驱动暂时没继续调下去了。
- 开始调试 HDMI 接口。关于 HDMI 的参考阅读资料和相关笔记见 [https://github.com/limingth/LASO/wiki/about-HDMI]
-
暂停 HDMI 接口调试,开始准备 tiny210 上 Linux 设备驱动课程。
-
驱动调试笔记
ldd-1 搭建开发环境
https://github.com/limingth/LASO/wiki/LDD-1-How-to-build-Linux-Device-Driver-dev-environmentldd-2 编译内核模块
https://github.com/limingth/LASO/wiki/LDD-2-How-to-write-kernel-module-and-compile-itldd-3 设备驱动框架
https://github.com/limingth/LASO/wiki/LDD-3-How-to-write-linux-device-driver-and-test-it
-
调试移植 按键驱动,串口驱动和带有中断功能的驱动
ldd-4 设备驱动相关概念
https://github.com/limingth/LASO/wiki/LDD-4-Linux-Device-Driver-Basicsldd-5 字符设备驱动
https://github.com/limingth/LASO/wiki/LDD-5-How-to-write-char-dev-driver-with-file_operationsldd-6 中断处理 (GPIO & UART)
https://github.com/limingth/LASO/wiki/LDD-6-How-to-write-driver-with-interrupt-enabled
https://github.com/limingth/LASO/wiki/LDD-7-How-to-write-gpio-button-interrupt-driver
https://github.com/limingth/LASO/wiki/LDD-8-How-to-write-uart-interrupt-driver
- 移植 DM9000.c 网卡驱动初步成功
- 开始着手简化 DM9000 驱动代码。
- linux 下的 DM9000.c 原理图和代码分析出来了,DM9000 的读写地址为 0x88000000 和 0x88000004
详见 arm9.net 论坛的帖子: http://www.arm9home.net/read.php?tid-18616.html - 裸机版 DM9000 网卡驱动移植成功,可以实现一个 arp 包的发送和接收
- 开始系统更新 LASO 电子书。 http://www.lumit.org/LASO/