optiboot_xflash.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. //! @file
  2. // Based on the OptiBoot project
  3. // https://github.com/Optiboot/optiboot
  4. // Licence GLP 2 or later.
  5. #include "Marlin.h"
  6. #include "xflash.h"
  7. #include "stk500.h"
  8. #include "bootapp.h"
  9. #include <avr/wdt.h>
  10. #include "lcd.h"
  11. #define OPTIBOOT_MAJVER 6
  12. #define OPTIBOOT_CUSTOMVER 0
  13. #define OPTIBOOT_MINVER 2
  14. static unsigned const int __attribute__((section(".version")))
  15. optiboot_version = 256*(OPTIBOOT_MAJVER + OPTIBOOT_CUSTOMVER) + OPTIBOOT_MINVER;
  16. #if 0
  17. #define XFLASH_SIGNATURE_0 9
  18. #define XFLASH_SIGNATURE_1 8
  19. #define XFLASH_SIGNATURE_2 7
  20. #else
  21. //FIXME this is a signature of ATmega2560!
  22. #define XFLASH_SIGNATURE_0 0x1E
  23. #define XFLASH_SIGNATURE_1 0x98
  24. #define XFLASH_SIGNATURE_2 0x01
  25. #endif
  26. #define RECV_READY ((UCSR0A & _BV(RXC0)) != 0)
  27. static uint8_t getch(void) {
  28. uint8_t ch;
  29. while(! RECV_READY) ;
  30. if (!(UCSR0A & _BV(FE0))) {
  31. /*
  32. * A Framing Error indicates (probably) that something is talking
  33. * to us at the wrong bit rate. Assume that this is because it
  34. * expects to be talking to the application, and DON'T reset the
  35. * watchdog. This should cause the bootloader to abort and run
  36. * the application "soon", if it keeps happening. (Note that we
  37. * don't care that an invalid char is returned...)
  38. */
  39. wdt_reset();
  40. }
  41. ch = UDR0;
  42. return ch;
  43. }
  44. static void putch(char ch) {
  45. while (!(UCSR0A & _BV(UDRE0)));
  46. UDR0 = ch;
  47. }
  48. static void verifySpace() {
  49. if (getch() != CRC_EOP) {
  50. putch(STK_FAILED);
  51. softReset();
  52. }
  53. putch(STK_INSYNC);
  54. }
  55. static void getNch(uint8_t count) {
  56. do getch(); while (--count);
  57. verifySpace();
  58. }
  59. typedef uint16_t pagelen_t;
  60. //Thou shalt not change these messages, else the avrdude-slicer xflash implementation will no longer work and the language upload will fail.
  61. //Right now we support 2 xflash chips - the original w25x20cl and a new one GD25Q20C
  62. static const char entry_magic_send [] PROGMEM = "start\n";
  63. static const char entry_magic_receive[] PROGMEM = "w25x20cl_enter\n";
  64. static const char entry_magic_cfm [] PROGMEM = "w25x20cl_cfm\n";
  65. struct block_t;
  66. extern struct block_t *block_buffer;
  67. //! @brief Enter an STK500 compatible Optiboot boot loader waiting for flashing the languages to an external flash memory.
  68. //! @return 1 if "start\n" was not sent. Optiboot was skipped
  69. //! @return 0 if "start\n" was sent. Optiboot ran normally. No need to send "start\n" in setup()
  70. uint8_t optiboot_xflash_enter()
  71. {
  72. // Make sure to check boot_app_magic as well. Since these bootapp flags are located right in the middle of the stack,
  73. // they can be unintentionally changed. As a workaround to the language upload problem, do not only check for one bit if it's set,
  74. // but rather test 33 bits for the correct value before exiting optiboot early.
  75. if ((boot_app_magic == BOOT_APP_MAGIC) && (boot_app_flags & BOOT_APP_FLG_USER0)) return 1;
  76. uint8_t ch;
  77. uint8_t rampz = 0;
  78. uint16_t address = 0;
  79. pagelen_t length;
  80. // Use the planner's queue for the receive / transmit buffers.
  81. // uint8_t *buff = (uint8_t*)block_buffer;
  82. uint8_t buff[260];
  83. // bitmap of pages to be written. Bit is set to 1 if the page has already been erased.
  84. uint8_t pages_erased = 0;
  85. // Handshake sequence: Initialize the serial line, flush serial line, send magic, receive magic.
  86. // If the magic is not received on time, or it is not received correctly, continue to the application.
  87. {
  88. wdt_reset();
  89. const char *ptr = entry_magic_send;
  90. const char *end = strlen_P(entry_magic_send) + ptr;
  91. const uint8_t selectedSerialPort_bak = selectedSerialPort;
  92. // Flush the serial line.
  93. while (RECV_READY) {
  94. wdt_reset();
  95. // Dummy register read (discard)
  96. (void)(*(char *)UDR0);
  97. }
  98. selectedSerialPort = 0; //switch to Serial0
  99. MYSERIAL.flush(); //clear RX buffer
  100. int SerialHead = rx_buffer.head;
  101. // Send the initial magic string.
  102. while (ptr != end)
  103. putch(pgm_read_byte(ptr ++));
  104. wdt_reset();
  105. // Wait for two seconds until a magic string (constant entry_magic) is received
  106. // from the serial line.
  107. ptr = entry_magic_receive;
  108. end = strlen_P(entry_magic_receive) + ptr;
  109. while (ptr != end) {
  110. unsigned long boot_timer = 2000000;
  111. // Beware of this volatile pointer - it is important since the while-cycle below
  112. // doesn't contain any obvious references to rx_buffer.head
  113. // thus the compiler is allowed to remove the check from the cycle
  114. // i.e. rx_buffer.head == SerialHead would not be checked at all!
  115. // With the volatile keyword the compiler generates exactly the same code as without it with only one difference:
  116. // the last brne instruction jumps onto the (*rx_head == SerialHead) check and NOT onto the wdr instruction bypassing the check.
  117. volatile int *rx_head = &rx_buffer.head;
  118. while (*rx_head == SerialHead) {
  119. wdt_reset();
  120. if ( --boot_timer == 0) {
  121. // Timeout expired, continue with the application.
  122. selectedSerialPort = selectedSerialPort_bak; //revert Serial setting
  123. return 0;
  124. }
  125. }
  126. ch = rx_buffer.buffer[SerialHead];
  127. SerialHead = (unsigned int)(SerialHead + 1) % RX_BUFFER_SIZE;
  128. if (pgm_read_byte(ptr ++) != ch)
  129. {
  130. // Magic was not received correctly, continue with the application
  131. selectedSerialPort = selectedSerialPort_bak; //revert Serial setting
  132. return 0;
  133. }
  134. wdt_reset();
  135. }
  136. cbi(UCSR0B, RXCIE0); //disable the MarlinSerial0 interrupt
  137. // Send the cfm magic string.
  138. ptr = entry_magic_cfm;
  139. end = strlen_P(entry_magic_cfm) + ptr;
  140. while (ptr != end)
  141. putch(pgm_read_byte(ptr ++));
  142. }
  143. spi_init();
  144. xflash_init();
  145. wdt_disable();
  146. lcd_clear();
  147. lcd_puts_at_P(0, 1, PSTR(" Upgrading xflash\n Do not disconnect!"));
  148. /* Forever loop: exits by causing WDT reset */
  149. for (;;) {
  150. /* get character from UART */
  151. ch = getch();
  152. if(ch == STK_GET_PARAMETER) {
  153. unsigned char which = getch();
  154. verifySpace();
  155. /*
  156. * Send optiboot version as "SW version"
  157. * Note that the references to memory are optimized away.
  158. */
  159. if (which == STK_SW_MINOR) {
  160. putch(optiboot_version & 0xFF);
  161. } else if (which == STK_SW_MAJOR) {
  162. putch(optiboot_version >> 8);
  163. } else {
  164. /*
  165. * GET PARAMETER returns a generic 0x03 reply for
  166. * other parameters - enough to keep Avrdude happy
  167. */
  168. putch(0x03);
  169. }
  170. }
  171. else if(ch == STK_SET_DEVICE) {
  172. // SET DEVICE is ignored
  173. getNch(20);
  174. }
  175. else if(ch == STK_SET_DEVICE_EXT) {
  176. // SET DEVICE EXT is ignored
  177. getNch(5);
  178. }
  179. else if(ch == STK_LOAD_ADDRESS) {
  180. // LOAD ADDRESS
  181. uint16_t newAddress;
  182. // Workaround for the infamous ';' bug in the Prusa3D usb to serial converter.
  183. // Send the binary data by nibbles to avoid transmitting the ';' character.
  184. newAddress = getch();
  185. newAddress |= getch();
  186. newAddress |= (((uint16_t)getch()) << 8);
  187. newAddress |= (((uint16_t)getch()) << 8);
  188. // Transfer top bit to LSB in rampz
  189. if (newAddress & 0x8000)
  190. rampz |= 0x01;
  191. else
  192. rampz &= 0xFE;
  193. newAddress += newAddress; // Convert from word address to byte address
  194. address = newAddress;
  195. verifySpace();
  196. }
  197. else if(ch == STK_UNIVERSAL) {
  198. // LOAD_EXTENDED_ADDRESS is needed in STK_UNIVERSAL for addressing more than 128kB
  199. if ( AVR_OP_LOAD_EXT_ADDR == getch() ) {
  200. // get address
  201. getch(); // get '0'
  202. rampz = (rampz & 0x01) | ((getch() << 1) & 0xff); // get address and put it in rampz
  203. getNch(1); // get last '0'
  204. // response
  205. putch(0x00);
  206. }
  207. else {
  208. // everything else is ignored
  209. getNch(3);
  210. putch(0x00);
  211. }
  212. }
  213. /* Write memory, length is big endian and is in bytes */
  214. else if(ch == STK_PROG_PAGE) {
  215. // PROGRAM PAGE - we support flash programming only, not EEPROM
  216. uint8_t desttype;
  217. uint8_t *bufPtr;
  218. pagelen_t savelength;
  219. // Read the page length, with the length transferred each nibble separately to work around
  220. // the Prusa's USB to serial infamous semicolon issue.
  221. length = ((pagelen_t)getch()) << 8;
  222. length |= ((pagelen_t)getch()) << 8;
  223. length |= getch();
  224. length |= getch();
  225. savelength = length;
  226. // Read the destination type. It should always be 'F' as flash.
  227. desttype = getch();
  228. // read a page worth of contents
  229. bufPtr = buff;
  230. do *bufPtr++ = getch();
  231. while (--length);
  232. // Read command terminator, start reply
  233. verifySpace();
  234. if (desttype == 'E') {
  235. while (1) ; // Error: wait for WDT
  236. } else {
  237. uint32_t addr = (((uint32_t)rampz) << 16) | address;
  238. // During a single bootloader run, only erase a 64kB block once.
  239. // An 8bit bitmask 'pages_erased' covers 512kB of FLASH memory.
  240. if ((address == 0) && (pages_erased & (1 << (addr >> 16))) == 0) {
  241. xflash_wait_busy();
  242. xflash_enable_wr();
  243. xflash_block64_erase(addr);
  244. pages_erased |= (1 << (addr >> 16));
  245. }
  246. xflash_wait_busy();
  247. xflash_enable_wr();
  248. xflash_page_program(addr, buff, savelength);
  249. xflash_wait_busy();
  250. xflash_disable_wr();
  251. }
  252. }
  253. /* Read memory block mode, length is big endian. */
  254. else if(ch == STK_READ_PAGE) {
  255. uint32_t addr = (((uint32_t)rampz) << 16) | address;
  256. pagelen_t i;
  257. // Read the page length, with the length transferred each nibble separately to work around
  258. // the Prusa's USB to serial infamous semicolon issue.
  259. length = ((pagelen_t)getch()) << 8;
  260. length |= ((pagelen_t)getch()) << 8;
  261. length |= getch();
  262. length |= getch();
  263. // Read the destination type. It should always be 'F' as flash. It is not checked.
  264. (void)getch();
  265. verifySpace();
  266. xflash_wait_busy();
  267. xflash_rd_data(addr, buff, length);
  268. for (i = 0; i < length; ++ i)
  269. putch(buff[i]);
  270. }
  271. /* Get device signature bytes */
  272. else if(ch == STK_READ_SIGN) {
  273. // READ SIGN - return what Avrdude wants to hear
  274. verifySpace();
  275. putch(XFLASH_SIGNATURE_0);
  276. putch(XFLASH_SIGNATURE_1);
  277. putch(XFLASH_SIGNATURE_2);
  278. }
  279. else if (ch == STK_LEAVE_PROGMODE) { /* 'Q' */
  280. // Adaboot no-wait mod
  281. wdt_enable(WATCHDOG_SOFT_RESET_VALUE);
  282. verifySpace();
  283. }
  284. else {
  285. // This covers the response to commands like STK_ENTER_PROGMODE
  286. verifySpace();
  287. }
  288. putch(STK_OK);
  289. }
  290. }