矿石收音机论坛

 找回密码
 加入会员

QQ登录

只需一步,快速开始

搜索
查看: 4635|回复: 6

JLINK OB 的bootloader

[复制链接]
     
发表于 2017-11-20 02:49:24 | 显示全部楼层 |阅读模式
差不多10年前,minux 写了这个东西让人们用上了便宜的JLINK。


他写的程序:

  1. /* filename: stm32boot.c, bootloader for JLink ARM-OB STM32 */
  2. /* To Test: burn ob-stm32-after-update.bin to 0x08000000,
  3. * and then burn stm32boot.bin to 0x08000000.
  4. * Power up, LED0 and LED1 should light up and then off,
  5. * and LED0 on for a moment(during copy_firmware()), and LED0 off, LED1 on to
  6. * indicate finished. LED0 on PE6, LED1 on PE1. */
  7. //#define DEBUG
  8. const char *pId = "$Id: stm32boot.c 21 2009-10-14 12:38:12Z minux $";
  9. typedef volatile unsigned int vu32;
  10. typedef unsigned int uint32_t;
  11. typedef unsigned short uint16_t;
  12. #define GPIOE_CRL    (*((vu32*)(0x40011800)))
  13. #define GPIOE_ODR    (*((vu32*)(0x4001180C)))
  14. #define GPIOE_BSRR   (*((vu32*)(0x40011810)))
  15. #define GPIOE_BRR    (*((vu32*)(0x40011814)))
  16. #define RCC_APB2ENR  (*((vu32*)(0x40021018)))

  17. #define FLASH_KEY1 0x45670123
  18. #define FLASH_KEY2 0xcdef89ab

  19. #define FLASH_ACR     (*((vu32*)(0x40022000)))
  20. #define FLASH_KEYR    (*((vu32*)(0x40022004)))
  21. #define FLASH_OPTKEYR (*((vu32*)(0x40022008)))  /* patch this to FLASH_KEYR */
  22. #define FLASH_SR      (*((vu32*)(0x4002200c)))
  23. #define FLASH_CR      (*((vu32*)(0x40022010)))
  24. #define FLASH_AR      (*((vu32*)(0x40022014)))

  25. #define SCB_BASE (0xe000ed00)
  26. #define SCB_VTOR (*((vu32*)(SCB_BASE + 0x08)))

  27. #define LED0 (1 << 6)
  28. #define LED1 (1 << 1)
  29. #ifdef DEBUG
  30. # define LED_ON(led) (GPIOE_BRR = led)
  31. # define LED_OFF(led) (GPIOE_BSRR = led)
  32. # define LED_TOGGLE(led) (GPIOE_ODR ^= led)
  33. #else
  34. # define LED_ON(led)
  35. # define LED_OFF(led)
  36. # define LED_TOGGLE(led)
  37. #endif

  38. #ifndef STACK_SIZE
  39. #define STACK_SIZE                   1024
  40. #endif

  41. void ResetISR(void);
  42. void NMIException(void);
  43. void HardFaultException(void);
  44. void delay(void);
  45. typedef void (* pfnISR)(void); // Pointer to exception handle function
  46. // mthomas: added section -> alignment thru linker-script
  47. __attribute__ ((section(".stackarea")))
  48. static unsigned long pulStack[STACK_SIZE];


  49. __attribute__ ((section(".isr_vector")))
  50. pfnISR VectorTable[] =
  51. {
  52.         (pfnISR)((unsigned long)pulStack + sizeof(pulStack)), // The initial stack pointer
  53.         ResetISR,                                // The reset handler
  54.         NMIException,
  55.         HardFaultException
  56. };

  57. void delay(void)
  58. {
  59.         unsigned int i;
  60.         for( i = 0; i < 0x3ffff; ++i)
  61.                 asm("nop");
  62. }


  63. // The following are constructs created by the linker, indicating where the
  64. // the "data" and "bss" segments reside in memory.  The initializers for the
  65. // for the "data" segment resides immediately following the "text" segment.
  66. extern unsigned long _etext;
  67. extern unsigned long _data;
  68. extern unsigned long _edata;
  69. extern unsigned long _bss;
  70. extern unsigned long _ebss;
  71. int main(void);
  72. void ResetISR(void) {
  73.         unsigned long *pulSrc, *pulDest;
  74.         // Copy the data segment initializers from flash to SRAM.
  75.         pulSrc = &_etext;
  76.         for(pulDest = &_data; pulDest < &_edata; ) *pulDest++ = *pulSrc++;
  77.         // Zero fill the bss segment.
  78.         for(pulDest = &_bss; pulDest < &_ebss; ) *pulDest++ = 0;
  79.         main();
  80. }
  81. void NMIException(void) { return; }
  82. void HardFaultException(void) { return; }
  83. void init(void)
  84. {
  85. #ifndef DEBUG
  86.         return;
  87. #endif
  88.         RCC_APB2ENR |= (1<<6); // enable GPIOE
  89.         GPIOE_CRL = 0x03000030; // PE6, PE1 output push-pull
  90.         //GPIOE_CRL |= 0x33330000;

  91.         LED_ON(LED0);
  92.         LED_ON(LED1);
  93.         delay();
  94.         LED_OFF(LED0);
  95.         LED_OFF(LED1);
  96. /*        int i;
  97.         for (i = 0; i < 1; i++) {
  98.                 LED_TOGGLE(LED0);
  99.                 delay();
  100.         }
  101.         LED_OFF(LED0);
  102. */
  103. }

  104. // stm32 bootloader for ob-stm32
  105. #define FIRMWARE_SIZE 0x5C00
  106. #define FIRMWARE_BASE 0x4000
  107. #define FROM (0x08000000+FIRMWARE_BASE+FIRMWARE_SIZE)
  108. #define TO   (0x08000000+FIRMWARE_BASE)
  109. #define PAGE_SIZE 1024

  110. unsigned short CalcCrc(unsigned char *R4, int count) // huge thanks to DASM!
  111. {
  112.         unsigned R0 = 0, R3, R5, i;
  113.         R3 = 0x8408;
  114.         for (;count != 0; count--)
  115.         {
  116.                 R5 = R0;
  117.                 R0 = *R4;
  118.                 R4++;
  119.                 R0 ^= R5;
  120.                 for (i = 8; i !=0; i--)
  121.                 {
  122.                         int last = R0;
  123.                         R0 >>= 1;
  124.                         if (last & 1)
  125.                                 R0 ^= R3;

  126.                 }
  127.         }
  128.         return R0;
  129. }

  130. void flash_unlock(void) { // unlock the flash program erase controller
  131.         FLASH_KEYR = FLASH_KEY1;
  132.         FLASH_KEYR = FLASH_KEY2;
  133. }

  134. void flash_wait(void) {
  135.         while (FLASH_SR & 0x1/*FLASH_FLAG_BSY*/)
  136.                 ;
  137.         FLASH_SR = 0x35;
  138. }

  139. void flash_erase_page(uint32_t addr) {
  140.         //LED_TOGGLE(LED1);
  141.         FLASH_CR |= 0x02;
  142.         FLASH_AR = addr;
  143.         FLASH_CR |= 0x40;
  144.         flash_wait();
  145.         FLASH_CR &= ~0x02;
  146. }

  147. static inline int flash_write_halfword(uint32_t addr, uint16_t word) {
  148.         flash_wait();
  149.         FLASH_CR |= 0x01;
  150.         *((volatile uint16_t *)addr) = word;
  151.         flash_wait();
  152.         FLASH_CR &= ~0x01;
  153.         return *((volatile uint16_t *)addr) == word;
  154. }

  155. static inline int flash_write_word(uint32_t addr, uint32_t word) {
  156.         flash_wait();
  157.         FLASH_CR |= 0x01;
  158.         asm volatile ("nop");
  159.         *((volatile uint16_t *)addr) = word & 0xffff;
  160.         flash_wait();
  161.         *((volatile uint16_t *) (addr + 2)) = word >> 16;
  162.         flash_wait();
  163.         FLASH_CR &= ~0x01;
  164.         return *((volatile uint32_t *)addr) == word;
  165. }

  166. void copy_firmware(void) {
  167.         uint32_t addr, waddr, data;

  168.         for (addr = TO; addr < TO + FIRMWARE_SIZE; addr += PAGE_SIZE) {
  169.                 int i;
  170.                 data = ~0;
  171.                 for (i = 0; i < PAGE_SIZE; i += 4) {
  172.                         data &= *((uint32_t *)(addr + i));
  173.                         if (data != (uint32_t)~0) { // need erase
  174.                                 //LED_ON(LED1); delay();
  175.                                 flash_erase_page(addr);
  176.                                 break;
  177.                         }
  178.                 }
  179.         }
  180.         for (addr = FROM, waddr = TO; addr < FROM + FIRMWARE_SIZE; ) {
  181.                 //if (addr & 0x1FF == 0x100) LED_TOGGLE(LED1);
  182.                 data = *((uint32_t *)addr);
  183.                 if (data == (uint32_t)&FLASH_OPTKEYR)
  184.                         data = (uint32_t)&FLASH_KEYR; // patch firmware
  185.                 flash_write_word(waddr, data);
  186.                 addr += 4;
  187.                 waddr += 4;
  188.         }
  189. }

  190. void mark_firmware_invalid(void) {
  191.         flash_erase_page(FROM);
  192. }

  193. unsigned char IsValideFirmware(void) {
  194.         unsigned int *i = (unsigned int *)FROM;
  195.         int cnt = 0;
  196.         unsigned int result = 0xFFFFFFFF;
  197.         for (cnt = 0; cnt < 32; cnt++)
  198.                 result &= (*i++);
  199.         if (result == 0xFFFFFFFF)
  200.                 return 0;
  201.         unsigned short crc = CalcCrc((unsigned char *) FROM, FIRMWARE_SIZE - 2);
  202.         if (*(unsigned short*)(FROM + FIRMWARE_SIZE- 2) != crc)
  203.                 return 0;
  204.         return 1;
  205. }

  206. int main() {
  207.         init(); // flash LED to indicate we started!

  208.         if (IsValideFirmware())
  209.         {
  210.                 flash_unlock();
  211.                 LED_ON(LED0);
  212.                 copy_firmware();
  213.                 LED_OFF(LED0);
  214.                 mark_firmware_invalid();
  215.                 LED_ON(LED1);
  216.         }
  217.         FLASH_CR |= (1 << 7); // lock the FPEC

  218.         // relocate vector table
  219.         SCB_VTOR = TO;
  220.         asm volatile ("ISB");
  221.         asm volatile ("movw r3, #:lower16:134234112"); // FROM == 134234112
  222.         asm volatile ("movt r3, #:upper16:134234112");
  223.         asm volatile ("ldr r6, [r3, #0]");
  224.         asm volatile ("msr msp, r6"); // load new stack pointer
  225.         asm volatile ("ldr r6, [r3, #4]");
  226.         asm volatile ("bx r6"); // direct branch to new reset routine
  227.         return 0;
  228. }

复制代码






OB不会更新了,这个也没用了。

自己也写个玩玩,参考他的自己写了个,他这个792字节,我这个348字节。

也能从JLINK驱动更新

截图_2017-11-20_01-43-09.png

  1.          .thumb                 
  2.          .syntax unified
  3. .section .data
  4.         .equ STACKINIT,         0x20005000
  5. yjmwxwx: .ascii "jlink ob boot 2017-11-19 yjmwxwx"
  6. .section .text
  7. _xiangliangbiao:
  8.         .word STACKINIT
  9.         .word _start + 1
  10.         .word _nmi_handler + 1
  11.         .word _hard_fault  + 1
  12.         .word _memory_fault + 1
  13.         .word _bus_fault + 1
  14.         .word _usage_fault + 1

  15. _start:
  16.         cpsid i
  17.         sub sp, sp, # 0x5000
  18.         ldr r0, = yjmwxwx
  19.         str r0, [sp]
  20.         add sp, sp, # 0x5000
  21.        
  22.         ldr r0, = 0xffffffff
  23.         ldr r1, = 0x8009c00
  24.         ldr r1, [r1]
  25.         cmp r1, r0
  26.         bne _crcjisuan
  27. _daogujian:       
  28.         ldr r0, = 0xe000ed08
  29.         ldr r1, = 0x8004000
  30.         str r1, [r0]
  31.         add r1, r1, # 4
  32.         ldr r1, [r1]
  33.         cpsie i
  34.         bx r1
  35. _crcjisuan:
  36.         ldr r0, = 0x8009c00
  37.         ldr r1, = 0x5bfe
  38.         mov r6, # 0
  39.         movw r4, # 0x8408
  40.        
  41. _crcxunhuan:
  42.         ldrb r5, [r0], # 1
  43.         eor r6, r6, r5
  44.         mov r2, # 8
  45. _crcxunhuan1:
  46.         mov r5, r6
  47.         lsrs r6, r6, # 1
  48.         tst r5, # 1
  49.         it ne
  50.         eorne r6, r6, r4
  51.        
  52.         subs r2, r2, # 1
  53.         bne _crcxunhuan1
  54.        
  55.         subs r1, r1, # 1
  56.         bne _crcxunhuan
  57.         ldr r0, = 0x800f7fe
  58.         ldr r1, [r0]
  59.         cmp r6, r1
  60.         bne _daogujian
  61.                                         @ flsh解锁
  62.         ldr r0, = 0x40022000
  63.         ldr r1, = 0x45670123
  64.         str r1, [r0, # 0x04]
  65.         ldr r1, = 0xcdef89ab
  66.         str r1, [r0, # 0x04]
  67.                                         @擦除23页
  68.         mov r5, # 23
  69.         ldr r4, = 0x8004000
  70.         movw r8, # 0x400
  71. _flashmang:
  72.         ldr r2, [r0, # 0x0c]
  73.         lsls r2, r2, # 31
  74.         bmi _flashmang
  75.         mov r1, # 2
  76.         str r1, [r0, # 0x10]
  77.         str r4, [r0, # 0x14]
  78.         mov r1, # 0x42
  79.         str r1, [r0, # 0x10]
  80.         add r4, r4, r8
  81.         subs r5, # 1
  82.         bne _flashmang
  83.                                                 @写FLASH
  84.         ldr r8, = 0x8004000
  85.         ldr r4, = 0x8009c00
  86.         mov r5, # 0
  87.         movw r6, # 0x1700
  88. _flashmang1:
  89.         ldr r2, [r0, # 0x0c]
  90.         lsls r2, r2, # 31
  91.         bmi _flashmang1
  92.         mov r1, # 1
  93.         str r1, [r0, # 0x10]
  94.         ldrh r3, [r4, r5]
  95.         strh r3, [r8, r5]
  96.         add r5, r5, # 2
  97. _flashmang2:
  98.         ldr r2, [r0, # 0x0c]
  99.         lsls r2, r2, # 31
  100.         bmi _flashmang2
  101.         ldrh r3, [r4, r5]
  102.         strh r3, [r8, r5]
  103.         add r5, r5, # 2
  104.         subs r6, r6, # 1
  105.         bne _flashmang1
  106. _flashmang3:
  107.         ldr r2, [r0, # 0x0c]
  108.         lsls r2, r2, # 31
  109.         bmi _flashmang3
  110.         mov r1, # 2
  111.         str r1, [r0, # 0x10]
  112.         ldr r3, = 0x8009c00           @ 擦去更新的一页
  113.         str r3, [r0, # 0x14]
  114.         mov r1, # 0x42
  115.         str r1, [r0, # 0x10]
  116. _flashmang4:
  117.         ldr r2, [r0, # 0x0c]
  118.         lsls r2, r2, # 31
  119.         bmi _flashmang4
  120.         mov r1, # 0x80
  121.         str r1, [r0]                          @flsh上锁
  122.         ldr r0, = 0xe000ed0c
  123.         ldr r1, = 0x05fa0004
  124.         str r1, [r0]                          @复位
  125.        
  126. _nmi_handler:
  127.         bx lr
  128. _hard_fault:
  129.         bx lr
  130. _memory_fault:
  131.         bx lr
  132. _bus_fault:
  133.         bx lr
  134. _usage_fault:
  135.         bx lr
复制代码


jlink ob.zip (92.42 KB, 下载次数: 260)
     
发表于 2017-11-20 09:35:32 | 显示全部楼层
20多年前学过操作系统,现在完全看不懂了
回复 支持 反对

使用道具 举报

     
发表于 2017-11-20 12:49:25 | 显示全部楼层
你的是汇编啊,肯定小
回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2017-11-20 19:05:48 | 显示全部楼层
la45088d1 发表于 2017-11-20 18:48
不止这么一点代码吧?J-link要与PC通信,需要USB从机协议,与其它的ARM控制器通信需要JTAG协议。你这点代码 ...

那些东西在官方固件里,这个代码也就是计算CRC和烧写FLASH,没别的功能,就是跳转到官方固件的一个跳板,有更新的时候就把更新的烧写到FLASH。
回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2017-11-20 19:15:08 | 显示全部楼层
la45088d1 发表于 2017-11-20 19:09
LZ下次长点记性,不要再写这样的指令了:
改成这样:
CPSID I

有什么区别呢?
回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2017-11-20 22:58:22 | 显示全部楼层
la45088d1 发表于 2017-11-20 21:51
请LZ注重细节,LZ的汇编之路开始的比我早吧?写了那么久,不是嘲讽,真的要提高了。不然,被一些人看到,又 ...

谢谢提醒,以前还真不知道这些细节。话说我一开始写汇编到现在也没什么提高,只要从我手里出来的东西都会变的杂乱,细节什么的更是不懂了,以后努力学学吧,不知道能不能学会。 其实我用在汇编的上的时间是非常少的,别看我时间很多,大多数时间都在玩,真正用来自学的时间十分之一也没有。 他们笑话我那是很正常的,人家都是专业培养出来的人才,而我全部都是自学的。比如前几个月想写个傅里叶变换的程序,但是看了几天搞不懂,不知道用小学文化怎么理解这个东西,就算是小学我也是班里倒数前5名那种,笑话我就像官员笑话农民工没钱一样。
回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2017-11-21 00:52:54 | 显示全部楼层
la45088d1 发表于 2017-11-20 21:35
LZ肯定没有好好看我之前发的文章,说实话,这个问题搞不明白,真的没必要再执着于汇编了,连C编译器再 ...

谢谢你提供的资料,长篇大论看不懂,没想到代码位置不同差别这么大, 做了个简单测试,设置SYSTICK定时器重载值0XFFFFFF,中断后跳出这个死循环。 第一个R1结果0XF0F0F ,第二个R1结果0XD7943


d1:
        sub sp, sp, # 0x5000
        ldr r0, = yjmwxwx
        str r0, [sp]
        add sp, sp, # 0x5000
        add r1, r1, # 1
        b d1
1.png



d1:
        ldr r0, = yjmwxwx
        sub sp, sp, # 0x5000
        str r0, [sp]
        add sp, sp, # 0x5000
        add r1, r1, # 1
        b d1

2.png

回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 加入会员

本版积分规则

小黑屋|手机版|矿石收音机 ( 蒙ICP备05000029号-1 )

蒙公网安备 15040402000005号

GMT+8, 2024-4-26 15:24

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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