我是靠谱客的博主 漂亮书包,最近开发中收集的这篇文章主要介绍KSDK_1.1.0 之hardware_init()函数,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

硬件平台TWR_K60D100M
先来分析main()里的第一个函数hardware_init():
该函数主要完成了打开clock gate 和进行板载GPIO的pinmux设置

void hardware_init(void) {
uint8_t i;
/* enable clock for PORTs */
for (i = 0; i < HW_PORT_INSTANCE_COUNT; i++) {
CLOCK_SYS_EnablePortClock(i);
}
/* Setup board clock source. */
g_xtal0ClkFreq = 50000000U;
g_xtalRtcClkFreq = 32768U;
for (i = 0; i < HW_PORT_INSTANCE_COUNT; i++) {
configure_gpio_pins(i);
}
}

这个函数会调用CLOCK_SYS_EnablePortClock()和configure_gpio_pins()两个函数,CLOCK_SYS_EnablePortClock()定义如下:

/*FUNCTION**********************************************************************
*
* Function Name : CLOCK_SYS_EnablePortClock
* Description
: Enable the clock for PORT module
* This function enables the clock for PORT module
*
*END**************************************************************************/
void CLOCK_SYS_EnablePortClock(uint32_t instance)
{

assert(instance < sizeof(portGateTable)/sizeof(portGateTable[0]));

SIM_HAL_EnableClock(SIM_BASE, portGateTable[instance]);
}

其中portGateTable定义如下:

/* PORT instance table. */
static const sim_clock_gate_name_t portGateTable[] =
{
kSimClockGatePortA,
kSimClockGatePortB,
kSimClockGatePortC,
kSimClockGatePortD,
kSimClockGatePortE
};

sim_clock_gate_name_t 是一个枚举类型,其定义如下

/*! @brief Clock gate name used for SIM_HAL_EnableClock/SIM_HAL_DisableClock. */
typedef enum _sim_clock_gate_name
{
kSimClockGateUart4
= FSL_SIM_SCGC_BIT(1U, 10U),
kSimClockGateUart5
= FSL_SIM_SCGC_BIT(1U, 11U),
kSimClockGateEnet0
= FSL_SIM_SCGC_BIT(2U, 0U),
kSimClockGateDac0
= FSL_SIM_SCGC_BIT(2U, 12U),
kSimClockGateDac1
= FSL_SIM_SCGC_BIT(2U, 13U),
kSimClockGateRnga0
= FSL_SIM_SCGC_BIT(3U, 0U),
kSimClockGateFlexcan1
= FSL_SIM_SCGC_BIT(3U, 4U),
kSimClockGateSpi2
= FSL_SIM_SCGC_BIT(3U, 12U),
kSimClockGateSdhc0
= FSL_SIM_SCGC_BIT(3U, 17U),
kSimClockGateFtm2
= FSL_SIM_SCGC_BIT(3U, 24U),
kSimClockGateAdc1
= FSL_SIM_SCGC_BIT(3U, 27U),
kSimClockGateEwm0
= FSL_SIM_SCGC_BIT(4U, 1U),
kSimClockGateCmt0
= FSL_SIM_SCGC_BIT(4U, 2U),
kSimClockGateI2c0
= FSL_SIM_SCGC_BIT(4U, 6U),
kSimClockGateI2c1
= FSL_SIM_SCGC_BIT(4U, 7U),
kSimClockGateUart0
= FSL_SIM_SCGC_BIT(4U, 10U),
kSimClockGateUart1
= FSL_SIM_SCGC_BIT(4U, 11U),
kSimClockGateUart2
= FSL_SIM_SCGC_BIT(4U, 12U),
kSimClockGateUart3
= FSL_SIM_SCGC_BIT(4U, 13U),
kSimClockGateUsbfs0
= FSL_SIM_SCGC_BIT(4U, 18U),
kSimClockGateCmp
= FSL_SIM_SCGC_BIT(4U, 19U),
kSimClockGateVref0
= FSL_SIM_SCGC_BIT(4U, 20U),
kSimClockGateLlwu0
= FSL_SIM_SCGC_BIT(4U, 28U),
kSimClockGateLptmr0
= FSL_SIM_SCGC_BIT(5U, 0U),
kSimClockGateTsi0
= FSL_SIM_SCGC_BIT(5U, 5U),
kSimClockGatePortA
= FSL_SIM_SCGC_BIT(5U, 9U),
kSimClockGatePortB
= FSL_SIM_SCGC_BIT(5U, 10U),
kSimClockGatePortC
= FSL_SIM_SCGC_BIT(5U, 11U),
kSimClockGatePortD
= FSL_SIM_SCGC_BIT(5U, 12U),
kSimClockGatePortE
= FSL_SIM_SCGC_BIT(5U, 13U),
kSimClockGateFtf0
= FSL_SIM_SCGC_BIT(6U, 0U),
kSimClockGateDmamux0
= FSL_SIM_SCGC_BIT(6U, 1U),
kSimClockGateFlexcan0
= FSL_SIM_SCGC_BIT(6U, 4U),
kSimClockGateSpi0
= FSL_SIM_SCGC_BIT(6U, 12U),
kSimClockGateSpi1
= FSL_SIM_SCGC_BIT(6U, 13U),
kSimClockGateSai0
= FSL_SIM_SCGC_BIT(6U, 15U),
kSimClockGateCrc0
= FSL_SIM_SCGC_BIT(6U, 18U),
kSimClockGateUsbdcd0
= FSL_SIM_SCGC_BIT(6U, 21U),
kSimClockGatePdb0
= FSL_SIM_SCGC_BIT(6U, 22U),
kSimClockGatePit0
= FSL_SIM_SCGC_BIT(6U, 23U),
kSimClockGateFtm0
= FSL_SIM_SCGC_BIT(6U, 24U),
kSimClockGateFtm1
= FSL_SIM_SCGC_BIT(6U, 25U),
kSimClockGateAdc0
= FSL_SIM_SCGC_BIT(6U, 27U),
kSimClockGateRtc0
= FSL_SIM_SCGC_BIT(6U, 29U),
kSimClockGateFlexbus0
= FSL_SIM_SCGC_BIT(7U, 0U),
kSimClockGateDma0
= FSL_SIM_SCGC_BIT(7U, 1U),
kSimClockGateMpu0
= FSL_SIM_SCGC_BIT(7U, 2U),
#if (defined(DOXYGEN_OUTPUT) && (DOXYGEN_OUTPUT))
} sim_clock_gate_name_k60d10_t;
#else
} sim_clock_gate_name_t;

以kSimClockGatePortA为例, kSimClockGatePortA = FSL_SIM_SCGC_BIT(5U, 9U), PORTA的Clock Gate位位于SIM_SCG5的第9位,FSL_SIM_SCGC_BIT的两个参数看起来与之有关系。

#define FSL_SIM_SCGC_BIT(SCGCx, n) (((SCGCx-1U)<<5U) + n)

这个宏定义代表什么含义呢?
它表示PORTA的clock gate 位(也就是SIM_SCGC5的第9位)相对与SIM_SCGC1起始位置的位数。<<5 就是乘以32的意思。
于是乎kSimClockGatePortA = (((5-1U)<<5U) + 9)=0x89

紧接着调用 SIM_HAL_EnableClock(SIM_BASE, portGateTable[instance]);也就是 SIM_HAL_EnableClock(SIM_BASE, kSimClockGatePortA);第一个参数是
SIM模块的基地址,第二个参数是PORTA gate 使能位相对SIM_SCGC1的位数。
这里写图片描述
这个函数定义如下:

/*!
* @brief Enable the clock for specific module.
*
* This function enables the clock for specific module.
*
* @param baseAddr Base address for current SIM instance.
* @param name Name of the module to enable.
*/
static inline void SIM_HAL_EnableClock(uint32_t baseAddr, sim_clock_gate_name_t name)
{
BW_SIM_SCGC_BIT(baseAddr, name, 1U);
}

它调用 BW_SIM_SCGC_BIT(baseAddr, name, 1U)这个,BW_SIM_SCGC_BIT这个宏的定义如下:

#define BW_SIM_SCGC_BIT(x, n, v)
(BITBAND_ACCESS32(HW_SIM_SCGC_BIT_ADDR((x), (n)), BP_SIM_SCGC_BIT(n)) = (uint32_t)(v))

这里面又调用了一个宏BITBAND_ACCESS32,这个宏非常关键

/**
* @brief Macro to access a single bit of a 32-bit peripheral register (bit band region
*
0x40000000 to 0x400FFFFF) using the bit-band alias region access.
* @param Reg Register to access.
* @param Bit Bit number to access.
* @return Value of the targeted bit in the bit band region.
*/
#define BITBAND_ACCESS32(Reg,Bit) (*((uint32_t volatile*)(0x42000000u + (32u*((uint32_t)(Reg) - (uint32_t)0x40000000u)) + (4u*((uint32_t)(Bit))))))

这个宏定义是为了获取bit band 区域中的某个位的值。实现的方式是通过访问别名区的地址来实现的。别名区的地址可以通过0x42000000+32*(reg-0x40000000)+4*bit来实现。其中reg就是寄存器的地址。 bit是寄存器中的bit 位数(0~32)。
位段操作可参考:Bit_nand介绍

再来看看BITBAND_ACCESS32具体的两个参数值,分别为:HW_SIM_SCGC_BIT_ADDR((x), (n))和BP_SIM_SCGC_BIT(n),HW_SIM_SCGC_BIT_ADDR(x,n) 定义如下

#define HW_SIM_SCGC_BIT_ADDR(x, n) (HW_SIM_SCGC1_ADDR(x) + ((((uint32_t)(n) >> 5) - 0U) * 4U))
#define HW_SIM_SCGC1_ADDR(x)
((uint32_t)(x) + 0x1028U)

0x4004_7000+0x1028=0x4004_8028得到的是SIM_SCGC1的地址,((((uint32_t)(n) >> 5) - 0U) * 4U))这个的含义是n先除以32,再乘以4,得到的结果是SIM_SCGC1应该加的地址增加数,对于PORTA,就得到SIM_SCG4的地址4004_8038

再看BP_SIM_SCGC_BIT(n)

#define BP_SIM_SCGC_BIT(n)
((uint32_t)(n) & ((1U << 5) - 1U)) 

我的目标是得到0x89的后五位(0~31),方法是与上0b11111, ((1U << 5) - 1U)) =31,恰好符和。
这样就得到SIM_SCGC5的地址和bit位数。Bitnand再一操作就可以对那位进行赋值。

说了这么多就是完成了对SIM_SCGC5的第9位赋1,结果整的这么复杂。在实际使用中如果你想打开UART0的Clock gate,需要做的是在portGateTable加入kSimClockGateUart0

/* PORT instance table. */
static const sim_clock_gate_name_t portGateTable[] =
{
kSimClockGatePortA,
kSimClockGatePortB,
kSimClockGatePortC,
kSimClockGatePortD,
kSimClockGatePortE,
kSimClockGateUart0
};

HW_PORT_INSTANCE_COUNT设置为6即可。

本质也就是调用了HAL层的SIM_HAL_EnableClock(uint32_t baseAddr, sim_clock_gate_name_t name),直接调用SIM_HAL_EnableClock(SIM_BASE,kSimClockGateUart0)也可以。

最后

以上就是漂亮书包为你收集整理的KSDK_1.1.0 之hardware_init()函数的全部内容,希望文章能够帮你解决KSDK_1.1.0 之hardware_init()函数所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(45)

评论列表共有 0 条评论

立即
投稿
返回
顶部