找回密码
 立即注册
查看: 1424|回复: 19

STC8H8K64U单片机bootloader无法跳转app程序

[复制链接]

该用户从未签到

6

主题

16

回帖

148

积分

注册会员

积分
148
发表于 2023-6-29 19:51:00 | 显示全部楼层 |阅读模式
经过验证我已经把外置flash的程序copy到eeprom的0x400地址上,

我在bootloader程序定义:

typedef void (*FunctionPointer)(void);
FunctionPointer entry_app = (FunctionPointer)0x0400;


然后在main函数中执行
entry_app();

并没有和想象中一样会跳转到这个地址执行我的代码。
求大牛们指点一下
回复 送花

使用道具 举报

  • TA的每日心情
    开心
    5 天前
  • 签到天数: 16 天

    [LV.4]偶尔看看III

    16

    主题

    722

    回帖

    2572

    积分

    超级版主

    积分
    2572
    发表于 2023-6-29 20:57:54 | 显示全部楼层
    1、下载时EEPROM设置为多大?
          这关系到EEPROM的地址和ROM地址关系,EEPROM的地址0x400并不一定等于ROM的地址0x400
    2、你存放在外部flash中的代码,在编译时目标地址是多少?
    3、外置flash中的代码中是否有绝对调用(ACALL/LCALL)或者绝度跳转(AJMP/LJMP)指令?

    上面的3点都有可能导致外部flash代码复制到EEPROM后无法正常运行
    回复 支持 反对 送花

    使用道具 举报

    该用户从未签到

    6

    主题

    16

    回帖

    148

    积分

    注册会员

    积分
    148
     楼主| 发表于 2023-6-30 09:15:39 | 显示全部楼层
    zhp 发表于 2023-6-29 20:57
    1、下载时EEPROM设置为多大?
          这关系到EEPROM的地址和ROM地址关系,EEPROM的地址0x400并不一定等于RO ...

    1、eeprom设置40k,片内flash大小是64k,这需要加上这24k的偏移吗,IAP访问eeprom的话我的代码就是放在0x400这个位置
    2、外部代码编译时没有做其他任何设置
    3、也没有调用跳转的命令,就正常编译出来一个bin文件
    回复 支持 反对 送花

    使用道具 举报

    该用户从未签到

    6

    主题

    16

    回帖

    148

    积分

    注册会员

    积分
    148
     楼主| 发表于 2023-6-30 11:35:46 | 显示全部楼层
    本帖最后由 chenyl 于 2023-6-30 11:38 编辑
    zhp 发表于 2023-6-29 20:57
    1、下载时EEPROM设置为多大?
          这关系到EEPROM的地址和ROM地址关系,EEPROM的地址0x400并不一定等于RO ...


    我直接改上面这里启动是可以运行我拷过来的代码的,正常流程跳转的话要怎么改呢
    截图_16880960118897.png

    点评

    zhp
    根据你的情况,你的EEPROM必须设置为64K,让EEPROM和ROM完全重合 才能保证EEPROM的0x400地址对应到ROM的0x400  详情 回复 发表于 2023-6-30 18:07
    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    开心
    5 天前
  • 签到天数: 16 天

    [LV.4]偶尔看看III

    16

    主题

    722

    回帖

    2572

    积分

    超级版主

    积分
    2572
    发表于 2023-6-30 18:07:46 | 显示全部楼层
    chenyl 发表于 2023-6-30 11:35
    我直接改上面这里启动是可以运行我拷过来的代码的,正常流程跳转的话要怎么改呢 ...

    根据你的情况,你的EEPROM必须设置为64K,让EEPROM和ROM完全重合
    才能保证EEPROM的0x400地址对应到ROM的0x400
    回复 支持 反对 送花

    使用道具 举报

    该用户从未签到

    6

    主题

    16

    回帖

    148

    积分

    注册会员

    积分
    148
     楼主| 发表于 2023-6-30 18:39:44 | 显示全部楼层
    zhp 发表于 2023-6-30 18:07
    根据你的情况,你的EEPROM必须设置为64K,让EEPROM和ROM完全重合
    才能保证EEPROM的0x400地址对应到ROM的0 ...

    我刚刚试了,把EEPROM设置大小设置成64K,拷贝应用程序的地址挪到了0x5000,还是没跑起来

    点评

    zhp
    将你的示例代码发出来看一下  详情 回复 发表于 2023-7-1 19:21
    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    开心
    5 天前
  • 签到天数: 16 天

    [LV.4]偶尔看看III

    16

    主题

    722

    回帖

    2572

    积分

    超级版主

    积分
    2572
    发表于 2023-7-1 19:21:13 | 显示全部楼层
    chenyl 发表于 2023-6-30 18:39
    我刚刚试了,把EEPROM设置大小设置成64K,拷贝应用程序的地址挪到了0x5000,还是没跑起来 ...

    将你的示例代码发出来看一下
    回复 支持 反对 送花

    使用道具 举报

    该用户从未签到

    6

    主题

    16

    回帖

    148

    积分

    注册会员

    积分
    148
     楼主| 发表于 2023-7-2 22:29:33 | 显示全部楼层
    zhp 发表于 2023-7-1 19:21
    将你的示例代码发出来看一下
    1. // 定义EEPROM的起始地址和大小
    2. #define EEPROM_START_ADDRESS 0x5000
    3. #define EEPROM_SIZE 0x5000
    4. // 定义接收和发送数据的缓冲区
    5. #define BUFFER_SIZE 256
    6. uint8_t recv_buf[BUFFER_SIZE];
    7. uint8_t send_buf[BUFFER_SIZE];
    8. typedef void (*FunctionPointer)(void);
    9. FunctionPointer entry_app = (FunctionPointer)0x5000;
    10. void IapProgram(int addr, int dat)
    11. {
    12.     IAP_CONTR = 0x80;                           //使能IAP
    13.     IAP_TPS = 12;                               //设置等待参数12MHz
    14.     IAP_CMD = 2;                                //设置IAP写命令
    15.     IAP_ADDRL = addr;                           //设置IAP低地址
    16.     IAP_ADDRH = addr >> 8;                      //设置IAP高地址
    17.     IAP_DATA = dat;                             //写IAP数据
    18.     IAP_TRIG = 0x5a;                            //写触发命令(0x5a)
    19.     IAP_TRIG = 0xa5;                            //写触发命令(0xa5)
    20.     _nop_();
    21.     IapIdle();                                  //关闭IAP功能
    22. }
    23. // 接收一个字节的数据
    24. uint8_t receive_byte() {
    25.         SPDAT = 0xff;
    26.     while((SPSTAT & SPIF) == 0) ;
    27.     SPSTAT = SPIF + WCOL;   //清0 SPIF和WCOL标志
    28.     return (SPDAT);
    29. }
    30. // 定义一个函数从外置SPI Flash中读取数据
    31. void read_flash(uint32_t address, uint8_t *dat, uint32_t sz)
    32. {
    33.         if(sz == 0)   return;
    34.     while(CheckFlashBusy() > 0);        //Flash忙检测
    35.     SPI_CS = 0;                       //enable device
    36.     send_byte(0x03);            //read command
    37.     send_byte(((u8 *)&address)[1]);    //设置起始地址
    38.     send_byte(((u8 *)&address)[2]);
    39.     send_byte(((u8 *)&address)[3]);
    40.     do{
    41.         *dat = receive_byte();       //receive byte and store at buffer
    42.         dat++;
    43.     }while(--sz);                     //read until no_bytes is reached
    44.     SPI_CS = 1;                      //disable device
    45. }
    46. // 定义一个函数将应用程序从外置SPI Flash中拷贝到EEPROM中
    47. void copy_app_to_eeprom() {
    48.             uint32_t app_size;
    49.         uint16_t addr;
    50.         uint16_t rev;
    51.         uint32_t k;
    52.        
    53.         uint32_t offset;
    54.         uint32_t sz;
    55.         uint8_t TEST = 0x55;
    56.        
    57.         Get_App_Size((unsigned int*)&app_size);
    58.        
    59.     // 擦除EEPROM
    60.         for (addr = EEPROM_SIZE; addr <  EEPROM_SIZE+ EEPROM_SIZE; )
    61.         {
    62.                 IapErase(addr);
    63.                 addr = addr+512;
    64.             }
    65.        
    66.         app_size = 0x4800;//暂时手动设置读取的大小
    67.         sz = BUFFER_SIZE;
    68.         for (k = 0; k < app_size; ) {
    69.                 offset = 0 + k;
    70.         read_flash(offset, recv_buf, sz);
    71.         for (rev = 0; rev < sz; rev++) {
    72.                 IapProgram(EEPROM_START_ADDRESS + k + rev, recv_buf[rev]);
    73.         }
    74.         k += BUFFER_SIZE;
    75.     }       
    76. }
    77. void SPI_init(void)
    78. {
    79.     P2M0 &= ~0x3e;
    80.         P2M1 &= ~0x3e;
    81.         SPCTL |=  (1 << 7); //忽略 SS 引脚功能,使用 MSTR 确定器件是主机还是从机
    82.     SPCTL |=  (1 << 6); //使能 SPI 功能
    83.     SPCTL &= ~(1 << 5); //先发送/接收数据的高位( MSB)
    84.     SPCTL |=  (1 << 4); //设置主机模式
    85.     SPCTL &= ~(1 << 3); //SCLK 空闲时为低电平,SCLK 的前时钟沿为上升沿,后时钟沿为下降沿
    86.     SPCTL &= ~(1 << 2); //数据 SS 管脚为低电平驱动第一位数据并在 SCLK 的后时钟沿改变数据
    87.     SPCTL = (SPCTL & ~3) | 3;   //SPI 时钟频率选择, 0: 4T, 1: 8T,  2: 16T,  3: 32T
    88.     P_SW1 = (P_SW1 & ~(3<<2)) | (1<<2);     //IO口切换. 0: P1.2/P5.4 P1.3 P1.4 P1.5, 1: P2.2 P2.3 P2.4 P2.5, 2: P5.4 P4.0 P4.1 P4.3, 3: P3.5 P3.4 P3.3 P3.2
    89.        
    90.     SPI_CLK = 0;    // set clock to low initial state
    91.     SPI_SI = 1;
    92.     SPSTAT = SPIF + WCOL;   //清0 SPIF和WCOL标志
    93. }
    94. void main() {       
    95.         // 初始化SPI
    96.         SPI_init();
    97. //        FlashCheckID();
    98. //        FlashCheckID();
    99.     should_copy_app_to_eeprom = 1;  // 判断是否需要将应用程序拷贝到EEPROM中
    100.     if (should_copy_app_to_eeprom) {
    101.         copy_app_to_eeprom();
    102.     }
    103.        
    104.     // 跳转到应用程序的地址
    105.         EA = 0;
    106.         entry_app();
    107. }
    复制代码
    回复 支持 反对 送花

    使用道具 举报

    该用户从未签到

    6

    主题

    16

    回帖

    148

    积分

    注册会员

    积分
    148
     楼主| 发表于 2023-7-2 22:30:18 | 显示全部楼层
    zhp 发表于 2023-7-1 19:21
    将你的示例代码发出来看一下

    大概是这样,麻烦帮看一下

    点评

    zhp
    主要是要看你放到外部Flash中的代码、项目设置以及 你将外置代码写入到外部Flash中的一些步骤  详情 回复 发表于 2023-7-3 08:56
    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    开心
    5 天前
  • 签到天数: 16 天

    [LV.4]偶尔看看III

    16

    主题

    722

    回帖

    2572

    积分

    超级版主

    积分
    2572
    发表于 2023-7-3 08:56:07 | 显示全部楼层
    chenyl 发表于 2023-7-2 22:30
    大概是这样,麻烦帮看一下

    主要是要看你放到外部Flash中的代码、项目设置以及
    你将外置代码写入到外部Flash中的一些步骤
    回复 支持 反对 送花

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

    GMT+8, 2024-5-16 22:56 , Processed in 0.072754 second(s), 68 queries .

    Powered by Discuz! X3.5

    © 2001-2024 Discuz! Team.

    快速回复 返回顶部 返回列表