上一篇文章,点灯后无法保持状态,本文来解决这个问题。
主要目的为:移植 do_lowlevel_init()
函数实现持续点灯。(三篇文章了,居然还在点灯 0.0)
1. get_reset_status()
该函数非常重要,获取 reset status,判断 device 是初次 boot 还是 wake-up,但是原有函数寄存器不支持,所以需要修改。
static uint32_t exynos4_get_reset_status(void)
{
#ifdef CONFIG_XHR4412
struct exynos4x12_power *power =
(struct exynos4x12_power *)samsung_get_base_power();
#else
struct exynos4_power *power =
(struct exynos4_power *)samsung_get_base_power();
#endif
return power->inform1;
}
2. set_ps_hold_ctrl()
该函数默认只支持了 exynos5 ,我们直接改为我们需要的。
#ifdef CONFIG_XHR4412
static void exynos4x12_set_ps_hold_ctrl(void)
{
struct exynos4x12_power *power =
(struct exynos4x12_power *)samsung_get_base_power();
/* value: 1000000000B */
setbits_le32(&power->ps_hold_control, EXYNOS_PS_HOLD_CONTROL_DATA_HIGH);
/**
* GPX0PUD register
*
* 0x0 = Disables Pull-up/Pull-down
* 0x1 = Enables Pull-down
* 0x2 = Reserved
* 0x3 = Enables Pull-up
*/
writel(0x3, (unsigned int *)0x11000c08);
}
#endif
void set_ps_hold_ctrl(void)
{
#ifdef CONFIG_XHR4412
if (cpu_is_exynos4())
exynos4x12_set_ps_hold_ctrl();
#else
if (cpu_is_exynos5())
exynos5_set_ps_hold_ctrl();
#endif
else while (1) ;
}
移植到这里已经可以永久点灯了。
这里要说明一下,前面会自动 reset 的原因并不是 watchdog,竟然是必须拉高 GPX0_0,原因还没有深究。
3. system_clock_init()
这里虽然只有一个函数,但是改动很大,就不细讲了,以后有时间再添加到这里或是专门写文描述。
4. mem_ctrl_init()
只改动了一些 timing,用闪灯测试一下 memory 是否初始化成功:
void led_test(void)
{
volatile unsigned long i = 0;
volatile unsigned long * ram;
volatile unsigned long * GPL2CON;
volatile unsigned long * GPL2DAT;
GPL2CON = (volatile unsigned long *)0x11000100;
GPL2DAT = (volatile unsigned long *)0x11000104;
ram = (volatile unsigned long *)0x43E00000;
*GPL2CON = 1;
*GPL2DAT = 0;
*ram = 1;
while (1)
{
*GPL2DAT = *ram;
*ram ^= 1;
for(i = 0;i < 500000;i++);
}
}
可以看出地址 0x43E00000 已经能够正常使用,memory 初始化成功!
5. 总结
memory 初始化完成后就可以将完整的 u-boot 重定位到 memory 中运行,下一篇文章介绍重定位与 UART 的初始化。
仍然有嵌入式大神鲁迅的名言:只要有 printf ,就没有调不出来的程序,如果有,那就一行一 printf 。