当前位置: 首页 > news >正文

LV.12 D13 C工程与寄存器封装 学习笔记

一、C语言工程简介

把模板在linux解压出来

代码写在interface.c就可以了。

map.lds是链接脚本文件(负责代码的排布)

include中是头文件,src中是写好的源代码 

start.s是启动代码,在interface.c之前运行,把cpu和栈做一个初始化

二、启动代码分析

.text
.global _start
_start:/** Vector table  * 异常向量表(占32个字节)*/ b resetb .b .b .b .b .b .b .reset:/** Set vector address in CP15 VBAR register*/ ldr	r0, =_start                @把异常向量表的值给r0mcr	p15, 0, r0, c12, c0, 0	   @Set VBAR (把r0寄存器的值放到p15协处理器中的c12寄存器)/** Set the cpu to SVC32 mode, Disable FIQ/IRQ* 把cpu模式改成SVC模式,改成ARM状态,关闭FIQ/IRQ中断*/  mrs r0, cpsrbic r0, r0, #0x1forr	r0, r0, #0xd3msr	cpsr ,r0/** Defines access permissions for each coprocessor*/  mov	r0, #0xfffffffmcr	p15, 0, r0, c1, c0, 2  	/** Invalidate L1 I/D                                                                                                                   */mov	r0, #0					@Set up for MCRmcr	p15, 0, r0, c8, c7, 0	@Invalidate TLBsmcr	p15, 0, r0, c7, c5, 0	@Invalidate icache/** Set the FPEXC EN bit to enable the FPU*/ mov r3, #0x40000000fmxr FPEXC, r3/** Disable MMU stuff and caches* MMU:负责物理地址和虚拟地址间的转换*/mrc	p15, 0, r0, c1, c0, 0bic	r0, r0, #0x00002000		@Clear bits 13 (--V-)bic	r0, r0, #0x00000007		@Clear bits 2:0 (-CAM)orr	r0, r0, #0x00001000		@Set bit 12 (---I) Icacheorr	r0, r0, #0x00000002		@Set bit 1 (--A-) Alignorr	r0, r0, #0x00000800		@Set bit 11 (Z---) BTBmcr	p15, 0, r0, c1, c0, 0/** Initialize stacks      * 初始化栈                                                                                                            */
init_stack:     /*svc mode stack*/msr cpsr, #0xd3            @把cpu的模式改为svc模式ldr sp, _stack_svc_end     @把svc模式下的栈的最高地址给了svc模式下的sp/*undef mode stack*/msr cpsr, #0xdb     ldr sp, _stack_und_end/*abort mode stack*/	msr cpsr,#0xd7ldr sp,_stack_abt_end/*irq mode stack*/	msr cpsr,#0xd2ldr sp, _stack_irq_end/*fiq mode stack*/msr cpsr,#0xd1ldr sp, _stack_fiq_end/*user mode stack, enable FIQ/IRQ*//*把cpu的模式改为user模式,并打开FIO/IRQ中断msr cpsr,#0x10ldr sp, _stack_usr_end/*Call main*/b main/** 把各个栈最高的地址算出来,作为起始地址*/
_stack_svc_end:      .word stack_svc + 512
_stack_und_end:      .word stack_und + 512
_stack_abt_end:      .word stack_abt + 512
_stack_irq_end:      .word stack_irq + 512
_stack_fiq_end:.word stack_fiq + 512
_stack_usr_end:      .word stack_usr + 512/** 给各个模式都申请了512个字节空间,作为栈*/
.data
stack_svc:      .space 512    
stack_und:.space 512
stack_abt:      .space 512
stack_irq:      .space 512
stack_fiq:      .space 512
stack_usr:      .space 512

三、C语言实现LED实验

/** 一、汇编语言访问存储器* 	1.读存储器* 		LDR R1, [R2]* 	2.写存储器* 		STR R1, [R2]** 二、C语言访问存储器* 	1.读存储器* 		data = *ADDR* 	2.写存储器* 		*ADDR = data* */void Delay(unsigned int Time)
{while(Time--);
}int main()
{/*通过设置GPX2CON寄存器来将GPX2_7引脚设置成输出功能*/*(unsigned int *)0x11000c40 = 0x10000000;while(1){/*点亮LED2*/*(unsigned int *)0x11000c44 = 0x00000080;/*延时*/Delay(1000000);/*熄灭LED2*/*(unsigned int *)0x11000c44 = 0x00000000;/*延时*/Delay(1000000);}return 0;
}

 

四、寄存器的封装方式

 1、把单个的寄存器封装成一个宏

#define GPX2CON (*(unsigned int *)0x11000c40)
#define GPX2DAT (*(unsigned int *)0x11000c44)int main()
{GPX2CON = 0x10000000;while(1){/*点亮LED2*/GPX2DAT = 0x00000080;/*延时*/Delay(1000000);/*熄灭LED2*/GPX2DAT = 0x00000000;/*延时*/Delay(1000000);}return 0;
}

2、把相关的几个寄存器封装成一个结构体,其地址空间必须是连续的

typedef struct
{unsigned int CON;unsigned int DAT;unsigned int PUD;unsigned int DRV;
}gpx2;#define GPX2 (*(gpx2 *)0x11000c40)int main()
{GPX2.CON = 0x10000000;while(1){/*点亮LED2*/GPX2.DAT = 0x00000080;/*延时*/Delay(1000000);/*熄灭LED2*/GPX2.DAT = 0x00000000;/*延时*/Delay(1000000);}return 0;
}

 

3、把整个芯片里的寄存器封装好,引用头文件

#include "exynos_4412.h"int main()
{GPX2.CON = 0x10000000;while(1){/*点亮LED2*/GPX2.DAT = 0x00000080;/*延时*/Delay(1000000);/*熄灭LED2*/GPX2.DAT = 0x00000000;/*延时*/Delay(1000000);}return 0;
}

五、寄存器操作的标准化

 只改寄存器的某几位,其他位保持不变

#include "exynos_4412.h"int main()
{GPX2.CON = GPX2.CON & (~(0xF << 28)) | (0x1 << 28);while(1){/*点亮LED2*/GPX2.DAT = GPX2.DAT | (1 << 7);/*延时*/Delay(1000000);/*熄灭LED2*/GPX2.DAT = GPX2.DAT & (~(1 << 7));/*延时*/Delay(1000000);}return 0;
}/** 1.unsigned int a; 将a的第3位置1,其他位保持不变* 	******** ******** ******** ********* 	******** ******** ******** ****1**** 	00000000 00000000 00000000 00001000** 	a = a | (1 << 3);** 2.unsigned int a; 将a的第3位置0,其他位保持不变* 	******** ******** ******** ********* 	******** ******** ******** ****0**** 	11111111 11111111 11111111 11110111** 	a = a & (~(1 << 3));** 	3.unsigned int a; 将a的第[7:4]位置为0101,其他位保持不变* 	******** ******** ******** ********* 	******** ******** ******** 0101****** 	1).先清零* 	11111111 11111111 11111111 00001111* 	00000000 00000000 00000000 11110000*  00000000 00000000 00000000 00001111** 	a = a & (~(0xF << 4));** 	2).再置位* 	00000000 00000000 00000000 01010000* 	00000000 00000000 00000000 00000101** 	a = a | (0x5 << 4);** 	=> a = a & (~(0xF << 4)) | (0x5 << 4);*/

我没并不只能控制LED,一切可以通过高低电频控制的东西,都可以通过GPIO来控制。

 

http://www.lryc.cn/news/212930.html

相关文章:

  • Java SE 学习笔记(十九)—— XML、设计模式
  • grafana InfluxDB returned error: error reading influxDB 400错误解决
  • 【LeetCode:150. 逆波兰表达式求值 | 栈】
  • 什么是神经网络,它的原理是啥?(2)
  • leetcode做题笔记206. 反转链表
  • 2023/10/31 JAVA学习
  • SurfaceFliger绘制流程
  • 系统架构设计师-第14章-云原生架构设计理论与实践-
  • conda 实践
  • 行业追踪,2023-10-31
  • springboot 配置多个Redis数据源详解
  • 【数据结构】排序算法总结
  • 作为20年老程序员,我如何使用GPT4来帮我写代码
  • 【机器学习合集】模型设计之残差网络 ->(个人学习记录笔记)
  • GoLong的学习之路(十六)基础工具之Gin框架
  • VMware打开centos黑屏解决方法汇总
  • 5G物联网关相较有线网关有哪些独特优势
  • 【数据结构】顺序表的学习
  • 在NISQ小型计算机上执行大型并行量子计算的可能性
  • 考虑时空相关性的风电功率预测误差MATLAB代码
  • ASP.NET WebApi 极简依赖注入
  • 解决proteus仿真stm32,IIC通讯,IIC DEBUG无法显示从机应答信号的问题(问题情况为在8位数据后应答位显示?)
  • PHP判断闰年
  • 证照之星XE专业版下载专业证件照制作工具
  • VR全景图片如何制作?揭秘VR全景图片制作全流程
  • vue element el-table-column 循环示例代码
  • R语言生物群落(生态)数据统计分析与绘图实践技术应用
  • 有了 GPT,还需要付费咨询吗?
  • 如何搭建一台服务器?
  • [转载]C++序列化框架介绍和对比