s3c2440串口裸板驱动(使用fifo)
使用fifo的好处有:
1:串口的数据发送的数据量较大时,使用fifo可以大大降低MCU的开销。(有点类似串入并出的cput处理模型,本质上还是串行收发)
2:在某些特殊场合,例如制定较复杂的协议时,可以使用fifo特性来做协议简化,比如一包
数据包含8个字节,(并且fifo设置的长度为8),这样相当于把uart转换为类似CAN/以太网模型,
这样信息可扩展性得到了质的提高,当然,这里需要同步协调。
fifo分析拓展:
1. 如果要用中断来处理接收到的数据,就是说,接收完数据然后产生中断,再于中断里处理接收的数据。如果要实现这个本意,要设置好触发点。
至于超时中断之类,那是另外一回事了。
2. 就UART的中断类型而言,还包括:RBR中断使能、THRE中断使能、RX线状态中断使能、自动波特率超时中断使能等。
3. FIFO定义说了,先入先出缓冲区,在UART中有什么用呢。我们可以用它来批量发送 数据(而非FIFO模式,只能一字节一字节的发,而且发每个字节都需要等待缓冲区变空才能发送下一字节),这样能在一定程度上提高数据发送速度。还有就是 避免数据包的的丢失(这个问题,目前还没体会)。
需要了解的相关知识:
HCLK主要为S3C2440 AHB总线(Advanced High performance Bus)上挂接硬件提供工作频率,AHB总线主要挂接有内存,NAND,LCD控制器等硬件
FCLK主要为ARM920T内核提供工作频率;
PCLK主要为APB总线提供工作频率,APB总线主要挂接UART串口,Watchdog等硬件控制器。【所以在这里我们用PCLK作为UART的时钟源】
外接设备 |
起始地址 |
结束地址 |
存储控制器 |
0x48000000 |
0x48000030 |
USB Host控制器 |
0x49000000 |
0x49000058 |
中断控制器 |
0x4A000000 |
0x4A00001C |
DMA |
0x4B000000 |
0x4B0000E0 |
时钟和电源管理 |
0x4C000000 |
0x4C000014 |
LCD控制器 |
0x4D000000 |
0x4D000060 |
NAND FLASH控制器 |
0x4E000000 |
0x4E000014 |
摄像头接口 |
0x4F000000 |
0x4F0000A0 |
UART |
0x50000000 |
0x50008028 |
脉宽调制计时器 |
0x51000000 |
0x51000040 |
USB设备 |
0x52000140 |
0x5200026F |
WATCHDOG计时器 |
0x53000000 |
0x53000008 |
IIC控制器 |
0x54000000 |
0x5400000C |
IIS控制器 |
0x55000000 |
0x55000012 |
I/O端口 |
0x56000000 |
0x560000B0 |
实时时钟RTC |
0x57000040 |
0x5700008B |
A/D转换器 |
0x58000000 |
0x58000010 |
SPI |
0x59000000 |
0x59000034 |
SD接口 |
0x5A000000 |
0x5A000040 |
AC97音频编码接口 |
0x5B000000 |
0x5B00001C |
在start.s中完成对看门狗,内存等进行初始化:
GPBCON EQU 0x56000010
GPBDAT EQU 0x56000014
AREA Init,CODE,READONLY //声明一个只读性质的代码段Init.
ENTRY //入口
start
close watchdog
ldr r0,=0x53000000; //将看门狗控制寄存器地址放入r0
mov r1,#0
str r1,[r0]; //将r1的值0放到r0中,即设置看门/
狗控制寄存器的值为0
bl initmem; //跳转到initmem代码段,初始化内存
IMPORT main; //引入main.c中的main函数
ldr sp,=0x34000000; //调用c程序前先初始化桟指针
ldr lr,=loop; //设置main函数的返回地址
ldr pc,=main; //跳转到c程序的main函数的入口处执行
loop
b loop ; //死循环
initmen //内存初始化
ldr r0,=0x48000000; //加载内存相关寄存器首地址r0
ldr r1,=0x48000034; //加载内存相关寄存器尾地址到r1
adr r2,memdata; //将寄存器配置数据地址段首地址加载到r2
initmemloop
ldr r3,[r2],#4; //循环设置存寄存器
str r3,[r0],#4
teq r0,r1
bne initmemloop; //循环到最后一个寄存器时退出函数
mov pc,lr
memdata // 存放内存控制器设置数据
DCD 0x22000000 ;BWSCON
DCD 0x00000700 ;BANKCON0
DCD 0x00000700 ;BANKCON1
DCD 0x00000700 ;BANKCON2
DCD 0x00000700 ;BANKCON3
DCD 0x00000700 ;BANKCON4
DCD 0x00000700 ;BANKCON5
DCD 0x00018005 ;BANKCON6
DCD 0x00018005 ;BANKCON7
DCD 0x008e07a3 ;REFRESH
DCD 0x000000b1 ;BANKSIZE
DCD 0x00000030 ;MRSRB6
DCD 0x00000030 ;MRSRB7
END
在uart.c中:
#define GPHCON (*(volitile unsigned long *)0X56000070)
#define GPHDAT (*(volitile unsigned long *)0X56000074)
#define GPHUP (*(volitile unsigned long *)0X56000078)
#define UFCON0 (*(volitile unsigned long *)0x50000008)
#define UMCON0 (*(volitile unsigned long *)0X5000000C)
#define UCON0 (*(volitile unsigned long *)0X50000004)
#define ULCON0 (*(volitile unsigned long *)0X50000000)
#define UART_CLK PCKL //UART0的时钟源为PCLK
#define UART_BAUD_DATE 115200 //波特率
#define UART_BRD ((UART_CLK/(UART_BAUD_DATE*16))-1)
void uart_init(void)
{
UFCON0=0xbf; //使用fifo(发送fifo和接收fifo的触发深度都为32字节)【在中断模式下的fifo要设置触发方式(超时触发或字节触发)】
UMCON0=0x00; //不使用流控
UBRDIV0=UART_BRD; //波特率为115200
GPHCON |=0xa0; //GPH2,GPH3用作TXD0,RXD0
GPHUP=0x0c; //GPH2,GPH3内部上拉
UCON0=0X05 //时钟源为PCKL
ULCON0 &=0X03; //正常模式,数据格式:8个数据位,没有流控,1个数据位
}
当发送缓冲区里有数据需要传送时,我们就需要中断,来完成发送数据的任务。这个中断的产生,是由 s3c24xx_serial_start_tx()函数来完成的,具体来说,是它所调用的一个是中断使能的函数 enable_irq(TX_IRQ(port))来完成的。而此中断一旦使能,就会调用该中断的服务函数 s3c24xx_serial_tx_chars()去做后续的工作。
其次,在响应函数中,要注意检测TxFIFO是否已满。
发 送FIFO,是串口传送数据非常重要的机制。相当于提供了一个发送前的缓冲区,给我们的发送工作的多样化的处理带来了可能。我们的中断响应函数需要把数据 从发送缓冲区先搬送到TxFIFO中,但搬送之前需要做的工作就是判断FIFO是不是已经满了,如果已经满了,就不能再往里放数据了。
再次,在响应函数中,要注意检测传送缓冲区是否已空。
这一点也很重要,我们要发送的数据来源于数据缓冲区,如果该缓冲区的数据是空的,那我们就不需要去传送了。
最后,如何做到连续不断地传送数据。
我们从数据缓冲区里把数据传到TxFIFO中,要想持续地传送数据,很显然还需要有人往数据缓冲区里不断地放入新的数据。
void putc(unsigned char c)
{
while(UFSTAT0 & (UFSTAT0=0<<14))
{
UTXH0=C;
}
unsigined char getc(void)
{
while(UFSTAT0 &(UFSTAT0=0<<6))
{
return URXH0;
}
在main.c中:
#include "start.s"
#include "uart.h"
int main()
{
unsigned char c;
uart_init();
while(1)
{
c=getc();
if(isDigit(c)||isLetter(c))
putc(c);
return 0;
}
用FIFO发送数据时,若所用为轮询法(用在非高速场合,高速场合最好用BDMA或中 断法,故此轮询法很少用)需要保证接受FIFO不溢出,类似中断法,通过软件来设置触发条件。例如 if(rUFSTAT0&0x000f>0x0008)触发读为FIFO内有8字节数据。但是我们同时还要考虑,不能空读接收FIFO,例 如while((rUFSTAT0&0x000F)>0x0000){ 读接收FIFO}。这种轮询法比较山寨,稳定性不咋地,适用低速。不提倡使用。
s3c2440串口裸板驱动(使用fifo)的更多相关文章
- 裸板驱动总结(makefile+lds链接脚本+裸板调试)
在裸板2440中,当我们使用nand启动时,2440会自动将前4k字节复制到内部sram中,如下图所示: 然而此时的SDRAM.nandflash的控制时序等都还没初始化,所以我们就只能使用前0~40 ...
- arm裸板驱动总结(makefile+lds链接脚本+裸板调试)
在裸板2440中,当我们使用nand启动时,2440会自动将前4k字节复制到内部sram中,如下图所示: 然而此时的SDRAM.nandflash的控制时序等都还没初始化,所以我们就只能使用前0~40 ...
- S5PV210裸板驱动:启动
以往2440和6410的启动方式,只要我们把裸板代码烧写到NAND FLASH的开始位置,当开发板上点启动时,处理器会自动从NAND FLASH上拷贝前面一段的代码到内部的RAM中执行.按照以前的方法 ...
- 今天学习的裸板驱动之存储控制器心得(初始化SDRAM)
CPU只管操作地址,而有些地址代表的是某些存储设备. 但是操作这些存储设备需要很多东西,比如需要制定bank,行/列地址等.所以就有了存储管理器,用来处理这种CPU操作的地址和存储设备间的转换. (1 ...
- 今天学习的裸板驱动之GPIO实验学习心得
GPIO分成很多组今天学习的这个芯片的GPIO有GPA-GPJ个组.具体可在芯片手册中看到. GPIO有很多寄存器,今天学习的这个芯片,他的寄存器分为以下几种类型: (1)端口控制寄存器 (2)端口数 ...
- 关于在arm裸板编程时使用printf问题的解决方法
在ARM裸板驱动编程中,是不允许程序直接调用C库程序的.为什么呢?因为此时kernel还没有被加载,所以在封装在kernel层的C库的API是用不了的,那怎么办? 在开发过程中,printf的功能我不 ...
- 【嵌入式开发】 嵌入式开发工具简介 (裸板调试示例 | 交叉工具链 | Makefile | 链接器脚本 | eclipse JLink 调试环境)
作者 : 韩曙亮 博客地址 : http://blog.csdn.net/shulianghan/article/details/42239705 参考博客 : [嵌入式开发]嵌入式 开发环境 (远 ...
- 嵌入式 hi3518c裸板uboot烧写、kernel烧写、fs烧写小结
1.在uboot中我可以添加自己的命令,添加的方法是找到一个uboot的命令,然后模仿着去增加属于自己的命令代码以及实现函数就可以 2.记住在使用printf进行调试的时候,在遇到指针或者字符串的时候 ...
- uboot-tiny4412启动流程(下)----如何将自己的裸板测试程序加入uboot中启动测试
今天在工作上搞了一天高通的芯片uboot程序,目的是希望将一个裸板的程序移植到uboot中,并且开机让它运行.这个芯片是NXP4330,目前是高通的一个芯片,基于ARM-contexA9架构,那么就跟 ...
随机推荐
- NandFlash详述【转】
NandFlash详述 转自:http://wenku.baidu.com/view/04d9330bb52acfc789ebc92f.html?re=view 1. 硬件特性: [Flash的硬件实 ...
- 防止SQL注入和XSS攻击Filter
nbsp;今天系统使用IBM的安全漏洞扫描工具扫描出一堆漏洞,下面的filter主要是解决防止SQL注入和XSS攻击 一个是Filter负责将请求的request包装一下. 一个是request包装器 ...
- BZOJ 2351 Matrix(哈希)
题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2351 题意:给出一个n*m的01矩阵.再给出10个A*B的小01矩阵.判断这些小的矩阵是 ...
- BZOJ 1041 圆上的整点
题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1041 题意:求圆x^2+y^2=r^2上的整点. 思路:由于对称性,我们只需要计算第一象 ...
- ubuntu中apt-get安装与默认路径
一.apt-get 安装 deb是debian linus的安装格式,跟red hat的rpm非常相似,最基本的安装命令是:dpkg -i file.deb或者直接双击此文件 dpkg 是Debian ...
- 1430. Crime and Punishment(枚举)
1430 即使是枚举 也是有一定技术含量的 对于ax+by = n: 枚举max(a,b)中的系数 这样可以确定另一个 但问题是如何确定上限 假设max(a,b) = a,很显然是不会超n/a的 但这 ...
- c#开源Excel操作库--NPOI
前言 以前也用C#操作过excel,用的是OleDb或者offic的com组件,但是总是非常的麻烦,依赖限制较多,所以果断寻找开源方案,JAVA上面已经有非常成熟的POI,就这样,找到了移.Net的移 ...
- laravel中的命名公约规范及relation N+1问题
User: model ; users: 表名: user_id 键值 relation: public function tasks(){return $this->belongsToMa ...
- Volley : "参数param:{ inoutNo:inoutNo ,whcode:’’}
private void fuzzySearch() { mRequestQueue = Volley.newRequestQueue(getActivity()); String str = Sha ...
- acdream 1685 多民族王国(DFS,并查集)
Problem Description 娜娜好不容易才回忆起自己是娜娜而不是什么Alice,也回忆起了自己要继续探索这个世界的目标,便偷偷溜出皇宫.娜娜发现这个王国有很多个民族组成,每个民族都有自己的 ...