在bsp包初始化的过程中,系统会根据用户在user_config.h文件中的宏定义,选择性地初始化gpio。
1、文件Init_bsp.c (source\bsp\twrk60n512)中,代码:
/* Install the GPIO driver */
#if BSPCFG_ENABLE_GPIODEV
_io_gpio_install("gpio:");
#endif
/*FUNCTION*-------------------------------------------------------------------
*
* Function Name : _io_gpio_install
* Returned Value : _mqx_uint a task error code or MQX_OK
* Comments :
* Install a gpio driver.
*
*END*----------------------------------------------------------------------*/
_mqx_uint _io_gpio_install
(
/* [IN] A string that identifies the device for fopen */
/* input values are those identifiers defined in io_gpio.h file */
char_ptr identifier
)
{ /* Body */
if (IO_OK == gpio_cpu_init())
return _io_dev_install(identifier,
_io_gpio_open,
_io_gpio_close,
_io_gpio_read,
_io_gpio_write,
gpio_cpu_ioctl,
NULL);
return (_mqx_uint)IO_ERROR;
} /* Endbody */
/*FUNCTION*****************************************************************
*
* Function Name : gpio_cpu_install
* Returned Value : IO_OK
* Comments :
* Performs basic initialization specific to board
*
*END*********************************************************************/
_mqx_int gpio_cpu_init()
{ /* Body */
_bsp_gpio_io_init();
return IO_OK;
} /* Endbody */
/*FUNCTION*-------------------------------------------------------------------
*
* Function Name : _bsp_gpio_io_init
* Returned Value : MQX_OK or -1
* Comments :
* This function performs BSP-specific initialization related to GPIO
*
*END*----------------------------------------------------------------------*/
_mqx_int _bsp_gpio_io_init
(
void
)
{
/* Enable clock gating to all ports */
SIM_SCGC5 |= SIM_SCGC5_PORTA_MASK \
| SIM_SCGC5_PORTB_MASK \
| SIM_SCGC5_PORTC_MASK \
| SIM_SCGC5_PORTD_MASK \
| SIM_SCGC5_PORTE_MASK;
return MQX_OK;
}
#define SIM_SCGC5 SIM_SCGC5_REG(SIM_BASE_PTR)
#define SIM_SCGC5_REG(base) ((base)->SCGC5)
/* SIM - Peripheral instance base addresses */
/** Peripheral SIM base pointer */
#define SIM_BASE_PTR ((SIM_MemMapPtr)0x40047000u)
/** SIM - Peripheral register structure */
typedef struct SIM_MemMap {
uint32_t SOPT1; /**< System Options Register 1, offset: 0x0 */
uint8_t RESERVED_0[4096];
uint32_t SOPT2; /**< System Options Register 2, offset: 0x1004 */
uint8_t RESERVED_1[4];
uint32_t SOPT4; /**< System Options Register 4, offset: 0x100C */
uint32_t SOPT5; /**< System Options Register 5, offset: 0x1010 */
uint32_t SOPT6; /**< System Options Register 6, offset: 0x1014 */
uint32_t SOPT7; /**< System Options Register 7, offset: 0x1018 */
uint8_t RESERVED_2[8];
uint32_t SDID; /**< System Device Identification Register, offset: 0x1024 */
uint32_t SCGC1; /**< System Clock Gating Control Register 1, offset: 0x1028 */
uint32_t SCGC2; /**< System Clock Gating Control Register 2, offset: 0x102C */
uint32_t SCGC3; /**< System Clock Gating Control Register 3, offset: 0x1030 */
uint32_t SCGC4; /**< System Clock Gating Control Register 4, offset: 0x1034 */
uint32_t SCGC5; /**< System Clock Gating Control Register 5, offset: 0x1038 */
uint32_t SCGC6; /**< System Clock Gating Control Register 6, offset: 0x103C */
uint32_t SCGC7; /**< System Clock Gating Control Register 7, offset: 0x1040 */
uint32_t CLKDIV1; /**< System Clock Divider Register 1, offset: 0x1044 */
uint32_t CLKDIV2; /**< System Clock Divider Register 2, offset: 0x1048 */
uint32_t FCFG1; /**< Flash Configuration Register 1, offset: 0x104C */
uint32_t FCFG2; /**< Flash Configuration Register 2, offset: 0x1050 */
uint32_t UIDH; /**< Unique Identification Register High, offset: 0x1054 */
uint32_t UIDMH; /**< Unique Identification Register Mid-High, offset: 0x1058 */
uint32_t UIDML; /**< Unique Identification Register Mid Low, offset: 0x105C */
uint32_t UIDL; /**< Unique Identification Register Low, offset: 0x1060 */
} volatile *SIM_MemMapPtr;
分析1:
地址0x40047000u是SIM模块在K60整个地址空间中的基地址,SIM模块占用一块连续的存储空间,作为自己的操作寄存器,为了操作方便,头文件中把这些寄存器定义成了一个空间结构体。这样,只要基地址正确,结构体中变量正好对应SIM的各个寄存器地址,当然也包括一些保留字节。
该地址定义位于文件K60P100M100SF2RM.pdf 文件的12.1Memory map and register definition一节中。部分截图如下:
可以对照该结构体和文档地址空间定义进行分析理解。((SIM_MemMapPtr)0x40047000u)语句对物理地址进行了强制类型转换,然后根据结构体空间的顺序紧凑性,就可以得出:SIM_SCGC5_REG(SIM_BASE_PTR)语句就是操作了SCGC5寄存器,给里边的相应位置数操作。
6、文件MK60DZ10.h(source\psp\cortex)中,代码:
#define SIM_SCGC5_PORTA_MASK 0x200u
#define SIM_SCGC5_PORTA_SHIFT 9
#define SIM_SCGC5_PORTB_MASK 0x400u
#define SIM_SCGC5_PORTB_SHIFT 10
#define SIM_SCGC5_PORTC_MASK 0x800u
#define SIM_SCGC5_PORTC_SHIFT 11
#define SIM_SCGC5_PORTD_MASK 0x1000u
#define SIM_SCGC5_PORTD_SHIFT 12
#define SIM_SCGC5_PORTE_MASK 0x2000u
#define SIM_SCGC5_PORTE_SHIFT 13
从文档12.2.12 System Clock Gating Control Register 5 (SIM_SCGC5) 中可以看到,这些宏定义分别对应着ABCDE端口的始终脉冲门。在这里是打开了这些端口的时钟脉冲门,进行初始化。
我大概猜测一下:这些脉冲门,主要是控制给对应模块的时钟信号供给,当关闭脉冲门,就相当于关闭信号来源,那么就关闭了对应端口,可以达到省电的目的。为什么GPIO口还需要这些呢,其实当GPIO不管是输入还是输出,都有脉冲进行控制。当输出时,这些脉冲门信号供给,决定了你输出信号的响应时间,当信号频率越高,那么响应时间越短;当输入时,也是一样的道理,在微观上,当有外部信号过来,必须等到该引脚内部有脉冲输入的时候,他才能检测到你的外部信号过来,这里边同样有响应时间的问题。除了可以选择打开关闭,是不是还要有给GPIO口设置参考频率的寄存器,暂时还没有发现,不过我估计即便这个芯片没有,别的芯片可能也会有。