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架构,那么就跟 ...
随机推荐
- 日期工具类 - DateUtil.java
日期工具类,提供对日期的格式化和转换方法.获取区间日期.指定日期.每月最后一天等. 源码如下:(点击下载 -DateUtil.java.commons-lang-2.6.jar ) import ja ...
- 如何给桌面搬家(Win XP)
是不是习惯把一些常用的文件放在桌面上?或者接收个文件就直接放桌面了,这样用起来方便点. 可是一旦你重装系统或者恢复系统,桌面又回到了以前的状态,很多的文件就丢了.小心的话,重做系统前会做个备份.但如果 ...
- poj-2393 Yogurt factory (贪心)
http://poj.org/problem?id=2393 奶牛们有一个工厂用来生产奶酪,接下来的N周时间里,在第i周生产1 单元的奶酪需要花费ci,同时它们也有一个储存室,奶酪放在那永远不会坏,并 ...
- 总结Selenium自动化测试方法(二)测试环境搭建
(接上期内容) 二.测试环境搭建 1.安装python 现在python3.0比python2.0多了一些改进的功能(详见http://zhidao.baidu.com/link?url=3sT1g7 ...
- Codeforces Round #276 (Div. 2)
A. Factory 题意:给出a,m,第一天的总量为a,需要生产为a%m,第二天的总量为a+a%m,需要生产(a+a%m)%m 计算到哪一天a%m==0为止 自己做的时候,把i开到1000来循环就过 ...
- Cocoa & Cocoa Touch概念
Application Kit框架包括广泛的类和方法,它们用来开发交互式图形应用程序,使得开发文本/菜单/工具栏/表/文档/剪贴板和窗口之类的过程变得十分简便.在Mac OSX操作系统中,术语coco ...
- HDU 3555 Bomb (数位DP-记忆化搜索模板)
题意 求区间[1,n]内含有相邻49的数. 思路 比较简单的按位DP思路.这是第一次学习记忆化搜索式的数位DP,确实比递推形式的更好理解呐,而且也更通用~可以一般化: [数位DP模板总结] int d ...
- 浅析extendedLayout, automaticallyAdjustsScrollViewInsets, extendedLayoutIncludesOpaqueBars
参考文章: http://stackoverflow.com/questions/18798792/explaining-difference-between-automaticallyadjusts ...
- (六) 6.3 Neurons Networks Gradient Checking
BP算法很难调试,一般情况下会隐隐存在一些小问题,比如(off-by-one error),即只有部分层的权重得到训练,或者忘记计算bais unit,这虽然会得到一个正确的结果,但效果差于准确BP得 ...
- 【转】让Souce Insight支持多种语言的语法高亮:Python,Ruby,ARM汇编,windows脚本文件(bat/batch),PPC,SQL,TCL,Delphi等
原文网址:http://www.crifan.com/source_insight_support_highlight_for_python_ruby_arm_batch_ppc_sql_tcl_de ...
