optiboot_x.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780
  1. /**********************************************************/
  2. /* Optiboot bootloader for Mega0, Tiny0, Tiny1 */
  3. /* */
  4. /* https://github.com/optiboot/optiboot */
  5. /* */
  6. /* Heavily optimised bootloader that is fast and small */
  7. /* (512 bytes, 115200bps */
  8. /* */
  9. /* Written almost entirely in C */
  10. /* Customisable timeout with accurate timeconstant */
  11. /* */
  12. /* */
  13. /* Copyright 2013-2021 by Bill Westfield. */
  14. /* Copyright 2010 by Peter Knight. */
  15. /* */
  16. /* This program is free software; you can redistribute it */
  17. /* and/or modify it under the terms of the GNU General */
  18. /* Public License as published by the Free Software */
  19. /* Foundation; either version 2 of the License, or */
  20. /* (at your option) any later version. */
  21. /* */
  22. /* This program is distributed in the hope that it will */
  23. /* be useful, but WITHOUT ANY WARRANTY; without even the */
  24. /* implied warranty of MERCHANTABILITY or FITNESS FOR A */
  25. /* PARTICULAR PURPOSE. See the GNU General Public */
  26. /* License for more details. */
  27. /* */
  28. /* You should have received a copy of the GNU General */
  29. /* Public License along with this program; if not, write */
  30. /* to the Free Software Foundation, Inc., */
  31. /* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
  32. /* */
  33. /* Licence can be viewed at */
  34. /* https://github.com/Optiboot/optiboot/blob/master/LICENSE */
  35. /* */
  36. /**********************************************************/
  37. /**********************************************************/
  38. /* */
  39. /* Optional defines: */
  40. /* */
  41. /**********************************************************/
  42. /* */
  43. /* BIGBOOT: */
  44. /* Build a 1k bootloader, not 512 bytes. This turns on */
  45. /* extra functionality. */
  46. /* */
  47. /* BAUD_RATE: */
  48. /* Set bootloader baud rate. */
  49. /* */
  50. /* LED_START_FLASHES: */
  51. /* Number of LED flashes on bootup. */
  52. /* */
  53. /* LED_DATA_FLASH: */
  54. /* Flash LED when transferring data. For boards without */
  55. /* TX or RX LEDs, or for people who like blinky lights. */
  56. /* */
  57. /* WDTIME: */
  58. /* Bootloader timeout period, in seconds. */
  59. /* 1, 2, 4, 8 supported. */
  60. /* */
  61. /* UARTTX: */
  62. /* UART TX pin (B0, etc) for devices with more than */
  63. /* one hardware uart, or alternative pins */
  64. /* */
  65. /**********************************************************/
  66. /**********************************************************/
  67. /* Version Numbers! */
  68. /* */
  69. /* Optiboot now includes a Version number in the source */
  70. /* and object code, and returns this value via STK500 */
  71. /* */
  72. /* The iniital Mega0/Xtiny support is version 9. */
  73. /* This is very different from normal AVR because of */
  74. /* changed peripherals and unified address space. */
  75. /* */
  76. /* It would be good if versions implemented outside the */
  77. /* official repository used an out-of-seqeunce version */
  78. /* number (like 104.6 if based on based on 4.5) to */
  79. /* prevent collisions. The CUSTOM_VERSION=n option */
  80. /* adds n to the high version to facilitate this. */
  81. /* */
  82. /**********************************************************/
  83. /**********************************************************/
  84. /* Edit History: */
  85. /* */
  86. /* Jun 2021 */
  87. /* 9.2 add rs485 support and SpenceKonde's startup code */
  88. /* Sep 2020 */
  89. /* 9.1 fix do_nvmctrl */
  90. /* Aug 2019 */
  91. /* 9.0 Refactored for Mega0/Xtiny from optiboot.c */
  92. /* : */
  93. /* 4.1 WestfW: put version number in binary. */
  94. /**********************************************************/
  95. #define OPTIBOOT_MAJVER 9
  96. #define OPTIBOOT_MINVER 2
  97. /*
  98. * OPTIBOOT_CUSTOMVER should be defined (by the makefile) for custom edits
  99. * of optiboot. That way you don't wind up with very different code that
  100. * matches the version number of a "released" optiboot.
  101. */
  102. #if !defined(OPTIBOOT_CUSTOMVER)
  103. # define OPTIBOOT_CUSTOMVER 0
  104. #endif
  105. unsigned const int __attribute__((section(".version"))) __attribute__((used))
  106. optiboot_version = 256*(OPTIBOOT_MAJVER + OPTIBOOT_CUSTOMVER) + OPTIBOOT_MINVER;
  107. #include <inttypes.h>
  108. #include <avr/io.h>
  109. #if (!defined(__AVR_XMEGA__)) || (__AVR_ARCH__ != 103)
  110. #error CPU not supported by this version of Optiboot.
  111. #include <unsupported> // include a non-existent file to stop compilation
  112. #endif
  113. /*
  114. * Fuses.
  115. * This is an example of what they'd be like, but some should not
  116. * necessarily be under control of the bootloader. You'll need a
  117. * a programmer that processes the .fuses section to actually get
  118. * these programmed into the chip.
  119. * The fuses actually REQUIRED by Optiboot are:
  120. * BOOTEND=2, SYSCFG0=(CRC off, RSTPIN as appropriate)
  121. * On some chips, the "reset" pin can be either RESET or GPIO.
  122. * Other also have the UPDI option. If RESET is not enabled we won't be
  123. * able to auto-reset. But if the UPDI pin is set to cause RESET, we
  124. * won't be able to reprogram the chip without HV UPDI (which is uncommon.)
  125. * The settings show will set chips (ie m4809) with RESET/GPIO to use RESET,
  126. * and chips with RESET/GPIO/UPDI to leave it in UPDI mode - the bootloader
  127. * can still be started by a power-on RESET.
  128. */
  129. FUSES = {
  130. .WDTCFG = 0, /* Watchdog Configuration */
  131. .BODCFG = FUSE_BODCFG_DEFAULT, /* BOD Configuration */
  132. .OSCCFG = FREQSEL_20MHZ_gc, /* 20MHz */
  133. #ifdef FUSE_TCD0CFG_DEFAULT
  134. .TCD0CFG = FUSE_TCD0CFG_DEFAULT, /* TCD0 Configuration */
  135. #endif
  136. #ifdef RSTPIN
  137. .SYSCFG0 = CRCSRC_NOCRC_gc | RSTPINCFG_RST_gc, /* RESET is enabled */
  138. #else
  139. # ifdef FUSE_RSTPINCFG_gm // group mask will be defined for triple-func pins
  140. .SYSCFG0 = CRCSRC_NOCRC_gc | RSTPINCFG_UPDI_gc, /* RESET is not yet */
  141. # else
  142. .SYSCFG0 = CRCSRC_NOCRC_gc, /* RESET is not yet */
  143. # endif
  144. #endif
  145. .SYSCFG1 = 0x06, /* startup 32ms */
  146. .APPEND = 0, /* Application Code Section End */
  147. .BOOTEND = 2 /* Boot Section End */
  148. };
  149. /*
  150. * optiboot uses several "address" variables that are sometimes byte pointers,
  151. * sometimes word pointers. sometimes 16bit quantities, and sometimes built
  152. * up from 8bit input characters. avr-gcc is not great at optimizing the
  153. * assembly of larger words from bytes, but we can use the usual union to
  154. * do this manually. Expanding it a little, we can also get rid of casts.
  155. */
  156. typedef union {
  157. uint8_t *bptr;
  158. uint16_t *wptr;
  159. uint16_t word;
  160. uint8_t bytes[2];
  161. } addr16_t;
  162. /*
  163. * pin_defs.h
  164. * This contains most of the rather ugly defines that implement our
  165. * ability to use UART=n and LED=D3, and some avr family bit name differences.
  166. */
  167. #include "pin_defs_x.h"
  168. /*
  169. * stk500.h contains the constant definitions for the stk500v1 comm protocol
  170. */
  171. #include "stk500.h"
  172. #ifndef LED_START_FLASHES
  173. # define LED_START_FLASHES 0
  174. #endif
  175. /*
  176. * The mega-0, tiny-0, and tiny-1 chips all reset to running on the
  177. * internal oscillator, with a prescaler of 6. The internal oscillator
  178. * is either 20MHz or 16MHz, depending on a fuse setting - we can read
  179. * the fuse to figure our which.
  180. * The BRG divisor is also fractional, permitting (afaik) any reasonable
  181. * bit rate between about 1000bps and 115200bps. (higher bitrates would
  182. * require changing the default clock.)
  183. * This makes the BRG generation a bit different than for prior processors.
  184. */
  185. /* set the UART baud rate defaults */
  186. #ifndef BAUD_RATE
  187. # define BAUD_RATE 115200L // Highest rate Avrdude win32 will support
  188. #endif
  189. #ifdef F_CPU
  190. # warning F_CPU is ignored for this chip (run from internal osc.)
  191. #endif
  192. #ifdef SINGLESPEED
  193. # warning SINGLESPEED ignored for this chip. (Fractional BRG)
  194. #endif
  195. #ifdef UART
  196. # warning UART is ignored for this chip (use UARTTX=PortPin instead)
  197. #endif
  198. #define BAUD_SETTING_16 (((16000000/6)*64) / (16L*BAUD_RATE))
  199. #define BAUD_ACTUAL_16 ((64L*(16000000/6)) / (16L*BAUD_SETTING))
  200. #define BAUD_SETTING_20 (((20000000/6)*64) / (16L*BAUD_RATE))
  201. #define BAUD_ACTUAL_20 ((64L*(20000000/6)) / (16L*BAUD_SETTING))
  202. #if BAUD_SETTING_16 < 64 // divisor must be > 1. Low bits are fraction.
  203. # error Unachievable baud rate (too fast) BAUD_RATE
  204. #endif
  205. #if BAUD_SETTING > 65635
  206. # error Unachievable baud rate (too slow) BAUD_RATE
  207. #endif // baud rate slow check
  208. /*
  209. * Watchdog timeout translations from human readable to config vals
  210. */
  211. #ifndef WDTTIME
  212. # define WDTPERIOD WDT_PERIOD_1KCLK_gc // 1 second
  213. #elif WDTTIME == 1
  214. # define WDTPERIOD WDT_PERIOD_1KCLK_gc // 1 second
  215. #elif WDTTIME == 2
  216. # define WDTPERIOD WDT_PERIOD_2KCLK_gc // 2 seconds
  217. #elif WDTTIME == 4
  218. # define WDTPERIOD WDT_PERIOD_4KCLK_gc // 4 seconds
  219. #elif WDTTIME == 8
  220. # define WDTPERIOD WDT_PERIOD_8KCLK_gc // 8 seconds
  221. #else
  222. #endif
  223. /*
  224. * We can never load flash with more than 1 page at a time, so we can save
  225. * some code space on parts with smaller pagesize by using a smaller int.
  226. */
  227. #if MAPPED_PROGMEM_PAGE_SIZE > 255
  228. typedef uint16_t pagelen_t;
  229. # define GETLENGTH(len) len = getch()<<8; len |= getch()
  230. #else
  231. typedef uint8_t pagelen_t;
  232. # define GETLENGTH(len) (void) getch() /* skip high byte */; len = getch()
  233. #endif
  234. /* Function Prototypes
  235. * The main() function is in init9, which removes the interrupt vector table
  236. * we don't need. It is also 'OS_main', which means the compiler does not
  237. * generate any entry or exit code itself (but unlike 'naked', it doesn't
  238. * suppress some compile-time options we want.)
  239. */
  240. void pre_main(void) __attribute__ ((naked)) __attribute__ ((section (".init8")));
  241. int main(void) __attribute__ ((OS_main)) __attribute__ ((section (".init9"))) __attribute__((used));
  242. void __attribute__((noinline)) __attribute__((leaf)) putch(char);
  243. uint8_t __attribute__((noinline)) __attribute__((leaf)) getch(void) ;
  244. void __attribute__((noinline)) verifySpace();
  245. void __attribute__((noinline)) watchdogConfig(uint8_t x);
  246. static void getNch(uint8_t);
  247. #if LED_START_FLASHES > 0
  248. static inline void flash_led(uint8_t);
  249. #endif
  250. #define watchdogReset() __asm__ __volatile__ (" wdr\n")
  251. /*
  252. * RAMSTART should be self-explanatory. It's bigger on parts with a
  253. * lot of peripheral registers.
  254. * Note that RAMSTART (for optiboot) need not be exactly at the start of RAM.
  255. */
  256. #if !defined(RAMSTART) // newer versions of gcc avr-libc define RAMSTART
  257. #error RAMSTART not defined.
  258. #endif
  259. /* everything that needs to run VERY early */
  260. void pre_main (void) {
  261. // Allow convenient way of calling do_spm function - jump table,
  262. // so entry to this function will always be here, independent
  263. // of compilation, features, etc
  264. __asm__ __volatile__ (
  265. " rjmp 1f\n"
  266. #ifndef APP_NOSPM
  267. " rjmp do_nvmctrl\n"
  268. #else
  269. " ret\n" // if do_spm isn't include, return without doing anything
  270. #endif
  271. "1:\n"
  272. );
  273. }
  274. /* main program starts here */
  275. int main (void) {
  276. uint8_t ch;
  277. /*
  278. * Making these local and in registers prevents the need for initializing
  279. * them, and also saves space because code no longer stores to memory.
  280. * (initializing address keeps the compiler happy, but isn't really
  281. * necessary, and uses 4 bytes of flash.)
  282. */
  283. register addr16_t address;
  284. register pagelen_t length;
  285. // This is the first code to run.
  286. //
  287. // Optiboot C code makes the following assumptions:
  288. // No interrupts will execute
  289. // SP points to RAMEND
  290. __asm__ __volatile__ (" clr __zero_reg__\n"); // known-zero required by avr-libc
  291. #define RESET_EXTERNAL (RSTCTRL_EXTRF_bm|RSTCTRL_UPDIRF_bm|RSTCTRL_SWRF_bm)
  292. #ifndef FANCY_RESET_LOGIC
  293. ch = RSTCTRL.RSTFR; // get reset cause
  294. #ifdef START_APP_ON_POR
  295. /*
  296. * If WDRF is set OR nothing except BORF and PORF are set, that's
  297. * not bootloader entry condition so jump to app - this is for when
  298. * UPDI pin is used as reset, so we go straight to app on start.
  299. * 11/14: NASTY bug - we also need to check for no reset flags being
  300. * set (ie, direct entry) and run bootloader in that case, otherwise
  301. * bootloader won't run, among other things, after fresh bootloading!
  302. */
  303. if (ch && (ch & RSTCTRL_WDRF_bm ||
  304. (!(ch & (~(RSTCTRL_BORF_bm | RSTCTRL_PORF_bm)))))) {
  305. # ifdef KeepBracesMatched
  306. }
  307. # endif
  308. #else
  309. /*
  310. * If WDRF is set OR nothing except BORF is set, that's not
  311. * bootloader entry condition so jump to app - let's see if this
  312. * works okay or not...
  313. */
  314. if (ch && (ch & RSTCTRL_WDRF_bm || (!(ch & (~RSTCTRL_BORF_bm))))) {
  315. #endif
  316. /* Start the app.
  317. * Dont bother trying to stuff it in r2, which requires heroic
  318. * effort to fish out we'll put it in GPIOR0 where it won't get
  319. * stomped on.
  320. */
  321. // __asm__ __volatile__ (" mov r2, %0\n" :: "r" (ch));
  322. RSTCTRL.RSTFR = ch; //clear the reset causes before jumping to app...
  323. GPIOR0 = ch; // but, stash the reset cause in GPIOR0 for use by app...
  324. watchdogConfig(WDT_PERIOD_OFF_gc);
  325. __asm__ __volatile__(
  326. " jmp app\n"
  327. );
  328. }
  329. #else
  330. /*
  331. * Protect as much Reset Cause as possible for application
  332. * and still skip bootloader if not necessary
  333. */
  334. ch = RSTCTRL.RSTFR;
  335. if (ch != 0) {
  336. /*
  337. * We want to run the bootloader when an external reset has occurred.
  338. * On these mega0/XTiny chips, there are three types of ext reset:
  339. * reset pin (may not exist), UPDI reset, and SW-request reset.
  340. * One of these reset causes, together with watchdog reset, should
  341. * mean that Optiboot timed out, and it's time to run the app.
  342. * Other reset causes (notably poweron) should run the app directly.
  343. * If a user app wants to utilize and detect watchdog resets, it
  344. * must make sure that the other reset causes are cleared.
  345. */
  346. if (ch & RSTCTRL_WDRF_bm) {
  347. if (ch & RESET_EXTERNAL) {
  348. /*
  349. * Clear WDRF because it was most probably set by wdr in
  350. * bootloader. It's also needed to avoid loop by broken
  351. * application which could prevent entering bootloader.
  352. */
  353. RSTCTRL.RSTFR = RSTCTRL_WDRF_bm;
  354. }
  355. }
  356. if (!(ch & RESET_EXTERNAL)) {
  357. /*
  358. * save the reset flags in the designated register.
  359. * This can be saved in a main program by putting code in
  360. * .init0 (which executes before normal c init code) to save R2
  361. * to a global variable.
  362. */
  363. __asm__ __volatile__(" mov r2, %0\n" :: "r"(ch));
  364. // switch off watchdog
  365. watchdogConfig(WDT_PERIOD_OFF_gc);
  366. __asm__ __volatile__(
  367. " jmp app\n"
  368. );
  369. }
  370. }
  371. #endif // Fancy reset cause stuff
  372. watchdogReset();
  373. // _PROTECTED_WRITE(CLKCTRL.MCLKCTRLB, 0); // full speed clock
  374. MYUART_TXPORT.DIR |= MYUART_TXPIN; // set TX pin to output
  375. MYUART_TXPORT.OUT |= MYUART_TXPIN; // and "1" as per datasheet
  376. #if defined (MYUART_PMUX_VAL)
  377. MYPMUX_REG = MYUART_PMUX_VAL; // alternate pinout to use
  378. #endif
  379. if ((FUSE_OSCCFG & FUSE_FREQSEL_gm) == FREQSEL_16MHZ_gc) {
  380. MYUART.BAUD = BAUD_SETTING_16;
  381. } else {
  382. MYUART.BAUD = BAUD_SETTING_20;
  383. }
  384. MYUART.DBGCTRL = 1; // run during debug
  385. MYUART.CTRLC = (USART_CHSIZE_gm & USART_CHSIZE_8BIT_gc); // Async, Parity Disabled, 1 StopBit
  386. MYUART.CTRLA = 0; // Interrupts: all off
  387. MYUART.CTRLB = USART_RXEN_bm | USART_TXEN_bm;
  388. #ifdef RS485
  389. RS485_PORT.DIR |= _BV(RS485_BIT);
  390. #endif
  391. // Set up watchdog to trigger after a bit
  392. // (nominally:, 1s for autoreset, longer for manual)
  393. watchdogConfig(WDTPERIOD);
  394. #if (LED_START_FLASHES > 0) || defined(LED_DATA_FLASH) || defined(LED_START_ON)
  395. /* Set LED pin as output */
  396. LED_PORT.DIR |= LED;
  397. #endif
  398. #if LED_START_FLASHES > 0
  399. /* Flash onboard LED to signal entering of bootloader */
  400. # ifdef LED_INVERT
  401. flash_led(LED_START_FLASHES * 2+1);
  402. # else
  403. flash_led(LED_START_FLASHES * 2);
  404. # endif
  405. #else
  406. #if defined(LED_START_ON)
  407. # ifndef LED_INVERT
  408. /* Turn on LED to indicate starting bootloader (less code!) */
  409. LED_PORT.OUT |= LED;
  410. # endif
  411. #endif
  412. #endif
  413. /* Forever loop: exits by causing WDT reset */
  414. for (;;) {
  415. /* get character from UART */
  416. ch = getch();
  417. if(ch == STK_GET_PARAMETER) {
  418. unsigned char which = getch();
  419. verifySpace();
  420. /*
  421. * Send optiboot version as "SW version"
  422. * Note that the references to memory are optimized away.
  423. */
  424. if (which == STK_SW_MINOR) {
  425. putch(optiboot_version & 0xFF);
  426. } else if (which == STK_SW_MAJOR) {
  427. putch(optiboot_version >> 8);
  428. } else {
  429. /*
  430. * GET PARAMETER returns a generic 0x03 reply for
  431. * other parameters - enough to keep Avrdude happy
  432. */
  433. putch(0x03);
  434. }
  435. }
  436. else if(ch == STK_SET_DEVICE) {
  437. // SET DEVICE is ignored
  438. getNch(20);
  439. }
  440. else if(ch == STK_SET_DEVICE_EXT) {
  441. // SET DEVICE EXT is ignored
  442. getNch(5);
  443. }
  444. else if(ch == STK_LOAD_ADDRESS) {
  445. // LOAD ADDRESS
  446. address.bytes[0] = getch();
  447. address.bytes[1] = getch();
  448. // ToDo: will there be mega-0 chips with >128k of RAM?
  449. /* UPDI chips apparently have byte-addressable FLASH ?
  450. address.word *= 2; // Convert from word address to byte address
  451. */
  452. verifySpace();
  453. }
  454. else if(ch == STK_UNIVERSAL) {
  455. #ifndef RAMPZ
  456. // UNIVERSAL command is ignored
  457. getNch(4);
  458. putch(0x00);
  459. #endif
  460. }
  461. /* Write memory, length is big endian and is in bytes */
  462. else if(ch == STK_PROG_PAGE) {
  463. // PROGRAM PAGE - any kind of page!
  464. uint8_t desttype;
  465. GETLENGTH(length);
  466. desttype = getch();
  467. if (desttype == 'F') {
  468. address.word += MAPPED_PROGMEM_START;
  469. } else {
  470. address.word += MAPPED_EEPROM_START;
  471. }
  472. // TODO: user row?
  473. do {
  474. *(address.bptr++) = getch();
  475. } while (--length);
  476. // Read command terminator, start reply
  477. verifySpace();
  478. /*
  479. * Actually Write the buffer to flash (and wait for it to finish.)
  480. */
  481. _PROTECTED_WRITE_SPM(NVMCTRL.CTRLA, NVMCTRL_CMD_PAGEERASEWRITE_gc);
  482. while (NVMCTRL.STATUS & (NVMCTRL_FBUSY_bm|NVMCTRL_EEBUSY_bm))
  483. ; // wait for flash and EEPROM not busy, just in case.
  484. }
  485. /* Read memory block mode, length is big endian. */
  486. else if(ch == STK_READ_PAGE) {
  487. uint8_t desttype;
  488. GETLENGTH(length);
  489. desttype = getch();
  490. verifySpace();
  491. if (desttype == 'F') {
  492. address.word += MAPPED_PROGMEM_START;
  493. } else {
  494. address.word += MAPPED_EEPROM_START;
  495. }
  496. // TODO: user row?
  497. do {
  498. putch(*(address.bptr++));
  499. } while (--length);
  500. }
  501. /* Get device signature bytes */
  502. else if(ch == STK_READ_SIGN) {
  503. // READ SIGN - return actual device signature from SIGROW
  504. // this enables the same binary to be ued on multiple chips.
  505. verifySpace();
  506. putch(SIGROW_DEVICEID0);
  507. putch(SIGROW_DEVICEID1);
  508. putch(SIGROW_DEVICEID2);
  509. }
  510. else if (ch == STK_LEAVE_PROGMODE) { /* 'Q' */
  511. // Adaboot no-wait mod
  512. watchdogConfig(WDT_PERIOD_8CLK_gc);
  513. verifySpace();
  514. }
  515. else {
  516. // This covers the response to commands like STK_ENTER_PROGMODE
  517. verifySpace();
  518. }
  519. putch(STK_OK);
  520. }
  521. }
  522. #if RS485
  523. inline void rs485_txon() {
  524. # ifdef RS485_INVERT
  525. RS485_PORT.OUT &= ~_BV(RS485_BIT);
  526. # else
  527. RS485_PORT.OUT |= _BV(RS485_BIT);
  528. # endif
  529. }
  530. inline void rs485_txoff() {
  531. // First, wait for any pending transmits to finish.
  532. MYUART.STATUS = USART_TXCIF_bm; // This clears the TX complete flag
  533. while ((MYUART.STATUS & USART_TXCIF_bm) == 0)
  534. ; // spin loop waiting for TX Complete (could be immediately)
  535. # ifdef RS485_INVERT
  536. RS485_PORT.OUT |= _BV(RS485_BIT);
  537. # else
  538. RS485_PORT.OUT &= ~_BV(RS485_BIT);
  539. # endif
  540. }
  541. #else // provide null functions to be optimized away.
  542. inline void rs485_txon() {}
  543. inline void rs485_txoff() {}
  544. #endif
  545. void putch (char ch) {
  546. rs485_txon(); // turn on and leave on till we're done xmitting.
  547. while (0 == (MYUART.STATUS & USART_DREIF_bm))
  548. ;
  549. MYUART.TXDATAL = ch;
  550. rs485_txoff(); // To receive, turn off transmitter
  551. }
  552. uint8_t getch (void) {
  553. uint8_t ch, flags;
  554. while (!(MYUART.STATUS & USART_RXCIF_bm))
  555. ;
  556. flags = MYUART.RXDATAH;
  557. ch = MYUART.RXDATAL;
  558. if ((flags & USART_FERR_bm) == 0)
  559. watchdogReset();
  560. #ifdef LED_DATA_FLASH
  561. LED_PORT.IN |= LED;
  562. #endif
  563. return ch;
  564. }
  565. void getNch (uint8_t count) {
  566. do getch(); while (--count);
  567. verifySpace();
  568. }
  569. void verifySpace () {
  570. if (getch() != CRC_EOP) {
  571. watchdogConfig(WDT_PERIOD_8CLK_gc); // shorten WD timeout
  572. while (1) // and busy-loop so that WD causes
  573. ; // a reset and app start.
  574. }
  575. putch(STK_INSYNC);
  576. }
  577. #if LED_START_FLASHES > 0
  578. void flash_led (uint8_t count) {
  579. uint16_t delay; // at 20MHz/6, a 16bit delay counter is enough
  580. while (count--) {
  581. LED_PORT.IN |= LED;
  582. // delay assuming 20Mhz OSC. It's only to "look about right", anyway.
  583. for (delay = ((20E6/6)/150); delay; delay--) {
  584. watchdogReset();
  585. if (MYUART.STATUS & USART_RXCIF_bm)
  586. return;
  587. }
  588. }
  589. watchdogReset(); // for breakpointing
  590. }
  591. #endif
  592. /*
  593. * Change the watchdog configuration.
  594. * Could be a new timeout, could be off...
  595. */
  596. void watchdogConfig (uint8_t x) {
  597. while(WDT.STATUS & WDT_SYNCBUSY_bm)
  598. ; // Busy wait for sycnhronization is required!
  599. _PROTECTED_WRITE(WDT.CTRLA, x);
  600. }
  601. #ifndef APP_NOSPM
  602. /*
  603. * Separate function for doing nvmctrl stuff.
  604. * It's needed for application to do manipulate flash, since only the
  605. * bootloader can write or erase flash, or write to the flash alias areas.
  606. * Note that this is significantly different in the details than the
  607. * do_spm() function provided on older AVRs. Same "vector", though.
  608. *
  609. * How it works:
  610. * - if the "command" is legal, write it to NVMCTRL.CTRLA
  611. * - if the command is not legal, store data to *address
  612. * - wait for NVM to complete
  613. *
  614. * For example, to write a flash page:
  615. * Copy each byte with
  616. * do_nvmctrl(flashOffset+MAPPED_PROGMEM_START, 0xFF, *inputPtr);
  617. * Erase and write page with
  618. * do_nvmctrl(0, NVMCTRL_CMD_PAGEERASEWRITE_gc, 0);
  619. */
  620. static void do_nvmctrl(uint16_t address, uint8_t command, uint8_t data) __attribute__ ((used));
  621. static void do_nvmctrl (uint16_t address, uint8_t command, uint8_t data) {
  622. if (command <= NVMCTRL_CMD_gm) {
  623. _PROTECTED_WRITE_SPM(NVMCTRL.CTRLA, command);
  624. while (NVMCTRL.STATUS & (NVMCTRL_FBUSY_bm|NVMCTRL_EEBUSY_bm))
  625. ; // wait for flash and EEPROM not busy, just in case.
  626. } else {
  627. *(uint8_t *)address = data;
  628. }
  629. }
  630. #endif
  631. #ifdef BIGBOOT
  632. /*
  633. * Optiboot is designed to fit in 512 bytes, with a minimum feature set.
  634. * Some chips have a minimum bootloader size of 1024 bytes, and sometimes
  635. * it is desirable to add extra features even though 512bytes is exceedded.
  636. * In that case, the BIGBOOT can be used.
  637. * Our extra features so far don't come close to filling 1k, so we can
  638. * add extra "frivolous" data to the image. In particular, we can add
  639. * information about how Optiboot was built (which options were selected,
  640. * what version, all in human-readable form (and extractable from the
  641. * binary with avr-strings.)
  642. *
  643. * This can always be removed or trimmed if more actual program space
  644. * is needed in the future. Currently the data occupies about 160 bytes,
  645. */
  646. #define xstr(s) str(s)
  647. #define str(s) #s
  648. #define OPTFLASHSECT __attribute__((section(".fini8")))
  649. #define OPT2FLASH(o) OPTFLASHSECT const char f##o[] = #o "=" xstr(o)
  650. __attribute__((section(".fini9"))) const char f_delimit = 0xFF;
  651. #ifdef LED_START_FLASHES
  652. OPT2FLASH(LED_START_FLASHES);
  653. #endif
  654. #ifdef LED_DATA_FLASH
  655. OPT2FLASH(LED_DATA_FLASH);
  656. #endif
  657. #ifdef LED_START_ON
  658. OPT2FLASH(LED_START_ON);
  659. #endif
  660. #ifdef LED_NAME
  661. OPTFLASHSECT const char f_LED[] = "LED=" LED_NAME;
  662. #endif
  663. #ifdef SUPPORT_EEPROM
  664. OPT2FLASH(SUPPORT_EEPROM);
  665. #endif
  666. #if defined(RS485)
  667. OPTFLASHSECT const char f_rs485[] = "RS485=" RS485_NAME;
  668. #endif
  669. #ifdef BAUD_RATE
  670. OPT2FLASH(BAUD_RATE);
  671. #endif
  672. #ifdef UARTTX
  673. OPTFLASHSECT const char f_uart[] = "UARTTX=" UART_NAME;
  674. #endif
  675. OPTFLASHSECT const char f_date[] = "Built:" __DATE__ ":" __TIME__;
  676. #ifdef BIGBOOT
  677. OPT2FLASH(BIGBOOT);
  678. #endif
  679. OPTFLASHSECT const char f_device[] = "Device=" xstr(__AVR_DEVICE_NAME__);
  680. #ifdef OPTIBOOT_CUSTOMVER
  681. # if OPTIBOOT_CUSTOMVER != 0
  682. OPT2FLASH(OPTIBOOT_CUSTOMVER);
  683. # endif
  684. #endif
  685. OPTFLASHSECT const char f_version[] = "Version=" xstr(OPTIBOOT_MAJVER) "." xstr(OPTIBOOT_MINVER);
  686. #endif
  687. // Dummy application that will loop back into the bootloader if not overwritten
  688. // This gives the bootloader somewhere to jump, and by referencing otherwise
  689. // unused variables/functions in the bootloader, it prevents them from being
  690. // omitted by the linker, with fewer mysterious link options.
  691. void __attribute__((section( ".application")))
  692. __attribute__((naked)) app();
  693. void app()
  694. {
  695. uint8_t ch;
  696. ch = RSTCTRL.RSTFR;
  697. RSTCTRL.RSTFR = ch; // reset causes
  698. *(volatile uint16_t *)(&optiboot_version); // reference the version
  699. do_nvmctrl(0, NVMCTRL_CMD_PAGEBUFCLR_gc, 0); // reference this function!
  700. __asm__ __volatile__ (
  701. " jmp 0\n" // similar to running off end of memory
  702. );
  703. // _PROTECTED_WRITE(RSTCTRL.SWRR, 1); // cause new reset
  704. }