0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

【御芯微UCM108E开发板试用体验】二次开发代码启动分析

开发板试用精选 来源:开发板试用 作者:电子发烧友论坛 2022-11-24 17:05 次阅读

本文来源电子发烧友社区,作者:许鹏虎, 帖子地址:https://bbs.elecfans.com/jishu_2286915_1_1.html

UCM108E二次开发代码启动分析

简介

UCM108E内置了一颗RISC-V核心的UC8188MCU,所以其实也是在分析UC8188的启动过程。UC8188 是一款高性能 MCU GNSS 多模卫星导航接收机 SoC 芯片。 芯片集成了 RISCV 32 位通用处理器, 数字基带处理器, 射频前端, 具有 4Mb 内嵌的闪存。 拥有 SPI、I2CUARTx2 以及其它丰富的外设。

启动过程分析

  1. MCU启动一般情况下是从reset中断开始的,我们拿到的这颗MCU也是这样,找到它的启动汇编代码,找到reset中断入口

XoLRjU.md.png

  1. 分析这段启动代码
/* reset 中断入口 */
reset_handler:
  csrw mtvec, x0
  csrci  mstatus, 0x08
  /* 1. 将所有寄存器置位为0 set all registers to zero */
  mv  x1, x0
  mv  x2, x1
  mv  x3, x1
  mv  x4, x1
  mv  x5, x1
  mv  x6, x1  
  mv  x7, x1 
  mv  x8, x1  
  mv  x9, x1 
  mv x10, x1
  mv x11, x1
  mv x12, x1
  mv x13, x1
  mv x14, x1
  mv x15, x1
  mv x16, x1
  mv x17, x1
  mv x18, x1
  mv x19, x1
  mv x20, x1
  mv x21, x1
  mv x22, x1
  mv x23, x1
  mv x24, x1
  mv x25, x1
  mv x26, x1
  mv x27, x1
  mv x28, x1
  mv x29, x1
  mv x30, x1
  mv x31, x1

#ifdef ARCH_RISCV_FPU
  fssr    x0
  fmv.s.x f0, x0
  fmv.s.x f1, x0
  fmv.s.x f2, x0
  fmv.s.x f3, x0
  fmv.s.x f4, x0
  fmv.s.x f5, x0
  fmv.s.x f6, x0
  fmv.s.x f7, x0
  fmv.s.x f8, x0
  fmv.s.x f9, x0
  fmv.s.x f10,x0
  fmv.s.x f11,x0
  fmv.s.x f12,x0
  fmv.s.x f13,x0
  fmv.s.x f14,x0
  fmv.s.x f15,x0
  fmv.s.x f16,x0
  fmv.s.x f17,x0
  fmv.s.x f18,x0
  fmv.s.x f19,x0
  fmv.s.x f20,x0
  fmv.s.x f21,x0
  fmv.s.x f22,x0
  fmv.s.x f23,x0
  fmv.s.x f24,x0
  fmv.s.x f25,x0
  fmv.s.x f26,x0
  fmv.s.x f27,x0
  fmv.s.x f28,x0
  fmv.s.x f29,x0
  fmv.s.x f30,x0
  fmv.s.x f31,x0
#endif

  /* 2. 初始化堆栈 stack initilization */
  la   x2, _stack_start


_start:
  .global _start
  
  /* 3. 将bss段清零 clear BSS */
  la x26, _bss_start
  la x27, _bss_end

  bge x26, x27, zero_loop_end

zero_loop:
  sw x0, 0(x26)
  addi x26, x26, 4
  ble x26, x27, zero_loop
zero_loop_end:

  /* 4. 运行全局初始化函数 Run global initialization functions */
  li a0, 1                      /* set app mode */
  call  set_program_type
  
  call  boot_noop
  call  boot_strap /* 关闭全局中断 配置时钟和XIP */
  call  __libc_init_array
  j main_entry   /* 跳转到main_entry 在下面*/
.section .crt0, "ax" 

main_entry:
  addi   x10, x0, 0
  /* Baud Rate 156250 
  *clock divider, SYSCLK/156250/16-1
  *5MHZ 1; 50MHZ 19
  * 103.68Mhz clk, 115200 sv model 89
  * 19.6608Mhz clk, VHD model, value 4. VHD
  * 196/2Mhz   VHD model value 84 for 115200
  */
  //addi   x11, x0, 84 //98Mhz, 1152000 for sim
  addi   x11, x0, 70  //131.072Mhz, 115200 for sim
  //addi   x11, x0, 22 //26M DCXO, just leave it here, not necessary
  //jal  uart_set_cfg 
  
  /* jump to main program entry point (argc = argv = 0) */
  addi x10, x0, 0
  addi x11, x0, 0
  jal x1, entry   /* 跳转到entry函数 */

  jal  uart_wait_tx_done;

  /* if program exits call exit routine from library */
  jal  x1, exit
  1. 通过以上的分析,我们看到最后是跳转到entry函数去了,这个entry就是rt-thread的入口函数,接下来,我们看在这个函数里做了哪些事情

XoLXuD.md.png

  1. 在entry函数里面其实就是调用了rtthread_startup()函数,然后,我们重点分析一下这个函数里面都做了哪些事情
int rtthread_startup(void)
{
    // 关闭全局中断
    rt_hw_interrupt_disable();

    /* board level initialization
     * NOTE: please initialize heap inside board initialization.
     * 板子相关的初始化,主要是启动了systick
     */
    rt_hw_board_init();

    /* show RT-Thread version */
    rt_show_version();

    /* 系统定时器初始化,后续的任务切换调度都会用到这个timer,timer system initialization */
    rt_system_timer_init();

    /* 初始化系统调度器 scheduler system initialization */
    rt_system_scheduler_init();

#ifdef RT_USING_SIGNALS
    /* signal system initialization */
    rt_system_signal_init();
#endif

    /* 创建main线程并启动 create init_thread */
    rt_application_init();

    /* 创建timer线程并启动 timer thread initialization */
    rt_system_timer_thread_init();

    /* 创建空闲线程并启动 idle thread initialization */
    rt_thread_idle_init();

#ifdef RT_USING_SMP
    rt_hw_spin_lock(&_cpus_lock);
#endif /*RT_USING_SMP*/

    /* 启动调度器 start scheduler */
    rt_system_scheduler_start();

    /* never reach here */
    return 0;
}
  1. 通过对以上的分析,我们大概知道rt-thread创建了几个必要的线程并启动了调度器,这个时候就会启动刚才创建的线程,其中用户关心的则是main线程,我们看下main线程里面做了哪些工作
/* the system main thread */
void main_thread_entry(void* parameter)
{
    extern int main(void);

#ifdef RT_USING_COMPONENTS_INIT
    /* RT-Thread components initialization */
    rt_components_init();
#endif

#ifdef RT_USING_SMP
    rt_hw_secondary_cpu_up();
#endif
    /* invoke system main function */
#if defined(__CC_ARM) || defined(__CLANG_ARM)
    {
        extern int $Super$$main(void);
        $Super$$main(); /* for ARMCC. */
    }
#elif defined(__ICCARM__) || defined(__GNUC__) || defined(__TASKING__)
    main();  // 运行main函数
#endif
}
  1. 其实这个线程最终是为了调用main函数,也就是我们用户编程的入口函数
int main(void)
{
        int_disable();
        REG_INT_PEND = 0x0;
#ifdef _WTG_OPEN_
        wdt_init(UC_WATCHDOG, 5000);
        wdt_enable(UC_WATCHDOG);
#endif
        InitUart(UART_BSP_115200);
        GnssStart(get_pos, 0x7f, FALSE, NULL);
        
        g_hTaskUartTx = rt_thread_create("Task Uart Tx", TaskUartTx, NULL, TSK_STACK_SIZE_UART_TX, 10, 10);
        
        if(g_hTaskUartTx == RT_NULL)
                printf("tx task create failed!rn");
        else
        {
                rt_thread_startup(g_hTaskUartTx);
                printf("tx task is start!rn");
        }
        
        g_hTaskUartRx = rt_thread_create("Task Uart Rx", TaskUartRx, NULL, TSK_STACK_SIZE_UART_RX, 10, 10);
        
        if(g_hTaskUartRx == RT_NULL)
                printf("rx task create failed!rn");
        else
        {
                rt_thread_startup(g_hTaskUartRx);
                printf("rx task is start!rn");
        }
#ifdef _WTG_OPEN_
        wdt_feed(UC_WATCHDOG);
#endif
}
  1. 分析到这里我们应该清楚的知道UCM108E从上电到main的整个运行流程了。

如果大家对rt-thread感兴趣,可以访问官网获取更多学习资料。后续还会分享RISC-V任务切换相关知识。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 御芯微
    +关注

    关注

    4

    文章

    55

    浏览量

    3314
  • 开发板试用
    +关注

    关注

    3

    文章

    301

    浏览量

    2038
  • UCM108E
    +关注

    关注

    0

    文章

    13

    浏览量

    142
收藏 人收藏

    评论

    相关推荐

    追加名额丨米尔瑞RK3576开发板有奖试用

    米尔与瑞合作发布的新品基于瑞RK3576应用处理器的MYD-LR3576开发板免费试用
    的头像 发表于 11-22 01:00 16次阅读
    追加名额丨米尔瑞<b class='flag-5'>芯</b><b class='flag-5'>微</b>RK3576<b class='flag-5'>开发板</b>有奖<b class='flag-5'>试用</b>

    【迅为】瑞RK3588开发板RK3568开发板区别及优势

    RK3568开发板
    的头像 发表于 11-18 14:19 144次阅读
    【迅为】瑞<b class='flag-5'>芯</b><b class='flag-5'>微</b>RK3588<b class='flag-5'>开发板</b>RK3568<b class='flag-5'>开发板</b>区别及优势

    有奖丨米尔 瑞RK3576开发板免费试用

    米尔与瑞合作发布的新品基于瑞RK3576应用处理器的MYD-LR3576开发板免费试用
    的头像 发表于 11-12 01:00 153次阅读
    有奖丨米尔 瑞<b class='flag-5'>芯</b><b class='flag-5'>微</b>RK3576<b class='flag-5'>开发板</b>免费<b class='flag-5'>试用</b>

    有奖试用!!RA-Eco-RA4E2-64PIN-V1.0开发板试用活动开始报名

    有奖试用!!RA-Eco-RA4E2-64PIN-V1.0开发板试用活动开始报名
    的头像 发表于 11-09 01:02 118次阅读
    有奖<b class='flag-5'>试用</b>!!RA-Eco-RA4<b class='flag-5'>E</b>2-64PIN-V1.0<b class='flag-5'>开发板</b><b class='flag-5'>试用</b>活动开始报名

    RK3568开发板Linux编译报错404怎么办?触觉智能教你轻松解决

    本文介绍瑞RK3568主板/开发板SDK编译流程和编译报错404的解决方法,使用触觉智能EVB3568鸿蒙开发板演示,具有丰富的视频输入输出接口(HDMI/eDP/MIPI/LVD
    的头像 发表于 11-05 11:02 237次阅读
    瑞<b class='flag-5'>芯</b><b class='flag-5'>微</b>RK3568<b class='flag-5'>开发板</b>Linux编译报错404怎么办?触觉智能教你轻松解决

    如何使用Air780E开发板?看这篇就够了!

    对 Air780E 模块进行性能评估,功能调试,软件开发等用途 开发板配置 IO 口默认电平 3.3V (1.8V 可调) 支持 USB 5V 直接供电 自弹式 Micro SIM
    的头像 发表于 10-23 17:07 286次阅读
    如何使用Air780<b class='flag-5'>E</b><b class='flag-5'>开发板</b>?看这篇就够了!

    什么~FPGA可以自行二次开发了?

    什么!FPGA可以自行二次开发了? 目前市场上的标准采集卡通常不支持用户自行开发FPGA。但因为应用环境的需要,不仅仅只需要单一的数据采集流程,往往还需要在其中嵌入更复杂的运行和分析逻辑。为了解
    的头像 发表于 10-14 15:47 181次阅读
    什么~FPGA可以自行<b class='flag-5'>二次开发</b>了?

    【RA-Eco-RA0E1-32PIN-V1.0开发板试用】点灯

    RA0E1开发板试用报告 试用单位 : 个人开发板 : RA0E1 一、背景 很荣幸获得由电子发
    发表于 09-24 11:54

    RK3588开发板Linux系统添加自启动命令的方法,深圳触觉智能Arm嵌入式鸿蒙硬件方案商

    本文适用所有Linux系统的开发板、主板添加自启动命令的方法,本次使用了触觉智能的EVB3588开发板演示,搭载了瑞RK3588旗舰芯片
    的头像 发表于 09-19 09:32 567次阅读
    瑞<b class='flag-5'>芯</b><b class='flag-5'>微</b>RK3588<b class='flag-5'>开发板</b>Linux系统添加自<b class='flag-5'>启动</b>命令的方法,深圳触觉智能Arm嵌入式鸿蒙硬件方案商

    ARMxy ARM工业边缘计算网关带Ubuntu OS支持二次开发

    ARMxy系列工业边缘计算网关,搭载Ubuntu操作系统,不仅提供了强大的数据处理能力,而且通过支持二次开发,为企业提供了定制化解决方案的可能性。本文将深入探讨ARMxy网关的技术特性、Ubuntu
    的头像 发表于 08-19 15:32 335次阅读
    ARMxy ARM工业边缘计算网关带Ubuntu OS支持<b class='flag-5'>二次开发</b>

    条码维码扫码模组,支持二次开发嵌入吗?

    维码扫码模组的技术支持、应用领域及其在二次开发嵌入中的优势和挑战。扫码模组技术支持与应用领域条码维码扫码模组采用了先进的CMOS影像技术和智能图像识别算法,能
    的头像 发表于 08-14 15:44 235次阅读
    条码<b class='flag-5'>二</b>维码扫码模组,支持<b class='flag-5'>二次开发</b>嵌入吗?

    边缘计算智能盒子如何助力HMI设备实现二次开发

    HMI(Human-MachineInterface)又称人机界面,是用户与机器之间交互和通信的媒介。今天带你了解智能盒子如何助力HMI设备实现二次开发?HMI设备被广泛应用在工业自动化中,具有显示
    的头像 发表于 07-10 18:52 402次阅读
    边缘计算智能盒子如何助力HMI设备实现<b class='flag-5'>二次开发</b>?

    5G千兆双核物联网模块 OpenWrt二次开发

    HLK-RM20是海凌科2024年推出的首款路由模块,多端口5G千兆网关,双核ARM处理器,1.3GHz主频,支持Openwrt二次开发。高性能、高速率、低延迟,功能强大,应用广泛。
    的头像 发表于 06-03 14:23 1015次阅读
    5G千兆双核物联网模块 OpenWrt<b class='flag-5'>二次开发</b>

    个性化定制,提升运营效率:SAP二次开发引领企业数字化转型

    SAP二次开发引领企业数字化转型 随着企业竞争的日益激烈,定制化管理方案成为企业实现差异化竞争的重要工具。SAP作为全球领先的企业管理软件提供商,SAP二次开发服务应运而生,为企业提供个性定制
    的头像 发表于 02-18 13:29 383次阅读

    明德扬PCIE开发板系列XILINX-K7试用体验-第

    本文为明德扬原创文章,转载请注明出处!作者:Vito 明德扬PCIE开发板系列XILINX-K7试用体验-第篇 第周的试用计划是实现常见
    的头像 发表于 11-29 15:39 3217次阅读
    明德扬PCIE<b class='flag-5'>开发板</b>系列XILINX-K7<b class='flag-5'>试用</b>体验-第<b class='flag-5'>二</b>篇