最近,在调试RT1064芯片的双以太网时,发现每次在初始化第二个以太网时,程序直接跑飞了。通过仿真器进行DBUG发现,程序卡在初始化第二路以太网的时钟地方,于是进一步查看寄存器值,发现头文件的宏定义有问题。
首先,我们来看下NXP 的SDK源码:
这是一个基本的可重入初始化函数,ENET1和ENET2均使用此函数来配置。关键问题出现在如下的 uint32_t instance = ENET_GetInstance(base);和(void)CLOCK_EnableClock(s_enetClock[instance]);这两句上面。
status_t ENET_Init(ENET_Type *base,
enet_handle_t *handle,
const enet_config_t *config,
const enet_buffer_config_t *bufferConfig,
uint8_t *macAddr,
uint32_t srcClock_Hz)
{
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
uint32_t instance = ENET_GetInstance(base);
/* Ungate ENET clock. */
(void)CLOCK_EnableClock(s_enetClock[instance]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
/* Reset ENET module. */
ENET_Reset(base);
return ENET_Up(base, handle, config, bufferConfig, macAddr, srcClock_Hz);
}
我们来剖析下ENET_GetInstance函数,通过for循环计算出instance为1(见ENET_BASE_PTRS),因此初始化ENET2时函数返回1。
#define ENET_BASE_PTRS { ENET, ENET2 }
/*! @brief Pointers to enet bases for each instance. */
static ENET_Type *const s_enetBases[] = ENET_BASE_PTRS;
uint32_t ENET_GetInstance(ENET_Type *base)
{
uint32_t instance;
/* Find the instance index from base address mappings. */
for (instance = 0; instance < ARRAY_SIZE(s_enetBases); instance++)
{
if (s_enetBases[instance] == base)
{
break;
}
}
assert(instance < ARRAY_SIZE(s_enetBases));
return instance;
}
我们继续看(void)CLOCK_EnableClock(s_enetClock[instance]);函数,当instance等于1时,s_enetClock[instance]为kCLOCK_IpInvalid,继续执行,将错误的值写入控制时钟的寄存器,将产生错误,问题因此出在这儿,下面函数就没必要展开了。我是将kCLOCK_IpInvalid替换成kCLOCK_Enet2,检查这个不会对其他程序造成影响,问题得到解决。
#define ENET_CLOCKS \
{ \
kCLOCK_Enet, kCLOCK_IpInvalid, kCLOCK_Enet2\
}
const clock_ip_name_t s_enetClock[] = ENET_CLOCKS;
(void)CLOCK_EnableClock(s_enetClock[instance]);