KSDK_1.1.0 之hardware_init()函数

来源:互联网 发布:网络牛牛赌博犯法 编辑:程序博客网 时间:2024/04/28 00:29

硬件平台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)也可以。

0 0
原创粉丝点击