13.C工程与寄存器封装

2023-05-16

文章目录

  • 启动代码分析
  • 使用C语言点灯
  • 封装代码
  • 寄存器操作的标准化

启动代码分析

.text
.global _start
_start:
	/*
	 * Vector table:占用异常向量表空间,让它不再能被其它代码占用
	 */ 
	b reset
	b .	@跳转到程序自身
	b .
	b .
	b .
	b .
	b .
	b .

reset:
	/*
	 * Set vector address in CP15 VBAR register
	 */ 
	ldr	r0, =_start @把异常向量表首地址给r0
	mcr	p15, 0, r0, c12, c0, 0	@Set VBAR,通过设置协处理器把r0设为异常向量表首地址

	/*
	 * Set the cpu to SVC32 mode, Disable FIQ/IRQ
	 */  
	mrs r0, cpsr
	bic r0, r0, #0x1f
	orr	r0, r0, #0xd3
	msr	cpsr ,r0

	/*
	 * Defines access permissions for each coprocessor
	 */  
    mov	r0, #0xfffffff
    mcr	p15, 0, r0, c1, c0, 2  	

	/*
	 * Invalidate L1 I/D                                                                                                                   
	 */
	mov	r0, #0					@Set up for MCR
	mcr	p15, 0, r0, c8, c7, 0	@Invalidate TLBs
	mcr	p15, 0, r0, c7, c5, 0	@Invalidate icache
	
	/*
	 * Set the FPEXC EN bit to enable the FPU
	 */ 
	mov r3, #0x40000000
	fmxr FPEXC, r3
	
	/*
	 * Disable MMU stuff and caches
	 */
	mrc	p15, 0, r0, c1, c0, 0
	bic	r0, r0, #0x00002000		@Clear bits 13 (--V-)
	bic	r0, r0, #0x00000007		@Clear bits 2:0 (-CAM)
	orr	r0, r0, #0x00001000		@Set bit 12 (---I) Icache
	orr	r0, r0, #0x00000002		@Set bit 1 (--A-) Align
	orr	r0, r0, #0x00000800		@Set bit 11 (Z---) BTB
	mcr	p15, 0, r0, c1, c0, 0

	/*
	 * Initialize stacks                                                                                                                  
	 */
init_stack:     
	/*svc mode stack*/
	msr cpsr, #0xd3	@切换模式
	ldr sp, _stack_svc_end	@sp栈指针指向栈底

	/*undef mode stack*/
	msr cpsr, #0xdb
	ldr sp, _stack_und_end

	/*abort mode stack*/	
	msr cpsr,#0xd7
	ldr sp,_stack_abt_end

	/*irq mode stack*/	
	msr cpsr,#0xd2
	ldr sp, _stack_irq_end
	
	/*fiq mode stack*/
	msr cpsr,#0xd1
	ldr sp, _stack_fiq_end
	
	/*user mode stack, enable FIQ/IRQ*/
	msr cpsr,#0x10
	ldr sp, _stack_usr_end

	/*Call main*/
	b main	@跳转到C语言中的main函数

_stack_svc_end:      @由于ARM采用的是满减栈,因此栈指针要指向栈底
	.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

.data@由于每个工作模式用的栈寄存器都不一样,因此要给每个模式申请512字节的栈空间
stack_svc:      
	.space 512 @占用512字节空间,不让其它指令占用,用作栈存储
stack_und:
	.space 512
stack_abt:      
	.space 512
stack_irq:      
	.space 512
stack_fiq:      
	.space 512
stack_usr:      
	.space 512

使用C语言点灯

/*
 * 一.汇编语言访问存储器
 * 	1.读存储器
 * 		LDR R1,[R2]
 * 	2.写存储器
 * 		STR R1,[R2]
 *
 * 二.C语言访问存储器
 * 	1.读存储器
 * 		data = *ADDR
 * 	2.写存储器
 * 	 	*ADDR = data
 */

void Delay(unsigned int Time)
{
	while(Time --);
}

#if 0//代码初版
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;
}
#endif

封装代码

#if 0//封装成宏定义
#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;
}
#endif

#if 0//将地址连续的描述同一个引脚的参数封装成结构体
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;
}
#endif

#if 0//将结构体及定义写到头文件里,包含头文件即可
#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;
}
#endif


#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;
}

寄存器操作的标准化

在不破坏其它位的值的情况下,只修改某一位的值。

#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
 *	或运算,或上0不变,或上1变1
 * 	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);
 */
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

13.C工程与寄存器封装 的相关文章

随机推荐

  • RPLIDAR十分钟极速入门教程

    本教程由 臭皮匠机器人 原创 转载请注明出处 收到一个RPLidar后 xff0c 干的第一件事应该是先让雷达跑起来 xff0c 边做边学是最高效的 本教程 xff0c 将教你只用简单的三步 xff0c 花10分钟即可上手 本教程RPLid
  • RPLIDAR最强参数详解

    本教程由 臭皮匠机器人 原创 转载请注明出处 有的同学跟我们说 xff0c RPLIDAR的参数看不懂 xff0c 感觉理解起来困难 其实也不难懂的 xff0c 本篇将带你了解这些重要的指标 xff0c 给你讲清说透 由于RPLIDAR还在
  • 如何避免头文件被重复包含?

    在实际的工程中我们很有可能重复包含某一个头文件 xff0c 比如下面这种情况 xff1a 开发人员B和开发人员C在自己的头文件中都包含了开发人员A的头文件 xff0c 而开发人员D在自己的编译单元中包含了B和C的头文件 xff0c 此时D就
  • VScode配置C/C++编程总结(GCC+Clang+CMake)

    VScode配置C C 43 43 编程总结 xff08 GCC 43 Clang 43 CMake xff09 自己存下档纪念一下2019 12 18 Visual Studio Code VScode全称Visual Studio Co
  • 关于锂电池的二三事

    为了解释的更清楚 xff0c 我录制了一个视频 xff0c 详情可以参看 xff1a 我的这个B站视频 这是目录0 0 背景参数指标一些使用方法 背景 锂电池是我们日常生活中和制造东西时经常见到和使用的一种东西 xff0c 但是有很多细节可
  • 单片机堆栈知识总结

    堆栈 在片内RAM中 xff0c 常常要指定一个专门的区域来存放某些特别的数据 它遵循顺序存取和后进先出 LIFO FILO 的原则 xff0c 这个RAM区叫堆栈 其实堆栈就是单片机中的一些存储单元 xff0c 这些存储单元被指定保存一些
  • STM32串口发送中断试验、在初始化时不能使能串口发送中断

    问题描述 在测试STM32串口发送完成中断的应用中 xff0c 遇到了一个很奇怪的问题 xff0c 在初始化完成之后直接就进入了串口中断函数的发送完成服务中断函数部分 本测试代码是在原来的基础上更改的 xff0c 原来只使能了接受中断 xf
  • java,http post请求,多个不同方式请求示例

    以下是 Java 中进行 HTTP POST 请求的示例代码 xff0c 包括使用 HttpURLConnection 和 HttpClient 两种方式 xff0c 供您参考 使用 HttpURLConnection 发送 POST 请求
  • 【STM32】HAL库开发教程(一)—基本使用

    前言 提示 xff1a 本系列本章针对STM32F207 xff0c 基于Cubemx和Keil进行程序开发 本系列文章并不是一步一操作的傻瓜式教程 xff0c 而更希望是一个向导 xff0c 引导读者去思考去开发 做为一个开发者应该是在思
  • 【STM32】HAL库开发教程(五)—RTC使用

    前言 不必害怕未知 xff0c 无需恐惧犯错 xff0c 做一个Creator xff01 一 RTC简介 STM32F2的实时时钟 RTC 是一个独立的BCD Binary Coded Decimal 定时器 计时器 xff0c 提供了一
  • 【STM32】HAL库开发教程(七)—SPI使用

    前言 不必害怕未知 xff0c 无需恐惧犯错 xff0c 做一个Creator xff01 本文主要介绍STM32 HAL库开发中SPI通信的使用 一 开发步骤 1 STM32CubeMX配置 在左侧引脚配置处勾选SPI进行配置在SPI模式
  • 【通信技术】信噪比及单位

    信噪比 xff1a 一个电子设备或者电子系统中信号与噪声的比例 计量单位 dB xff0c 其计算方法是10lg Ps Pn xff0c 其中Ps和Pn分别代表信号和噪声的有效功率 功率单位 xff1a dBm是一个考征功率绝对值的值 xf
  • 【C语言】字符串打印(定长)

    目的 xff1a 打印长度可控的字符串 char ucBuf uint8 t ucLen char ucString 256 memcpy ucString ucBuf ucLen ucString ucLen 61 39 0 39 pri
  • 【卫星】卫星通信基本概念与知识

    不必害怕未知 xff0c 无需恐惧犯错 xff0c 做一个Creator xff01 卫星通信基本概念与知识 上行链路 xff1a 从地球站发射信号到通信卫星所经过的通信路径成为上行链路 下行链路 xff1a 通信卫星将信号再转发到其他地球
  • 计算机基础笔记(三)—操作系统

    前言 不必害怕未知 xff0c 无需恐惧犯错 xff0c 做一个Creator xff01 目录 前言一 概述二 操作系统分类三 组成部分用户界面内存管理器进程管理进程同步设备管理文件管理 四 主流操作系统UNIXLinuxWindows
  • 计算机基础笔记(四)—数据结构

    前言 不必害怕未知 xff0c 无需恐惧犯错 xff0c 做一个Creator xff01 目录 前言数组链表栈 xff08 LIFO xff09 队列 xff08 FIFO xff09 广义线性表树图 定义 有特殊关系的数据的集合 xff
  • 计算机基础笔记(五)—数据库

    前言 不必害怕未知 xff0c 无需恐惧犯错 xff0c 做一个Creator xff01 目录 前言文件结构顺序文件索引文件散列文件目录 数据库数据库体系结构数据库模型数据库的设计其他数据库 文件结构 文件是数据记录的集合 xff0c 每
  • 陀螺仪数据处理(BMI088)

    1 BMI088惯性传感器介绍 1 1传感器原理图 传感器采用3 3V供电 xff0c 使用SPI IIC通讯模式 xff08 本文采用SPI通讯协议 xff09 1 2传感器功能介绍 注 xff1a 这里提到的数据读取频率 2000Hz是
  • FreeRTOS 多任务系统——任务切换、任务管理方式心得

    目前在进行对使用FreeRTOS的项目的代码升级 xff0c 之前采用的主逻辑任务切换模式 xff1a 由一个任务来进行逻辑上为串行的不同功能切换 xff0c 其他任务分别负责通信实时传输 传感器检测和电机控制 xff0c 系统中断中采用变
  • 13.C工程与寄存器封装

    文章目录 启动代码分析使用C语言点灯封装代码寄存器操作的标准化 启动代码分析 text global start start Vector table xff1a 占用异常向量表空间 xff0c 让它不再能被其它代码占用 b reset b