RK30SDK系统重启源码分析

发布时间:2023-05-23  

Linux系统重启的最底层函数是arch_reset,这是一个全局的函数指针变量,定义在 arch/arm/mach-rk30/include/mach/system.h中:

extern void (*arch_reset)(char, const char *);

注意,这是一个变量声明,类型为函数指针。并不是函数的声明!它的实现在mach-rk30/reset.c中:


static void rk30_arch_reset(char mode, const char *cmd)
{
    u32 boot_flag = 0;
    u32 boot_mode = BOOT_MODE_REBOOT;

    if (cmd) {
        if (!strcmp(cmd, "loader") || !strcmp(cmd, "bootloader"))
            boot_flag = SYS_LOADER_REBOOT_FLAG + BOOT_LOADER;
        else if(!strcmp(cmd, "recovery"))
            boot_flag = SYS_LOADER_REBOOT_FLAG + BOOT_RECOVER;
        else if (!strcmp(cmd, "charge"))
            boot_mode = BOOT_MODE_CHARGE;
    } else {
        if (system_state != SYSTEM_RESTART)
            boot_mode = BOOT_MODE_PANIC;
    }
    writel_relaxed(boot_flag, RK30_PMU_BASE + PMU_SYS_REG0);    // for loader
    writel_relaxed(boot_mode, RK30_PMU_BASE + PMU_SYS_REG1);    // for linux
    dsb();
    /* disable remap */
    writel_relaxed(1 << (12 + 16), RK30_GRF_BASE + GRF_SOC_CON0);
    /* pll enter slow mode */
    writel_relaxed(PLL_MODE_SLOW(APLL_ID) | PLL_MODE_SLOW(CPLL_ID) | PLL_MODE_SLOW(GPLL_ID), RK30_CRU_BASE + CRU_MODE_CON);
    dsb();
    writel_relaxed(0xeca8, RK30_CRU_BASE + CRU_GLB_SRST_SND);
    dsb();
}

void (*arch_reset)(char, const char *) = rk30_arch_reset;


注意,平台的真正实现在rk30_arch_reset中,然后赋值给指针变量arch_reset。 这样,你在其它地方就能把arch_reset当成函数一样任意调用了。为什么要这样?为了封装呀,不同的CPU上可能有不同的实现,但最后暴露给上层的接口始终是arch_reset。

rk30_arch_reset的内部实现很有意思,第一个参数mode没有用到,参数cmd是一个字符串,"loader" "bootloader"应该是通常的重新启动进入系统;"recovery"应该是重启进入recovery模式, “charge”应该是重启进入充电界面(相当于关机?)

下面来做个简单测试,随便找个驱动程序,在其probe函数里面加入下面的代码(记得要包含头文件哦),强行重启到recovery模式:

printk("++++++++reboot to recovery beginn");
printk("++++++++reboot to recovery beginn");
arch_reset(0, "recovery");
printk("++++++++reboot to recovery endn");
printk("++++++++reboot to recovery endn");

上电测试,串口中能打印出下面的信息,可以看出在arch_reset之后,系统确实重启了:

[    1.491413] ++++++++reboot to recovery begin
[    1.495691] ++++++++reboot to recovery begin
DDR Version 1.00 20120529
In
DDR3
freq
300MHz
config state
pctl
phy
mem

分析了这么多,那就顺便再看一下S3C2410里面的实现吧, arch_reset的定义在mach-s3c2410/system-reset.h中:

extern void (*s3c24xx_reset_hook)(void);

static void
arch_reset(char mode, const char *cmd)
{
    if (mode == 's') {
        cpu_reset(0);
    }

    if (s3c24xx_reset_hook)
        s3c24xx_reset_hook();

    arch_wdt_reset();

    /* we'll take a jump through zero as a poor second */
    cpu_reset(0);
}

这里又不同于RK30SDK,arch_reset被定义成了一个函数,它在内部又调用了s3c24xx_reset_hook,而s3c24xx_reset_hook却被定义成了一个函数指针变量,估计不同的CPU有不同的代码,让我们继续寻找s3c24xx_reset_hook:


./mach-s3c2416/s3c2416.c:87:    s3c24xx_reset_hook = s3c2416_hard_reset;
./mach-s3c2412/s3c2412.c:169:    s3c24xx_reset_hook = s3c2412_hard_reset;
./mach-s3c2443/s3c2443.c:68:    s3c24xx_reset_hook = s3c2443_hard_reset;

看到了吧,这3种CPU里面分别对应不同的hook函数,先看看s3c2416_hard_reset的实现:

static void s3c2416_hard_reset(void)
{
    __raw_writel(S3C2443_SWRST_RESET, S3C2443_SWRST);
}

再看看s3c2412_hard_reset的实现:

static void s3c2412_hard_reset(void)
{
    /* errata "Watch-dog/Software Reset Problem" specifies that
     * this reset must be done with the SYSCLK sourced from
     * EXTCLK instead of FOUT to avoid a glitch in the reset
     * mechanism.
     *
     * See the watchdog section of the S3C2412 manual for more
     * information on this fix.
     */

    __raw_writel(0x00, S3C2412_CLKSRC);
    __raw_writel(S3C2412_SWRST_RESET, S3C2412_SWRST);

    mdelay(1);
}

还有s3c2443_hard_reset的实现:

static void s3c2443_hard_reset(void)
{
    __raw_writel(S3C2443_SWRST_RESET, S3C2443_SWRST);
}

仔细观察,其实都大同小异,应该是2410系列中不同型号的CPU在寄存器上有些细微的差别,或者不同的实现方式。

不过这里arch_reset的参数的用法不同于RK30SDK,这里用了第一个参数mode, 第二个参数cmd却没有使用,这里先留个问题吧,后续再去深究这2个参数的用法。


文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

相关文章

    ST官方基于米尔STM32MP135开发板培训课程(一); 本文将以Myirtech的MYD-YF13X以及STM32MP135F-DK为例,讲解如何使用STM32CubeMX结合......
    如何使用示波器测试电池的瞬态能量;今天为大家带来用示波器的函数计算功能,测试一个电池的瞬态能量。 瞬态能量测试概念:在规定的时间内,被测产品瞬间释放了多少能量。如下图的阴影部分面积。 如何......
    ST官方基于米尔STM32MP135开发板培训课程(一);本文将以Myirtech的MYD-YF13X以及M32MP135F-DK为例,讲解如何使用M32CubeMX结合Developer......
    接收端口接收人家发送过来的数据。可以同时进行,这叫串口。两台设备要能够进行通信的话,一定要有相同的配置,波特率,检验位,停止位一定要一致。这些名词的具体概念大家自行百度,我这里只讲该如何在MSP432上实......
    STM32WB55_NUCLEO开发(3)----手机与STM32WB直接配对;概述 本篇文章主要介绍如何使用STM32CubeMX对生成STM32WB工程,并通过手机APP与其配对。 硬件......
    /stm32cubemx 具体安装,使用方法可以参看我之前整理的专栏文章:【专栏】STM32CubeMX系列教程 提示:软件包里包含FreeRTOS源码,但不是最新的。 2.3 FreeRTOS源码 上面......
    印信息输出方法。 本篇是第一篇,我们先介绍最常见的输出打印信息方式,即利用 MCU 芯片内的硬件 UART 外设。本篇其实并不是要具体介绍 UART 外设模块使用方法,而是重点分析 IAR 下是如何联系 C 标准......
    资深工程师解说:小钢炮程序该如何烧写; 1、小钢炮的使用的MCU是STM32F401RET6,stm32比较常用的烧写方式主要有JLINK、ULINK、STLINK、串口方式,根据......
    中可以操作单片机的那一部分就可以了,今天我们要说的就是C语言我们该如何来点亮并控制led灯。 首先来给你大家上电路图,相信大部分同学都可以看懂,如果看不懂的也没关系,因为篇幅有限就不给大家长篇大论了,相信......
    STM32WB55_NUCLEO开发(6)----手机与STM32WB通过配对后进行数值比较;概述 本篇文章主要介绍如何使用STM32CubeMX对生成STM32WB工程,并通过与STM32WB配对......

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>