Tiny6410之uart裸机驱动

UART简介:

  UART(Universal Asynchronous Receiver and Transmitter)通用异步收发器(异步串行通信口),是一种通用的数据通信协议,它包括了RS232、RS499、RS423、RS422和RS485等接口标准规范和总线标准规范,即UART是异步串行通信口的总称。而RS232、RS499、RS423、RS422和RS485等,是对应各种异步串行通信口的接口标准和总线标准,它规定了通信口的电气特性、传输速率、连接特性和接口的机械特性等内容,这些东东都是物理层的概念。通信协议,是属于通信网络中的数据链路层的概念。
一、数据传输流程:
  1)平时数据线处于“空闲”状态(1状态)
  2)当腰发送数据时,UART改变TxD数据线状态(0状态)并维持一位的时间,这样接收方检测到开始位后。再等1.5位的时间就开始一位一位的检测数据线状态得到所传输的数据。
  3)UART一帧中可以有5,6,7,或8位的数据,发送方一位一位的改变数据线的状态,将他们发送出去,首先发送最低位。
  4)如果使用校验功能UART在发送完数据后还要发送一校验位,有两种校验方式,奇校验和偶校--数据位连同校验位中,“1”的数目等于奇数或偶数
  5)最后发送停止位,数据线状态恢复到“空闲”状态(1状态)停止位的状态有三种1位,1.5位,2位。

    起始位:先发出一个逻辑”0”信号,表示传输字符的开始。
    数据位:可以是5~8位逻辑”0”或”1”。如ASCII码(7位),扩展BCD码(8位)。小端传输
    校验位:数据位加上这一位后,使得“1”的位数应为偶数(偶校验)或奇数(奇校验)
    停止位:它是一个字符数据的结束标志。可以是1位、1.5位、2位的高电平。
    空闲位:处于逻辑“1”状态,表示当前线路上没有资料传送。
    
二、操作步骤:
  第一步:配置引脚


  通过硬件原理图可以知道使用的是MAX3232SOP芯片 使用的是TX0 和RXD0 对应的配置寄存器是GPA通过数据手册可知GPA的地址及每位所代表的意义。通过数据手册可以知道通过配置GPACON的相应管脚就可以将其设置为UART功能。


  Register       Address
    GPACON   0x7F008000

GPA0  [3:0]        0000 = Input              0001 = Output
                         0010 = UART RXD[0]  0011 = Reserved
                         0100 = Reserved        0101 = Reserved
                         0110 = Reserved        0111 = External Interrupt Group 1 [0]
                            
GPA1  [7:4]        0000 = Input              0001 = Output
                         0010 = UART TXD[0]  0011 = Reserved
                         0100 = Reserved        0101 = Reserved
                         0110 = Reserved        0111 = External Interrupt Group 1 [1]

故只需要将GPACON的第八位赋值成 0x00100010即可将GPA配置成UART

第二步:设置数据格式
  由数据手册可知uart数据帧发送是可编程的。它由一个起始位,5~8 个数据位,一个可选的奇偶位和 1~2
个可由行控制寄存器(ULCONn )指定的停止位组成。发送器也可以产生中断条件,在传输过程中,它通过置位逻辑状态 0
来强制串行输出。当目前的发送完全传输完成后,发送中断信号。然后不断传送数据到发送 FIFO 寄存器(在非 FIFO 的模式下,发送保存寄存器。)

word length = 11,8bit的数据

Number of Stop Bit = 0;1bit的停止位

Parity Mode = 000;无校验位

Intfrared Mode =0;使用普通模式

所以ULCON0 = 0x3;

第三步:UART配置

Receive Mode = 01;使用中断模式或轮询模式、

Transmit Mode = 01;使用中断模式或轮询模式

Send Break Signal = 0;普通传输

loop-back Mode = 0;使用回环方式

Clock Selection = 0;使用PCLK作为UART的工作时钟

所以UCON =0x5;UFCON0 用来使能FIFO,UMCON0用来设置无留控

第三步:设置波特率
  波特率即每秒传输的数据位数,涉及两个寄存器UBRDIV0和UDIVSLOT0

波特率设置相关公式:DIV_VAL = UBRDIVn + (num of 1’s in UDIVSLOTn)/16. Refer to UART Baud Rate Configure Registers.

PCLK = 66.5MHZ 波特率bps设置为115200。所以(66.5MHZ、(115200*16))-1 =35.08 =UBRDIVn + (num of 1’s in UDIVSLOTn)/16。故设置UBRDIV0 = 35,UDIVSLOT0 = 0x1;

第四步:编码

  1 //start.S
  2 // 启动代码
  3 .global _start
  4
  5 _start:
  6
  7     // 把外设的基地址告诉CPU
  8     ldr r0, =0x70000000
  9     orr r0, r0, #0x13
 10     mcr p15,0,r0,c15,c2,4
 11
 12     // 关看门狗
 13     ldr r0, =0x7E004000
 14     mov r1, #0
 15     str r1, [r0]
 16
 17     // 设置栈
 18     ldr sp, =0x0C002000
 19
 20     // 开启icaches
 21 #ifdef  CONFIG_SYS_ICACHE_OFF
 22     bic r0, r0, #0x00001000                 @ clear bit 12 (I) I-cache
 23 #else
 24     orr r0, r0, #0x00001000                 @ set bit 12 (I) I-cache
 25 #endif
 26     mcr p15, 0, r0, c1, c0, 0
 27
 28     // 设置时钟
 29     bl clock_init
 30
 31     // 调用C函数点灯
 32     bl main
 33
 34 halt:
 35     b halt
 36 //Tiny6410Addr.h
 37 #ifndef _Tiny6410Addr_H
 38 #define _Tiny6410Addr_H
 39 //GPK
 40 #define GPKIO_BASE (0x7F008800)
 41 #define rGPKCON0 (*((volatile unsigned long *)(GPKIO_BASE+0x00)))
 42 #define rGPKDAT  (*((volatile unsigned long *)(GPKIO_BASE+0x08)))
 43
 44 //CLOCK
 45 #define APLL_LOCK (*((volatile unsigned long *)0x7E00F000))
 46 #define MPLL_LOCK (*((volatile unsigned long *)0x7E00F004))
 47 #define EPLL_LOCK (*((volatile unsigned long *)0x7E00F008))
 48 #define OTHERS     (*((volatile unsigned long *)0x7E00F900))
 49 #define CLK_DIV0  (*((volatile unsigned long *)0x7E00F020))
 50 #define APLL_CON  (*((volatile unsigned long *)0x7E00F00C))
 51 #define MPLL_CON  (*((volatile unsigned long *)0x7F00F010))
 52 #define CLK_SRC   (*((volatile unsigned long *)0x7E00F01C))
 53
 54 //GPA /uart
 55 #define ULCON0     (*((volatile unsigned long *)0x7F005000))
 56 #define UCON0      (*((volatile unsigned long *)0x7F005004))
 57 #define UFCON0     (*((volatile unsigned long *)0x7F005008))
 58 #define UMCON0     (*((volatile unsigned long *)0x7F00500C))
 59 #define UTRSTAT0   (*((volatile unsigned long *)0x7F005010))
 60 #define UFSTAT0    (*((volatile unsigned long *)0x7F005018))
 61 #define UTXH0      (*((volatile unsigned char *)0x7F005020))
 62 #define URXH0      (*((volatile unsigned char *)0x7F005024))
 63 #define UBRDIV0    (*((volatile unsigned short *)0x7F005028))
 64 #define UDIVSLOT0  (*((volatile unsigned short *)0x7F00502C))
 65 #define GPACON     (*((volatile unsigned long *)0x7F008000))
 66
 67
 68
 69 #endif
 70
 71
 72
 73 //uart.c
 74 // 功能:初始化串口
 75 #include "uart.h"
 76 #include "Tiny6410Addr.h"
 77
 78
 79 void uart_init(void)
 80 {
 81     /* 1. 配置引脚 */
 82     GPACON &= ~0xff;
 83     GPACON |= 0x22;
 84
 85     /* 2. 设置数据格式等 */
 86     ULCON0 = 0x3;                      // 数据位:8, 无校验, 停止位: 1, 8n1
 87     UCON0  = 0x5;                      // 时钟:PCLK,禁止中断,使能UART发送、接收
 88     UFCON0 = 0x01;                     // FIFO ENABLE
 89     UMCON0 = 0;                        // 无流控
 90
 91     /* 3. 设置波特率 */
 92     // DIV_VAL = (PCLK / (bps x 16 ) ) - 1 = (66500000/(115200x16))-1 = 35.08
 93     // DIV_VAL = 35.08 = UBRDIVn + (num of 1’s in UDIVSLOTn)/16
 94     UBRDIV0   = 35;
 95     UDIVSLOT0 = 0x1;
 96
 97 }
 98
 99 /* 接收一个字符 */
100 char get_char(void)
101 {
102     while ((UFSTAT0 & 0x7f) == 0);  // 如果RX FIFO空,等待
103     return URXH0;                   // 取数据
104 }
105
106 /* 发送一个字符 */
107 void put_char(char c)
108 {
109     while (UFSTAT0 & (1<<14));         // 如果TX FIFO满,等待
110     UTXH0 = c;                      // 写数据
111 }
112
113
114 //uart.h
115 char get_char(void);
116 void put_char(char c);
117 void init_uart(void);
118
119 //clock.c
120 #include "Tiny6410Addr.h"
121 // 功能:c语言初始化时钟
122
123
124 #define ARM_RATIO    0                           // ARMCLK     = DOUTAPLL / (ARM_RATIO + 1)      = 532/(0+1) = 532  MHz
125 #define MPLL_RATIO   0                           // DOUTMPLL = MOUTMPLL / (MPLL_RATIO + 1)   = 532/(0+1) = 532  MHz
126 #define HCLKX2_RATIO 1                           // HCLKX2     = HCLKX2IN / (HCLKX2_RATIO + 1) = 532/(1+1) = 266  MHz
127 #define HCLK_RATIO   1                           // HCLK     = HCLKX2   / (HCLK_RATIO + 1)   = 266/(1+1) = 133  MHz
128 #define PCLK_RATIO   3                           // PCLK       = HCLKX2   / (PCLK_RATIO + 1)   = 266/(3+1) = 66.5 MHz
129
130
131
132 #define APLL_CON_VAL  ((1<<31) | (266 << 16) | (3 << 8) | (1))
133
134
135 #define MPLL_CON_VAL  ((1<<31) | (266 << 16) | (3 << 8) | (1))
136
137
138
139 void clock_init(void)
140 {
141     /* 1. 设置各PLL的LOCK_TIME,使用默认值 */
142     APLL_LOCK = 0xffff;                            // APLL_LOCK,供cpu使用
143     MPLL_LOCK = 0xffff;                            // MPLL_LOCK,供AHB(存储/中断/lcd等控制器)/APB(看门狗,定时器,SD等)总线上的设备使用
144     EPLL_LOCK = 0xffff;                            // EPLL_LOCK,供UART,IIS,IIC使用
145
146     /* 2. 设置为异步模式(Asynchronous mode) */
147     OTHERS &= ~0xc0;                            //《linux installation for u-boot》3.7中:用MPLL作为HCLK和PCLK的Source是异步(ASYNC)模式,用APLL是同步(SYNC)模式
148     while ((OTHERS & 0xf00) != 0);
149
150     /* 3. 设置分频系数 */
151     CLK_DIV0 = (ARM_RATIO) | (MPLL_RATIO << 4) | (HCLK_RATIO << 8) | (HCLKX2_RATIO << 9) | (PCLK_RATIO << 12);
152
153     /* 4. 设置PLL,放大时钟 */
154     APLL_CON = APLL_CON_VAL;
155     MPLL_CON = MPLL_CON_VAL;
156
157     /* 5. 选择PLL的输出作为时钟源 */
158     CLK_SRC = 0x03;
159 }
160
161 //main.c
162 #include "uart.h"
163 int main()
164 {
165     char c;
166     uart_init();
167     while(1)
168     {
169         c= get_char();
170         put_char(c+1);
171     }
172
173     return 0;
174     }
175
176 //Makefile
177 uart.bin : start.o clock.o main.o uart.o
178     arm-linux-ld -Ttext 0x50000000 -o uart.elf start.o clock.o main.o uart.o
179     arm-linux-objcopy -O binary uart.elf uart.bin
180     arm-linux-objdump -D uart.elf > uart.dis
181
182 %.o : %.S
183     arm-linux-gcc -g -c -O2 -o [email protected] $^
184
185 %.o : %.c
186     arm-linux-gcc -g -c -O2 -o [email protected] $^
187 .PHONY:clean
188 clean:
189     rm *.o *.elf *.bin *.dis

时间: 2024-10-24 16:59:22

Tiny6410之uart裸机驱动的相关文章

Tiny6410之按键裸机驱动

操作步骤: 第一步:查看开发板电路原理图 找到LED 和按键的管脚所对应的寄存器 LED:(见Tiny6410之LED裸机驱动) nLED_1 - GPK4 nLED_2 - GPK5 nLED_3 - GPK6 nLED_4 - GPK7 Buttons: K1   GPN0 K2   GPN1 K3   GPN2 K4   GPN3 由原理图可知LED对应的寄存器为GPK寄存器,buttons 对应的寄存器为GPL,由二极管的特性可知当LED_n为低电平时LED灯亮第二步:查看数据手册找到G

Tiny6410之LED裸机驱动

操作步骤: 第一步:查看开发板电路原理图 找到LED 的管脚所对应的寄存器 nLED_1 - GPK4 nLED_2 - GPK5 nLED_3 - GPK6 nLED_4 - GPK7 由原理图可知LED对应的寄存器为GPK寄存器,由二极管的特性可知当LED_n为低电平时LED灯亮第二步:查看数据手册找到GPK寄存器的地址及每位表示的意义 Register  Address GPKCON0   0x7F008800 GPKCON1   0x7F008804 GPKDAT    0x7F0088

Tiny6410之控制icache驱动

什么是cache:    基于程序访问的局限性,在主存和CPU通用寄存器之间设置了一类高速的.容量较小的存储器,把正在执行的指令地址附件的一部分指令或数据从主存调入这类存储器,供CPU 在一段时间内使用,这对提高程序的运行速度有很大的作用.这类介于主存和CPU 之间的高速小容量存储器称作高速cache.主要为了解决主存和CPU之间速度不匹配的问题.    比较常见的cache 包括icache 和dcache.icache 的使用比较简单,系统刚上电时,icache中的内容是无效的,并且icac

【华为云技术分享】小熊派华为物联网操作系统LiteOS裸机驱动移植02-LCD驱动移植及使用

1. LCD裸机驱动 小熊派开发板使用的LCD屏幕为1.3寸的TFT彩屏,色彩深度16bit,分辨率240*240,使用 SPI 接口与 MCU 之间通信. 如果你对裸机玩转LCD屏幕还不熟悉,请先阅读这篇文章: 2. 移植LCD裸机驱动到LiteOS 如果你对移植裸机驱动到LiteOS的方法还不了解,请先阅读这篇文章: 复制裸机驱动文件到LiteOS工程 LCD的底层是使用SPI驱动的,那么除了 STM32CubeMX 生成的spi.h和spi.c文件,还需要自己在此基础上手写LCD屏幕的驱动

Tiny6410之NAND FLASH驱动

一.NAND FLASH的特点 S3C6410的NAND FLASH控制器有如下特点 1.自导入模式:复位后,引导代码被送入到8KB的STEPPINGSTONE中,引导代码移动完毕,引导代码将在STEPPINGSTONE中执行.导入期间,NAND FLASH控制器不支持ECC矫正. 2.NAND FLSH 控制器I/F:支持512字节和2KB页 3.软件模式:用户可以直接访问nand flash 控制器,该特性可以用于读/檫/编程nand flash 存储器. 1)写命令寄存器=NAND FLA

DM9000裸机驱动程序设计

对于任何一个硬件模块的设计,首先第一步都是要先了解硬件本身后,再开始程序的软件设计.而由于DM9000的芯片文档内容很多,要驱动好网卡,需要很长时间,特别对于新手比较困难,所以可以参考linux内核代码中的网卡驱动程序,将其移植到裸机程序当中.下面将就ok6410,介绍DM9000裸机程序驱动的详细过程,并且完成arp协议的程序设计. 1.       DM9000硬件接口 打开ok6410的底板原理图可以看到DM9000和ok6410的硬件接口,通过DM9000的文档大概浏览可知一些比较重要的

Tiny4412之串口(Uart)驱动编写

一:tiny4412串口驱动编写 1.串口通信简介 串口通信指串口按位(bit)发送和接收字节,串口通信的概念非常简单,串口按位(bit)发送和接收字节.尽管比按字节(byte)的并行通信慢,但是串口可以在使用一根线发送数据的同时用另一根线 接收数据.它很简单并且能够实现远距离通信.比如IEEE488定义并行通行状态时,规定设备线总长不得超过20米,并且任意两个设备间的长度不得超过2 米:而对于串口而言,长度可达1200米. 串口通信所采用的通信协议为RS-232,RS-232通信方式允许简单连

S3C2440 UART串口驱动

++++++++++++++++++++++++++++++++++++++++++ 本文转载自mr_raptor的专栏,感谢mr_raptor大神. http://blog.csdn.net/mr_raptor/article/details/6556133 ++++++++++++++++++++++++++++++++++++++++++ 通用异步接收器和发送器(Universal Asynchronous Receiver and Transmitter)简称UART.通常是嵌入式设备中

[国嵌攻略][158][SPI裸机驱动设计]

SPI控制器工作流程 SPI控制器提供2个SPI接口.每个SPI接口有两个通道,分别为TX通道和RX通道.CPU要写数据到FIFO中,先写数据到SPI_TX_DATA寄存器中,这样此寄存器中的内容就会自动移动到发送FIFO中:同理,如果CPU要从接收FIFO中读取数据,就访问寄存器SPI_RX_DATA,紧接着接收FIFO的数据就会自动移动到SPI_RX_DATA寄存器中. OK6410 SPI裸机程序分析 //SPI初始化 u8 SPI_Init(){ //SPI复位 CH_CFG0 |= B