program_flash.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. /**
  2. * ZuluSCSI™ - Copyright (c) 2022-2025 Rabbit Hole Computing™
  3. *
  4. * ZuluSCSI™ firmware is licensed under the GPL version 3 or any later version. 
  5. *
  6. * https://www.gnu.org/licenses/gpl-3.0.html
  7. * ----
  8. * This program is free software: you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation, either version 3 of the License, or
  11. * (at your option) any later version. 
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16. * GNU General Public License for more details. 
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  20. **/
  21. /**
  22. * This has been removed from ZuluSCSI_platform.cpp so this code can be
  23. * placed in SRAM while ZuluSCSI_platform.cpp.o can be placed in flash
  24. */
  25. #include "ZuluSCSI_platform.h"
  26. #include "ZuluSCSI_log.h"
  27. #include <hardware/flash.h>
  28. #include <hardware/structs/xip_ctrl.h>
  29. #include <hardware/structs/usb.h>
  30. #include <hardware/structs/nvic.h>
  31. #include <hardware/structs/scb.h>
  32. #include <hardware/sync.h>
  33. #ifndef PIO_FRAMEWORK_ARDUINO_NO_USB
  34. #include <SerialUSB.h>
  35. #include <class/cdc/cdc_device.h>
  36. #endif
  37. /*****************************************/
  38. /* Flash reprogramming from bootloader */
  39. /*****************************************/
  40. #ifdef PLATFORM_BOOTLOADER_SIZE
  41. extern uint32_t __real_vectors_start;
  42. extern uint32_t __StackTop;
  43. static volatile void *g_bootloader_exit_req;
  44. __attribute__((section(".time_critical.platform_rewrite_flash_page")))
  45. bool platform_rewrite_flash_page(uint32_t offset, uint8_t buffer[PLATFORM_FLASH_PAGE_SIZE])
  46. {
  47. if (offset == PLATFORM_BOOTLOADER_SIZE)
  48. {
  49. if (buffer[3] != 0x20 || buffer[7] != 0x10)
  50. {
  51. logmsg("Invalid firmware file, starts with: ", bytearray(buffer, 16));
  52. return false;
  53. }
  54. }
  55. #ifdef ZULUSCSI_MCU_RP23XX
  56. if (nvic_hw->iser[0] & 1 << 14)
  57. {
  58. logmsg("Disabling USB during firmware flashing");
  59. nvic_hw->icer[0] = 1 << 14;
  60. usb_hw->main_ctrl = 0;
  61. }
  62. #else
  63. if (nvic_hw->iser & 1 << 14)
  64. {
  65. logmsg("Disabling USB during firmware flashing");
  66. nvic_hw->icer = 1 << 14;
  67. usb_hw->main_ctrl = 0;
  68. }
  69. #endif
  70. dbgmsg("Writing flash at offset ", offset, " data ", bytearray(buffer, 4));
  71. assert(offset % PLATFORM_FLASH_PAGE_SIZE == 0);
  72. assert(offset >= PLATFORM_BOOTLOADER_SIZE);
  73. // Avoid any mbed timer interrupts triggering during the flashing.
  74. uint32_t saved_irq = save_and_disable_interrupts();
  75. // For some reason any code executed after flashing crashes
  76. // unless we disable the XIP cache.
  77. // Not sure why this happens, as flash_range_program() is flushing
  78. // the cache correctly.
  79. // The cache is now enabled from bootloader start until it starts
  80. // flashing, and again after reset to main firmware.
  81. xip_ctrl_hw->ctrl = 0;
  82. flash_range_erase(offset, PLATFORM_FLASH_PAGE_SIZE);
  83. flash_range_program(offset, buffer, PLATFORM_FLASH_PAGE_SIZE);
  84. uint32_t *buf32 = (uint32_t*)buffer;
  85. uint32_t num_words = PLATFORM_FLASH_PAGE_SIZE / 4;
  86. for (int i = 0; i < num_words; i++)
  87. {
  88. uint32_t expected = buf32[i];
  89. #ifdef ZULUSCSI_MCU_RP23XX
  90. uint32_t actual = *(volatile uint32_t*)(XIP_NOCACHE_NOALLOC_BASE + offset + i * 4);
  91. #else
  92. uint32_t actual = *(volatile uint32_t*)(XIP_NOCACHE_BASE + offset + i * 4);
  93. #endif
  94. if (actual != expected)
  95. {
  96. logmsg("Flash verify failed at offset ", offset + i * 4, " got ", actual, " expected ", expected);
  97. restore_interrupts(saved_irq);
  98. return false;
  99. }
  100. }
  101. restore_interrupts(saved_irq);
  102. return true;
  103. }
  104. void platform_boot_to_main_firmware()
  105. {
  106. // To ensure that the system state is reset properly, we perform
  107. // a SYSRESETREQ and jump straight from the reset vector to main application.
  108. g_bootloader_exit_req = &g_bootloader_exit_req;
  109. scb_hw->aircr = 0x05FA0004;
  110. while(1);
  111. }
  112. void btldr_reset_handler()
  113. {
  114. uint32_t* application_base = &__real_vectors_start;
  115. if (g_bootloader_exit_req == &g_bootloader_exit_req)
  116. {
  117. // Boot to main application
  118. application_base = (uint32_t*)(XIP_BASE + PLATFORM_BOOTLOADER_SIZE);
  119. }
  120. scb_hw->vtor = (uint32_t)application_base;
  121. __asm__(
  122. "msr msp, %0\n\t"
  123. "bx %1" : : "r" (application_base[0]),
  124. "r" (application_base[1]) : "memory");
  125. }
  126. // Replace the reset handler when building the bootloader
  127. // The rp2040_btldr.ld places real vector table at an offset.
  128. __attribute__((section(".btldr_vectors")))
  129. const void * btldr_vectors[2] = {&__StackTop, (void*)&btldr_reset_handler};
  130. #endif // PLATFORM_BOOTLOADER_SIZE