TM4C123G学习记录(4)--关于ROM前缀函数和HWREG函数

  • 为了准备电赛临时学一下TM4C123G,简单记录学习内容
  • 大家可以在这里下载我收集的资源,非常全面,花了很大功夫收集来的,还有书籍、例程代码等
  • 还可以在TI官网下载相关文档TI官网

这两天学习TM4C的时候,看到了不少ROM前缀的库函数(比如ROM_SysCtlClockSet),还有很多库函数底层用了HWREG函数,比较迷糊,查资料学习了一下,在此稍作总结

一、ROM前缀函数

1、介绍

  • M4的ROM中集成了外设驱动库等代码。使用带ROM的函数,会直接跳转到ROM中去执行。如果不带ROM的话,代码会在Flash中执行。也就是说使用ROM函数可以节省内存空间,而带ROM前缀的函数在功能上和不带的没有区别
  • 使用ROM前,需要包含头文件#include "rom.h",并且按这个头文件中的格式定义芯片型号(因为不同型号芯片,函数在ROM中的存储情况不一样,rom.h中会根据这个芯片选择定义进行条件编译,打开看一下就知道了),如TARGET_IS_TM4C123_RB1,一般这种选型的定义可以放在MDK的Opinion菜单的C/C++选项栏中
    TM4C123G学习记录(4)--关于ROM前缀函数和HWREG函数_第1张图片

2、ROM函数调用分析

ROM_SysCtlClockSet函数为例,分析一下调用过程

(1)直接Goto Defination,如下

	#if defined(TARGET_IS_TM4C123_RA1) ||                                         \
   		defined(TARGET_IS_TM4C123_RA3) ||                                         \
    	defined(TARGET_IS_TM4C123_RB1) ||                                         \
    	defined(TARGET_IS_TM4C123_RB2)
	#define ROM_SysCtlClockSet                                                    \
        	((void (*)(uint32_t ui32Config))ROM_SYSCTLTABLE[23])
	#endif
  • 首先可以看出定义芯片信号TARGET_IS_TM4C123_RB1的作用,这里是一个条件编译
  • 分析ROM_SysCtlClockSet的定义,可以看到这里是一个强制类型转换,把ROM_SYSCTLTABLE[23]转换为一个函数指针void (*)(uint32_t ui32Config),指向地址ROM_SYSCTLTABLE[23]

(2)看一下ROM_SYSCTLTABLE[23]是什么

	#define ROM_APITABLE            ((uint32_t *)0x01000010)
	#define ROM_VERSION             (ROM_APITABLE[0])
	....
	#define ROM_SYSCTLTABLE         ((uint32_t *)(ROM_APITABLE[13]))
  • 看到这里是一个基址寻址,ROM_APITABLE是一个uint32_t型指针,指向地址 0x01000010,这样可以把它看做一个uint32_t数组
  • ROM_SYSCTLTABLE(uint32_t *)(ROM_APITABLE[13]),即取ROM_APITABLE数组的第13个元素(地址为0x01000010+13*4)的值,然后用一个unt32_t型指针指向这个值。可以推测,ROM_APITABLE数组存储的应当也是地址值

(3)小结一下

  • ROM中API表从地址0x0100010开始,每4个字节存一个uint32_t型数据,指向一个子表的首地址
  • 子表中,每4个字节存一个uint32_t型数据,指向一个函数地址
    TM4C123G学习记录(4)--关于ROM前缀函数和HWREG函数_第2张图片

二、HWREG函数

(1)顾名思义HWREG()的意思就是操作硬件寄存器的意思,里面的参数是tm4c芯片的硬件外设寄存器地址,可以在芯片手册memory地址分配找到。
(2)查看一下定义,有不少类似的函数

	//*****************************************************************************
	//
	// Macros for hardware access, both direct and via the bit-band region.
	//
	//*****************************************************************************
	#define HWREG(x)                                                              \
     	   (*((volatile uint32_t *)(x)))
	#define HWREGH(x)                                                             \
    	    (*((volatile uint16_t *)(x)))
	#define HWREGB(x)                                                             \
    	    (*((volatile uint8_t *)(x)))
	#define HWREGBITW(x, b)                                                       \
    	    HWREG(((uint32_t)(x) & 0xF0000000) | 0x02000000 |                     \
       	       		(((uint32_t)(x) & 0x000FFFFF) << 5) | ((b) << 2))
	#define HWREGBITH(x, b)                                                       \
    	    HWREGH(((uint32_t)(x) & 0xF0000000) | 0x02000000 |                    \
       	        	(((uint32_t)(x) & 0x000FFFFF) << 5) | ((b) << 2))
	#define HWREGBITB(x, b)                                                       \
    	    HWREGB(((uint32_t)(x) & 0xF0000000) | 0x02000000 |                    \
        	       (((uint32_t)(x) & 0x000FFFFF) << 5) | ((b) << 2))
  • 由定义不难看出,HWREG(x)函数的作用,就是先把x转为一个指向x的volatile uint32_t指针,然后从中取值,这样只要知道寄存器地址,我们就可以方便地对其进行读写操作

(3)更多介绍,参考TIVA中HWREG()使用详解

你可能感兴趣的:(嵌入式)