[DemoCode下载] 多引导启动实现方式

[复制链接]
 楼主| wanduzi 发表于 2024-2-28 19:10 | 显示全部楼层 |阅读模式
TI, ge, RT, ST, se, ar
  1. /****************************************************************************//**
  2. * [url=home.php?mod=space&uid=288409]@file[/url]     main.c
  3. * [url=home.php?mod=space&uid=895143]@version[/url]  V0.10
  4. * [url=home.php?mod=space&uid=247401]@brief[/url]    Implement a multi-boot system to boot from different applications in APROM.
  5. *           A LDROM code and 4 APROM code are implemented in this sample code.
  6. *
  7. * SPDX-License-Identifier: Apache-2.0
  8. * [url=home.php?mod=space&uid=17282]@CopyRight[/url] (C) 2018 Nuvoton Technology Corp. All rights reserved.
  9. *****************************************************************************/
  10. #include <stdio.h>
  11. #include "NuMicro.h"


  12. #if !defined(__ICCARM__) && !defined(__GNUC__)
  13. extern uint32_t Image$RO$Base;
  14. #endif

  15. void SYS_Init(void)
  16. {
  17.     /*---------------------------------------------------------------------------------------------------------*/
  18.     /* Init System Clock                                                                                       */
  19.     /*---------------------------------------------------------------------------------------------------------*/
  20.     /* Unlock protected registers */
  21.     SYS_UnlockReg();

  22.     /* Enable HIRC clock */
  23.     CLK_EnableXtalRC(CLK_PWRCTL_HIRCEN_Msk);

  24.     /* Wait for HIRC clock ready */
  25.     CLK_WaitClockReady(CLK_STATUS_HIRCSTB_Msk);

  26.     /* Select HCLK clock source as HIRC and and HCLK source divider as 1 */
  27.     CLK_SetHCLK(CLK_CLKSEL0_HCLKSEL_HIRC, CLK_CLKDIV0_HCLK(1));

  28.     /* Set PLL to Power-down mode and PLLSTB bit in CLK_STATUS register will be cleared by hardware.*/
  29.     CLK_DisablePLL();

  30.     /* Enable UART module clock */
  31.     CLK_EnableModuleClock(UART0_MODULE);

  32.     /* Select UART module clock source as HIRC and UART module clock divider as 1 */
  33.     CLK_SetModuleClock(UART0_MODULE, CLK_CLKSEL1_UART0SEL_HIRC, CLK_CLKDIV0_UART0(1));

  34.     /*---------------------------------------------------------------------------------------------------------*/
  35.     /* Init I/O Multi-function                                                                                 */
  36.     /*---------------------------------------------------------------------------------------------------------*/
  37.     /* Set PB multi-function pins for UART0 RXD=PB.12 and TXD=PB.13 */
  38.     SYS->GPB_MFPH = (SYS->GPB_MFPH & ~(SYS_GPB_MFPH_PB12MFP_Msk | SYS_GPB_MFPH_PB13MFP_Msk))
  39.                     |(SYS_GPB_MFPH_PB12MFP_UART0_RXD | SYS_GPB_MFPH_PB13MFP_UART0_TXD);

  40.     /* Lock protected registers */
  41.     SYS_LockReg();
  42. }

  43. /**
  44. * @brief    Routine to get a char
  45. * @param    None
  46. * @returns  Get value from UART debug port or semihost
  47. * [url=home.php?mod=space&uid=1543424]@Details[/url]  Wait UART debug port or semihost to input a char.
  48. */
  49. static char GetChar(void)
  50. {
  51.     while(1)
  52.     {
  53.         if ((UART0->FIFOSTS & UART_FIFOSTS_RXEMPTY_Msk) == 0)
  54.         {
  55.             return (UART0->DAT);
  56.         }
  57.     }
  58. }

  59. /*
  60. * @returns     Send value from UART debug port
  61. * @details     Send a target char to UART debug port .
  62. */
  63. static void SendChar_ToUART(int ch)
  64. {
  65.     while (UART0->FIFOSTS & UART_FIFOSTS_TXFULL_Msk);

  66.     UART0->DAT = ch;
  67.     if(ch == '\n')
  68.     {
  69.         while (UART0->FIFOSTS & UART_FIFOSTS_TXFULL_Msk);
  70.         UART0->DAT = '\r';
  71.     }
  72. }

  73. static void PutString(char *str)
  74. {
  75.     while (*str != '\0')
  76.     {
  77.         SendChar_ToUART(*str++);
  78.     }
  79. }

  80. static void PutHexNumber(uint32_t u32Num)
  81. {
  82.     int32_t i = 28;
  83.     uint32_t Digit;
  84.     PutString("0x");
  85.     do
  86.     {
  87.         Digit = (u32Num >> i) & 0x0F;
  88.         if(Digit != 0)
  89.             break;
  90.         i = i - 4;
  91.     }
  92.     while(i!=0);

  93.     while (i >= 0)
  94.     {
  95.         Digit =  (u32Num >> i) & 0x0F;
  96.         if(Digit < 10)
  97.             SendChar_ToUART('0'+Digit);
  98.         else
  99.             SendChar_ToUART('A'+Digit-10);
  100.         i = i - 4;
  101.     }
  102. }
  103. #ifdef __GNUC__                        /* for GNU C compiler */
  104. /**
  105. * @brief       Hard fault handler
  106. * @param[in]   stack pointer points to the dumped registers in SRAM
  107. * [url=home.php?mod=space&uid=266161]@return[/url]      None
  108. * @details     Replace while(1) at the end of this function with chip reset if WDT is not enabled for end product
  109. */
  110. void Hard_Fault_Handler(uint32_t stack[])
  111. {
  112.     PutString("In Hard Fault Handler\n");
  113.     while(1);
  114. }
  115. #endif
  116. int32_t main(void)
  117. {
  118.     uint8_t u8Ch;
  119.     uint32_t u32Data;


  120.     /* Init System, IP clock and multi-function I/O. */
  121.     SYS_Init();
  122.    
  123.     /* Unlock protected registers to operate FMC ISP function */
  124.     SYS_UnlockReg();

  125.     /* Configure UART0: 115200, 8-bit word, no parity bit, 1 stop bit. */
  126.     UART_Open(UART0, 115200);

  127.     /* Checking if target device supports the feature */
  128.     if( (GET_CHIP_SERIES_NUM == CHIP_SERIES_NUM_I) || (GET_CHIP_SERIES_NUM == CHIP_SERIES_NUM_G) )
  129.     {
  130.         /* Checking if flash size matches with target device */
  131.         if(FMC_FLASH_PAGE_SIZE != 2048)
  132.         {
  133.             /* FMC_FLASH_PAGE_SIZE is different from target device's */
  134.             printf("Please enable the compiler option - PAGE_SIZE_2048 in fmc.h\n");
  135.             while(SYS->PDID);
  136.         }
  137.     }
  138.     else
  139.     {
  140.         if(FMC_FLASH_PAGE_SIZE != 512)
  141.         {
  142.             /* FMC_FLASH_PAGE_SIZE is different from target device's */
  143.             printf("Please disable the compiler option - PAGE_SIZE_2048 in fmc.h\n");
  144.             while(SYS->PDID);
  145.         }
  146.     }

  147.     /* Enable FMC ISP function */
  148.     FMC_Open();

  149.     /*
  150.         This sample code shows how to boot with different firmware images in APROM.
  151.         In the code, VECMAP is used to implement multi-boot function. Software set VECMAP
  152.         to remap page of VECMAP to 0x0~0x1ff.
  153.         NOTE: VECMAP only valid when CBS = 00'b or 10'b.

  154.         The sample code didn't use stanard C library for UART message due to the size of LDROM.

  155.         To use this sample code, please:
  156.         1. Build all targets and download to device individually. The targets are:
  157.             FMC_MultiBoot, RO=0x0, ICE download algorithm to APROM
  158.             FMC_Boot0, RO=0x4000, ICE download algorithm to APROM
  159.             FMC_Boot1, RO=0x8000, ICE download algorithm to APROM
  160.             FMC_Boot2, RO=0xC000, ICE download algorithm to APROM
  161.             FMC_Boot3, RO=0x10000, ICE download algorithm to APROM
  162.             FMC_BootLD, RO=0x100000. ICE download algorithm to LDROM
  163.         2. Reset MCU to execute FMC_MultiBoot.
  164.     */

  165.     PutString("\n\n");
  166.     PutString("+---------------------------+\n");
  167.     PutString("|   Multi-Boot Sample Code  |\n");
  168.     PutString("+---------------------------+\n");
  169. #if defined(__BASE__)
  170.     PutString("Boot from 0\n");
  171. #endif
  172. #if defined(__BOOT0__)
  173.     PutString("Boot from 0x4000\n");
  174. #endif
  175. #if defined(__BOOT1__)
  176.     PutString("Boot from 0x8000\n");
  177. #endif
  178. #if defined(__BOOT2__)
  179.     PutString("Boot from 0xC000\n");
  180. #endif
  181. #if defined(__BOOT3__)
  182.     PutString("Boot from 0x10000\n");
  183. #endif
  184. #if defined(__LDROM__)
  185.     PutString("Boot from 0x100000\n");
  186. #endif

  187.     u32Data = FMC_GetVECMAP();
  188.     PutString("VECMAP = ");
  189.     PutHexNumber(u32Data);
  190.     PutString("\n");

  191.     PutString("Select one boot image: \n");
  192. #if !defined(__GNUC__)
  193.     PutString("[0] Boot 0, base = 0x4000\n");
  194. #endif
  195.     PutString("[1] Boot 1, base = 0x8000\n");
  196. #if !defined(__GNUC__)
  197.     PutString("[2] Boot 2, base = 0xC000\n");
  198. #endif
  199.     PutString("[3] Boot 3, base = 0x10000\n");
  200. #if !defined(__GNUC__)
  201.     PutString("[4] Boot 4, base = 0x100000\n");
  202. #endif
  203.     PutString("[Others] Boot, base = 0x0\n");

  204.     u8Ch = GetChar();//getchar();

  205.     switch (u8Ch)
  206.     {
  207. #if !defined(__GNUC__)
  208.     case '0':
  209.         FMC_SetVectorPageAddr(0x4000);
  210.         break;
  211. #endif

  212.     case '1':
  213.         FMC_SetVectorPageAddr(0x8000);
  214.         break;

  215. #if !defined(__GNUC__)
  216.     case '2':
  217.         FMC_SetVectorPageAddr(0xC000);
  218.         break;
  219. #endif

  220.     case '3':
  221.         FMC_SetVectorPageAddr(0x10000);
  222.         break;
  223. #if !defined(__GNUC__)

  224.     case '4':
  225.         FMC_SetVectorPageAddr(0x100000);
  226.         break;
  227. #endif

  228.     default:
  229.         FMC_SetVectorPageAddr(0x0);
  230.         break;
  231.     }
  232.     if (g_FMC_i32ErrCode != 0)
  233.     {
  234.         printf("FMC_SetVectorPageAddr failed!\n");
  235.         while (1);
  236.     }

  237.     /* Reset CPU only to reset to new vector page */
  238.     SYS_ResetCPU();

  239.     /* Reset System to reset to new vector page. */
  240.     //NVIC_SystemReset();

  241.     /* Disable ISP function */
  242.     FMC_Close();

  243.     /* Lock protected registers */
  244.     SYS_LockReg();

  245.     PutString("\nDone\n");

  246.     while (SYS->PDID) __WFI();

  247. }

  248. /*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/


 楼主| wanduzi 发表于 2024-2-28 19:10 | 显示全部楼层
这个程序是为了实现一个多引导系统,可以从存储在APROM(应用程序闪存)中的不同应用程序启动。以下是代码的主要功能和组件的总结:

头文件包含:代码包含了必要的头文件,如 stdio.h 和 "NuMicro.h",这些文件很可能包含了程序所需的定义和声明。

系统初始化 (SYS_Init):该函数初始化系统时钟,启用UART时钟,配置UART引脚,并设置UART模块以进行通信。

UART函数 (GetChar, SendChar_ToUART, PutString, PutHexNumber):这些函数处理UART通信,用于发送和接收字符和字符串。

硬件故障处理器:在发生硬件故障时,将调用此函数来处理故障。在提供的代码中,它仅通过UART发送一条消息,然后进入无限循环。

主函数 (main):

系统初始化: 初始化系统,解锁保护寄存器,配置UART通信,并根据芯片系列和闪存页面大小检查设备是否支持某些功能。

FMC(闪存存储控制器)配置: 设置FMC ISP(系统内编程)功能,该功能允许在设备运行时对闪存进行编程。它根据目标设备的闪存页面大小检查和配置FMC设置。

多引导配置: 根据预处理器定义 (__BASE__, __BOOT0__ 等),显示引导选项,读取用户输入以选择引导映像,并相应地使用 FMC_SetVectorPageAddr 函数设置向量页地址。

重置CPU: 调用 SYS_ResetCPU() 重置CPU,以从所选的引导映像开始执行代码。

清理工作: 关闭FMC ISP功能,锁定保护寄存器,并发送一条指示完成的消息。

注释: 代码包含了对各个部分、函数和指令的注释,这有助于理解代码的功能和目的。
 楼主| wanduzi 发表于 2024-2-28 19:10 | 显示全部楼层
总的来说,该代码实现了一个灵活的引导系统,允许从存储在APROM内存中的不同应用程序启动,并提供UART通信以供用户交互和反馈。此外,它利用了FMC模块来配置闪存存储器的设置和多引导功能。
 楼主| wanduzi 发表于 2024-2-28 19:11 | 显示全部楼层
允许从存储在APROM中的不同应用程序中引导,并提供了UART通信以进行用户交互和反馈。此外,它利用了FMC模块来配置Flash存储器设置和多重引导功能。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

154

主题

1857

帖子

3

粉丝
快速回复 在线客服 返回列表 返回顶部