正点原子ARM裸机开发篇

裸机就是手动的操作硬件来实现驱动设备,后面会有驱动框架不需要这么麻烦

第八章 汇编 LED 灯实验

 

核心过程

通过汇编语言来控制硬件(驱动程序)

代码流程

1、使能 GPIO1 时钟

GPIO1 的时钟由 CCM_CCGR1 的 bit27 和 bit26 这两个位控制,将这两个位都设置位 11 即 可。本教程所有例程已经将 I.MX6U 的所有外设时钟都已经打开了,因此这一步可以不用做。

2、设置 GPIO1_IO03 的复用功能

找到 GPIO1_IO03 的复用寄存器“IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03”的地址为 0X020E0068,然后设置此寄存器,将 GPIO1_IO03 这个 IO 复用为 GPIO 功能,也就是 ALT5

3、配置 GPIO1_IO03(io口的属性配置)

找到 GPIO1_IO03 的配置寄存器“IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03”的地址为 0X020E02F4,根据实际使用情况,配置此寄存器

4、设置 GPIO(输出还是输入)

5、控制 GPIO 的输出电平(电平是高还是低,低就是亮高是熄灭)

汇编程序代码

.global _start  /* 全局标号 */

/*
 * 描述:	_start函数,程序从此函数开始执行此函数完成时钟使能、
 *		  GPIO初始化、最终控制GPIO输出低电平来点亮LED灯。
 */
_start:
	/* 例程代码 */
	/* 1、使能所有时钟 */
	ldr r0, =0X020C4068 	/* CCGR0    寄存器地址*/
	ldr r1, =0XFFFFFFFF     /*表示对所有对外设都使能*/
	str r1, [r0]		    /*赋值操作*/ 
	 
	ldr r0, =0X020C406C  	/* CCGR1 */
	str r1, [r0]

	ldr r0, =0X020C4070  	/* CCGR2 */
	str r1, [r0]
	
	ldr r0, =0X020C4074  	/* CCGR3 */
	str r1, [r0]
	
	ldr r0, =0X020C4078  	/* CCGR4 */
	str r1, [r0]
	
	ldr r0, =0X020C407C  	/* CCGR5 */
	str r1, [r0]
	
	ldr r0, =0X020C4080  	/* CCGR6 */
	str r1, [r0]
	

	/* 2、设置GPIO1_IO03复用为GPIO1_IO03 */
	ldr r0, =0X020E0068	/* 将寄存器SW_MUX_GPIO1_IO03_BASE加载到r0中 */
	ldr r1, =0X5		/* 设置寄存器SW_MUX_GPIO1_IO03_BASE的MUX_MODE为5 */
	str r1,[r0]

	/* 3、配置GPIO1_IO03的IO属性	
	 *bit 16:0 HYS关闭
	 *bit [15:14]: 00 默认下拉
     *bit [13]: 0 kepper功能
     *bit [12]: 1 pull/keeper使能
     *bit [11]: 0 关闭开路输出
     *bit [7:6]: 10 速度100Mhz
     *bit [5:3]: 110 R0/6驱动能力
     *bit [0]: 0 低转换率
     */
    ldr r0, =0X020E02F4	/*寄存器SW_PAD_GPIO1_IO03_BASE */
    ldr r1, =0X10B0
    str r1,[r0]

	/* 4、设置GPIO1_IO03为输出 */
    ldr r0, =0X0209C004	/*寄存器GPIO1_GDIR */
    ldr r1, =0X0000008		
    str r1,[r0]

	/* 5、打开LED0
	 * 设置GPIO1_IO03输出低电平,也就算该寄存器对bit3
	 
	 */
	ldr r0, =0X0209C000	/*寄存器GPIO1_DR */
   ldr r1, =0		
   str r1,[r0]

/*
 * 描述:	loop死循环  ,b就是跳转的意思
 */
loop:
	b loop 				

	

	
	

c语言代码

#ifndef __MAIN_H
#define __MAIN_H
/*************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名	: 	 main.h
作者	   : 左忠凯
版本	   : V1.0
描述	   : 时钟GPIO1_IO03相关寄存器地址定义。
其他	   : 无
日志	   : 初版V1.0 2019/1/3 左忠凯创建
*************************************/

/* 
 * CCM相关寄存器地址 
 */
#define CCM_CCGR0 			*((volatile unsigned int *)0X020C4068)
#define CCM_CCGR1 			*((volatile unsigned int *)0X020C406C)

#define CCM_CCGR2 			*((volatile unsigned int *)0X020C4070)
#define CCM_CCGR3 			*((volatile unsigned int *)0X020C4074)
#define CCM_CCGR4 			*((volatile unsigned int *)0X020C4078)
#define CCM_CCGR5 			*((volatile unsigned int *)0X020C407C)
#define CCM_CCGR6 			*((volatile unsigned int *)0X020C4080)

/* 
 * IOMUX相关寄存器地址 
 */
#define SW_MUX_GPIO1_IO03 	*((volatile unsigned int *)0X020E0068)
#define SW_PAD_GPIO1_IO03 	*((volatile unsigned int *)0X020E02F4)

/* 
 * GPIO1相关寄存器地址 
 */
#define GPIO1_DR 			*((volatile unsigned int *)0X0209C000)
#define GPIO1_GDIR 			*((volatile unsigned int *)0X0209C004)
#define GPIO1_PSR 			*((volatile unsigned int *)0X0209C008)
#define GPIO1_ICR1 			*((volatile unsigned int *)0X0209C00C)
#define GPIO1_ICR2 			*((volatile unsigned int *)0X0209C010)
#define GPIO1_IMR 			*((volatile unsigned int *)0X0209C014)
#define GPIO1_ISR 			*((volatile unsigned int *)0X0209C018)
#define GPIO1_EDGE_SEL 		*((volatile unsigned int *)0X0209C01C)

#endif
#include "main.h"

/*
 * @description	: 使能I.MX6U所有外设时钟
 * @param 		: 无
 * @return 		: 无
 */
void clk_enable(void)
{
	CCM_CCGR0 = 0xffffffff;
	CCM_CCGR1 = 0xffffffff;
	CCM_CCGR2 = 0xffffffff;
	CCM_CCGR3 = 0xffffffff;
	CCM_CCGR4 = 0xffffffff;
	CCM_CCGR5 = 0xffffffff;
	CCM_CCGR6 = 0xffffffff;
}

/*
 * @description	: 初始化LED对应的GPIO
 * @param 		: 无
 * @return 		: 无
 */
void led_init(void)
{
	/* 1、初始化IO复用 */
	SW_MUX_GPIO1_IO03 = 0x5;	/* 复用为GPIO1_IO03 */

	/* 2、、配置GPIO1_IO03的IO属性	
	 *bit 16:0 HYS关闭
	 *bit [15:14]: 00 默认下拉
     *bit [13]: 0 kepper功能
     *bit [12]: 1 pull/keeper使能
     *bit [11]: 0 关闭开路输出
     *bit [7:6]: 10 速度100Mhz
     *bit [5:3]: 110 R0/6驱动能力
     *bit [0]: 0 低转换率
     */
	SW_PAD_GPIO1_IO03 = 0X10B0;		

	/* 3、初始化GPIO */
	GPIO1_GDIR = 0X0000008;	/* GPIO1_IO03设置为输出 */

	/* 4、设置GPIO1_IO03输出低电平,打开LED0 */
	GPIO1_DR = 0X0;
}

/*
 * @description	: 打开LED灯
 * @param 		: 无
 * @return 		: 无
 */
void led_on(void)
{
	/* 
	 * 将GPIO1_DR的bit3清零	 
	 */
	GPIO1_DR &= ~(1<<3); 
}

/*
 * @description	: 关闭LED灯
 * @param 		: 无
 * @return 		: 无
 */
void led_off(void)
{
	/*    
	 * 将GPIO1_DR的bit3置1
	 */
	GPIO1_DR |= (1<<3);
}

/*
 * @description	: 短时间延时函数
 * @param - n	: 要延时循环次数(空操作循环次数,模式延时)
 * @return 		: 无
 */
void delay_short(volatile unsigned int n)
{
	while(n--){}
}

/*
 * @description	: 延时函数,在396Mhz的主频下
 * 			  	  延时时间大约为1ms
 * @param - n	: 要延时的ms数
 * @return 		: 无
 */
void delay(volatile unsigned int n)
{
	while(n--)
	{
		delay_short(0x7ff);
	}
}

/*
 * @description	: mian函数
 * @param 	    : 无
 * @return 		: 无
 */
int main(void)
{
	clk_enable();		/* 使能所有的时钟		 	*/
	led_init();			/* 初始化led 			*/

	while(1)			/* 死循环 				*/
	{	
		led_off();		/* 关闭LED   			*/
		delay(500);		/* 延时大约500ms 		*/

		led_on();		/* 打开LED		 	*/
		delay(500);		/* 延时大约500ms 		*/
	}

	return 0;
}

注意:

#define CCM_CCGR0    *((volatile unsigned int *)0X020C4068)  是将右边地址命名为左边的

#define SW_MUX_GPIO1_IO03     *((volatile unsigned int *)0X020E0068)  左边起名字是为了便于认识这个寄存器的作用,是将gpio1组的03复用为寄存器

第十一章 模仿 STM32 驱动开发格式实验

为了不用每个寄存器都定义一次,我们将同一个外设的所有寄存器都写成一个结构体,每个成员变量是每个io口对应的复用寄存器。然后通过IOMUX_SW_MUX->GPIO1_IO03”来访问 GPIO1_IO03 的 IO 复用寄存器了

第十二章 官方 SDK 移植实验

NXP 官方为 I.MX6ULL 编写了 SDK 包,在 SDK 包里面 NXP 已经编写好了寄存器定义文件, 所以我们可以直接移植 SDK 包里面的文件来用。

第十三章 BSP 工程管理实验

必须对工程文件做管理,将不同功能的源码文 件放到不同的目录中。另外我们也需要将源码文件中,所有完成同一个功能的代码提取出来放 到一个单独的文件中,也就是对程序分功能管理。

bsp 用来存放驱动文件;

imx6ul 用来存放跟芯片有关的文件,比如 NXP 官方的 SDK 库文件;

obj 用来存放编译生成的.o 文件;

project 存放 start.S 和 main.c 文件,也就是应用文件;

第十四章 蜂鸣器实验

 当 SNVS_TAMPER1 输出低电平的时候 Q1 导通,相当于蜂鸣器的正 极连接到 DCDC_3V3,蜂鸣器形成一个通路,因此蜂鸣器会鸣叫。同理,当 SNVS_TAMPER1 输出高电平的时候 Q1 不导通,那么蜂鸣器就没有形成一个通路,因此蜂鸣器也就不会鸣叫

下面是调用了板子的函数库

void beep_init(void)
 {
   /* 1、初始化 IO 复用,复用为 GPIO5_IO01 */
   IOMUXC_SetPinMux(IOMUXC_SNVS_SNVS_TAMPER1_GPIO5_IO01,0); 
 
   /* 2、配置 GPIO1_IO03 的 IO 属性 */
   IOMUXC_SetPinConfig(IOMUXC_SNVS_SNVS_TAMPER1_GPIO5_IO01,0X10B0);
  
   /* 3、初始化 GPIO,GPIO5_IO01 设置为输出 */
   GPIO5->GDIR |= (1 << 1); 

   /* 4、设置 GPIO5_IO01 输出高电平,关闭蜂鸣器 */
   GPIO5->DR |= (1 << 1):
}

第十六章 主频和时钟配置实验

时钟是单片机的脉搏,是单片机的驱动源,使用任何一个外设都必须打开相应的时钟。这样的好处是,如果不使用一个外设的时候,就把它的时钟关掉,从而可以降低系统的功耗

主频越大,马力越大

晶振产生时钟信号,时钟信号有平路

时钟树

时钟源就和水源一样,会流出不同的大小(频率)水流,然后驱动不同外设工作

第十七章 GPIO 中断实验

中断向量表,存放了中断程序的起始地址

是指中断服务程序入口地址的偏移量段基址,一个中断向量占据4字节空间。中断向量表是8086系统内存中最低端1K字节空间,它的作用就是按照中断类型号从小到大的顺序存储对应的中断向量,总共存储256个中断向量。在中断响应过程中,CPU通过从接口电路获取的中断类型号(中断向量号)计算对应中断向量在表中的位置,并从中断向量表中获取中断向量,将程序流程转向中断服务程序的入口地址

中断向量偏移

       一般ARM从0X000000000地址开始运行,对于STM32我们设置连接首地址为0X8000000。

       如果代码一定要从0X8000000开始运行,那么需要告诉一下soc内核。也就是设置中断向量偏移。设置SCB的VTOR寄存器为新的中断向量表起始地址即可。

中断控制器

中断管理机构。使能和关闭指定的中断、设置中断优先级

Cortex-A7中断系统

1、Cortex-A中断向量表

       Cortex-A中断向量表有8个中断,其中重点关注IRQ。Cortex-A的中断向量表需要用户自己去定义。

2、中断向量偏移

       我们的裸机历程都是从0X87800000开始的,因此要设置中断向量偏移

GIC中断控制器

              同NVIC一样,GIC用于管理Cortex-A的中断。GIC提供了开关中断,设置中断优先级。

    4、IMX6U中断号

       为了区分不同的中断,引入了中断号。ID0~ID15是给SGI,ID16~ID31是给PPI。剩下的ID32~1019给SPI,也就是按键中断、串口中断。。。。

       6ULL支持128个中断

第十八章 EPIT 定时器实验

定时器

是内部soc的一个外设

定时器/计数器作为SoC的外设,主要用来实现定时执行代码的功能。定时器相对于SoC来说,就好像闹钟相对于人来说意义一样。单核的CPU是单线程的,只能干一件事情,干完这件事情完去干另一件事情需要定时器来提醒

2. 定时器有什么用

(1)定时器可以让SoC在执行主程序的同时,可以(通过定时器)具有计时功能,到了一定时间(计时结束)后,定时器会产生中断提醒CPU,CPU会去处理中断并执行定时器的ISR。从而去执行预先设定好的事件。

(2)定时器就好像是CPU的一个秘书一样,这个秘书专门管帮CPU来计时,并到时间后提醒CPU要做某件事情。所以CPU有了定时器之后,只需要预先把自己XX时间之后必须要做的事情绑定到定时器中断ISR即可,到了时间之后定时器就会以中断的方式提醒CPU来处理这个事情。
 

第19章 串口-UATR

在开发板上有一个串口转usb芯片,我们开发板与电脑相连是通过usb传输

全双工异步通用串行数据总线

UART_URXD  寄存器保存这串口接收到的数据    

UART_UTXD寄存器为发送数据寄存器

      UART_UCR1~UCR4都是串口的控制寄存器。UART_UCR1的bit0是UART的使能位,为1的时候使能UART。Bit14为自动检测波特率使能位,为1的时候使能波特率自动检测。

      UART_UCR2的bit0为软件复位位。为0的时候复位UART。Bit1使能UART的接收,我们要配置为1。Bit2为发送使能,要设置为1。Bit5设置数据位,0的话表示7位数据位,1的话表示8位数据位。Bit6设置停止位,0的话表示1位停止位,1的话表示2位。Bit7奇偶校验位,为0的时候是偶校验,为1的时候是计校验。Bit8校验使能位,为0的时候关闭校验

UART电平标准

TTL    低电平 0             高电平1 

RS-232  采用差分线   -3~·15 表示逻辑去  +3~+15表示0

第20章 ddr

DDR就是一个ram,就是内存,程序是在内存中运行的,先将文件存放到sd卡中,然后放到ddr中去运行

RAM   随机存储器(任意对其中的地址进行操作)

ROM  只读存储器   (存放数据)(flash也是)

第21 章  RGB-LCD

1、像素点

于一个“小灯“,不管是液晶屏,还是手机,平板,RGBLCD屏幕他都是有由一个个的彩色小灯构成的。彩色点阵屏每个像素点有三个小灯,红色、绿色和蓝色,也叫做RGB。RGB就是光的三原色。通过调整RGB三种颜色的比例,就可以实现姹紫千红的世界

2、分辨率

要想显示文字,图片,视频等等就需要很多个像素点,分辨率说的就是像素点的个数,1080P、720P、2K、4K,8K。1080P=1920*1080,表示一行有1920个像素点,一列有1080个。显示器有尺寸!24村,27村、55寸。尺寸不变的情况下,分辨率越高,显示效果越精细。4K=3840*2160相当于4个1080P

       正点原子的RGB屏幕有:4.3寸480*272,800*480,7寸的800*480和1024*600,10.1寸的1280*800。

       Iphone4屏幕尺寸是3.5寸,960*640分辨率,PPI=327

3、像素格式

如何将RGB三种颜色进行量化,每种颜色用8bit表示,RGB就需要888共24bit。可以描述出2^24=中颜色16777216=1677万种颜色。现在流行10bit,HDR10,支持HDR效果的10bit面板,RGB10 10 10。

       在RGB888的基础上在加上8bit的ALPHA通道,也就是透明通道,ARGB8888=32位。

4、LCD屏幕接口

RGB格式的屏幕,一般叫做RGB接口屏。

屏幕接口有:MIPI、LVDS、MCU、RGB接口。

正点原子屏幕ID:使用ID可以识别出不同的屏幕,在RGBLCD屏幕上对R7,G7,B7焊接上拉或下拉电阻实现不同的ID。,

正点原子的ALPHA地板RGB屏幕接口用了3个3157模拟开关。原因是防止LCD屏幕上的ID电阻影响到6ULL的启动

屏幕接口类型

正点原子是rgb类型

 正点原子屏幕ID,这个可以识别出不同的屏幕做出不同的初始化,这样板子就可以兼容多种屏幕

LCD参数

一帧的图像显示需要行同步信号与列同步信号一起运作

显存

一般是一帧图片需要的数据空间大小,比如32位表示一个像素点也急速4b,1024乘以00乘以4 = 2.5MB,我们直接定义一个数组lcdframe

IIC

2C 是很常见的一种总线协议,I2C 是 NXP 公司设计的,I2C 使用两条线在主控制器和从
机之间进行数据通信。一条是 SCL(串行时钟线),另外一条是 SDA(串行数据线),这两条数据
线需要接上拉电阻I2C 是支持多从机的,也就是一个 I2C 控制器下可以挂多个 I2C 从设备,这些不同的 I2C从设备有不同的器件地址,这样 I2C 主控制器就可以通过 I2C 设备的器件地址访问指定的 I2C设备了,一个 I2C 总线连接多个 I2C 设备如图 26.1.1.1 所示

起始位:SCL 为高电平的时候,SDA 出现下降沿就表示为起始位

停止位:SCL 位高电平的时候,SDA出现上升沿就表示为停止位

 在数据传输的时候 ,要保证SCL高电平,SDA上的数据稳定

I2C 写时序

i2c的操作无非是读寄存器和写寄存器的操作

写时序的具体步骤

1、开始信号

2、发送I2C设备地址,每个i2c器件都有一个设备地址,通过发送具体的设备地址来决定访问哪个i2c器件,这个一个8位的数据,其中高七位设备地址,最后一位是读写地址,为1的话就是表示这个一个读操作,为0的话就是表示这个一个写操作

3、I2C 器件地址后面跟着一个读写位,为 0 表示写操作,为 1 表示读操作

4、从机发送的 ACK 应答信号

5、重新发送开始信号

6、发送要写写入数据的寄存器地址

7、从机发送的 ACK 应答信号。

8、发送要写入寄存器的数据

9、从机发送的 ACK 应答信号

10、停止信号

I2C 读时序

l2C 单字节读时序比写时序要复杂一点,读时序分为 4 大步,第一步是发送设备地址,第
二步是发送要读取的寄存器地址,第三步重新发送设备地址,最后一步就是 I2C 从器件输出要
读取的寄存器值

l2c多字节读写时序

多字节读写时序和单字节的基本一致,只是在读写数据的
时候可以连续发送多个自己的数据,其他的控制时序都是和单字节一样的

SPI

SPI 是 Motorola 公司推出的一种同步串行接口技术,是一种高速、全双工的同步通信总线,SPI 时钟频率相比 I2C 要高很多,最高可以工作
在上百 MHz。

标准的 4 线 SPI,这四根线如下

1、①、CS/SS,Slave Select/Chip Select,这个是片选信号线,用于选择需要进行通信的从设备。I2C 主机是通过发送从机设备地址来选择需要进行通信的从机设备的,SPI 主机不需要发送从机设备,直接将相应的从机设备片选信号拉低即可

2、SCK,Serial Clock,串行时钟,和 I2C 的 SCL 一样,为 SPI 通信提供时钟

3、MOSI/SDO,Master Out Slave In/Serial Data Output,简称主出从入信号线,这根数据线
只能用于主机向从机发送数据,也就是主机输出,从机输入

4、MISO/SDI,Master In Slave Out/Serial Data Input,简称主入从出信号线,这根数据线只
能用户从机向主机发送数据,也就是主机输入,从机输出

SPI 通信都是由主机发起的,主机需要提供通信的时钟信号。主机通过 SPI 线连接多个从
设备

 SPI 有四种工作模式,通过串行时钟极性(CPOL)和相位(CPHA)的搭配来得到四种工作模式:
①、CPOL=0,串行时钟空闲状态为低电平。
②、CPOL=1,串行时钟空闲状态为高电平,此时可以通过配置时钟相位(CPHA)来选择具
体的传输协议。
③、CPHA=0,串行时钟的第一个跳变沿(上升沿或下降沿)采集数据。
④、CPHA=1,串行时钟的第二个跳变沿(上升沿或下降沿)采集数据。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Smart210是一款兼具高性能和高可靠性的裸机开发板,适用于嵌入式系统和物联网应用的快速开发裸机开发是指在无操作系统的环境下,直接通过硬件和软件编程完成应用的开发过程。对于Smart210来说,裸机开发可以充分发挥其性能优势和硬件资源,在没有操作系统的限制下,实现更高效的应用程序。 Smart210的裸机开发过程中,需要对其搭载的ARM Cortex-A8处理器进行编程。首先,我们需要了解Smart210的硬件平台,包括芯片架构、内存、外设接口等。然后,通过汇编语言或C语言等编程语言,利用编译器和调试工具,直接控制硬件资源,完成应用程序的设计和编写。在裸机开发中,开发者需要自行实现系统的初始化、任务调度、中断处理等功能,以及与硬件进行交互的驱动程序的编写。 裸机开发可能相对复杂和困难,因为需要手动管理硬件资源、处理底层细节,并且没有操作系统提供的抽象层和功能库,需要更多的开发工作量和技术知识。然而,裸机开发也有其优势,比如更高的性能和更少的资源占用,更灵活的控制和调试能力,以及更接近硬件的开发体验。 总之,Smart210裸机开发是一种高效和灵活的开发方式,适用于对性能要求较高、对硬件控制要求较多的应用场景。通过充分利用Smart210的硬件资源和裸机开发的优势,可以实现更加自由和高效的嵌入式系统和物联网应用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值