1
0

optiboot.c 58 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680
  1. #define FUNC_READ 1
  2. #define FUNC_WRITE 1
  3. /**********************************************************/
  4. /* Optiboot bootloader for Arduino */
  5. /* */
  6. /* http://optiboot.googlecode.com */
  7. /* */
  8. /* Arduino-maintained version : See README.TXT */
  9. /* http://code.google.com/p/arduino/ */
  10. /* It is the intent that changes not relevant to the */
  11. /* Arduino production environment get moved from the */
  12. /* optiboot project to the arduino project in "lumps." */
  13. /* */
  14. /* Heavily optimised bootloader that is faster and */
  15. /* smaller than the Arduino standard bootloader */
  16. /* */
  17. /* Enhancements: */
  18. /* Fits in 512 bytes, saving 1.5K of code space */
  19. /* Higher baud rate speeds up programming */
  20. /* Written almost entirely in C */
  21. /* Customisable timeout with accurate timeconstant */
  22. /* Optional virtual UART. No hardware UART required. */
  23. /* Optional virtual boot partition for devices without. */
  24. /* */
  25. /* What you lose: */
  26. /* Implements a skeleton STK500 protocol which is */
  27. /* missing several features including EEPROM */
  28. /* programming and non-page-aligned writes */
  29. /* High baud rate breaks compatibility with standard */
  30. /* Arduino flash settings */
  31. /* */
  32. /* Supported Devices: */
  33. /* With the merges of Spence Konde's ATTinyCore */
  34. /* https://github.com/SpenceKonde/ATTinyCore */
  35. /* and MCUDude's MightyCore, MiniCore, MegaCore, etc */
  36. /* https://github.com/MCUdude */
  37. /* the number of supported chips and configurations */
  38. /* has become quite large. Try "make help" for a list */
  39. /* Not all chips have received the same amount of */
  40. /* overall attention. Some version may have bugs. */
  41. /* */
  42. /* Does not support: */
  43. /* USB based devices (eg. Teensy, Leonardo) */
  44. /* */
  45. /* Assumptions: */
  46. /* The code makes several assumptions that reduce the */
  47. /* code size. They are all true after a hardware reset, */
  48. /* but may not be true if the bootloader is called by */
  49. /* other means or on other hardware. */
  50. /* No interrupts can occur */
  51. /* UART and Timer 1 are set to their reset state */
  52. /* SP points to RAMEND */
  53. /* */
  54. /* Code builds on code, libraries and optimisations from: */
  55. /* stk500boot.c by Jason P. Kyle */
  56. /* Arduino bootloader http://arduino.cc */
  57. /* Spiff's 1K bootloader http://spiffie.org/know/arduino_1k_bootloader/bootloader.shtml */
  58. /* avr-libc project http://nongnu.org/avr-libc */
  59. /* Adaboot http://www.ladyada.net/library/arduino/bootloader.html */
  60. /* AVR305 Atmel Application Note */
  61. /* */
  62. /* Copyright 2013-2021 by Bill Westfield. */
  63. /* Copyright 2010 by Peter Knight. */
  64. /* Note that many others have made major contributions! */
  65. /* */
  66. /* This program is free software; you can redistribute it */
  67. /* and/or modify it under the terms of the GNU General */
  68. /* Public License as published by the Free Software */
  69. /* Foundation; either version 2 of the License, or */
  70. /* (at your option) any later version. */
  71. /* */
  72. /* This program is distributed in the hope that it will */
  73. /* be useful, but WITHOUT ANY WARRANTY; without even the */
  74. /* implied warranty of MERCHANTABILITY or FITNESS FOR A */
  75. /* PARTICULAR PURPOSE. See the GNU General Public */
  76. /* License for more details. */
  77. /* */
  78. /* You should have received a copy of the GNU General */
  79. /* Public License along with this program; if not, write */
  80. /* to the Free Software Foundation, Inc., */
  81. /* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
  82. /* */
  83. /* Licence can be viewed at */
  84. /* http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt */
  85. /* */
  86. /**********************************************************/
  87. /**********************************************************/
  88. /* */
  89. /* Optional defines: */
  90. /* */
  91. /**********************************************************/
  92. /* */
  93. /* BIGBOOT: */
  94. /* Build a 1k bootloader, not 512 bytes. This turns on */
  95. /* extra functionality; notably EEPROM */
  96. /* */
  97. /* NO_APP_SPM: */
  98. /* omit the code that allows applications to "call" the */
  99. /* bootloader to perform SPM operations. */
  100. /* */
  101. /* SUPPORT_EEPROM: */
  102. /* Support reading and writing from EEPROM. This is not */
  103. /* used by Arduino, so off by default. */
  104. /* */
  105. /* WDTTIME: */
  106. /* Bootloader timeout period, in seconds. */
  107. /* 1 and 2 seconds are available on all chips */
  108. /* 4 and 8 are supported on most */
  109. /* */
  110. /* NO_START_APP_ON_POR: */
  111. /* If NO_START_APP_ON_POR is set, the bootloader will */
  112. /* also run on power-on */
  113. /* */
  114. /* START_APP_ON_EXTR: */
  115. /* If START_APP_ON_EXTR is set, the bootloader will not */
  116. /* run in the event of an external reset. */
  117. /* */
  118. /* If both are set, the bootloader will only run if the */
  119. /* app jumps directly to it. */
  120. /* */
  121. /* ---------- Comm features */
  122. /* UART: */
  123. /* UART number (0..n) for devices with more than */
  124. /* one hardware uart (644P, 1284P, etc) */
  125. /* */
  126. /* BAUD_RATE: */
  127. /* Set bootloader baud rate. */
  128. /* */
  129. /* SINGLESPEED: */
  130. /* do not use "U2X" mode for UART initialization. This */
  131. /* can be useful for some bit rates. */
  132. /* */
  133. /* SOFT_UART: */
  134. /* Use AVR305 soft-UART instead of hardware UART. */
  135. /* */
  136. /* RS485: */
  137. /* Either a pin (ex: "B5") or a pin followed by _INV */
  138. /* (ex: "B5_INV") which indicates inverted polarity. */
  139. /* This pin will be held low while transmitting in order */
  140. /* to control the direction pin of an RS485 tranciever */
  141. /* (RS485 support by Vladimir Dronnikov (github.com/dvv) */
  142. /* as used in github.com/SodaqMoja/optiboot ) */
  143. /* */
  144. /* ---------- LED behavior */
  145. /* LED: */
  146. /* Which pin to use for the LED flashs. This is a pin */
  147. /* name like "B5" */
  148. /* */
  149. /* LED_START_FLASHES: */
  150. /* Number of LED flashes on bootup. */
  151. /* */
  152. /* LED_DATA_FLASH: */
  153. /* Flash LED when transferring data. For boards without */
  154. /* TX or RX LEDs, or for people who like blinky lights. */
  155. /* */
  156. /* LED_START_ON: */
  157. /* Instead of blinking, turn the LED on when we start, */
  158. /* and off when it exits. Slightly smaller code. */
  159. /* */
  160. /**********************************************************/
  161. /*
  162. * default values.
  163. */
  164. #if !defined(BIGBOOT)
  165. # define BIGBOOT 0
  166. #endif
  167. #if !defined(SUPPORT_EEPROM)
  168. # define SUPPORT_EEPROM 0
  169. #endif
  170. #if !defined(APP_NOSPM)
  171. # define APP_NOSPM 0
  172. #endif
  173. #if !defined(START_APP_ON_EXTR)
  174. # define START_APP_ON_EXTR 0
  175. #endif
  176. #if !defined(NO_START_APP_ON_POR)
  177. # define NO_START_APP_ON_POR 0
  178. #endif
  179. /* UART options */
  180. #if !defined(SOFT_UART)
  181. # define SOFT_UART 0
  182. #endif
  183. #if !defined(UART)
  184. #define UART 0
  185. #endif
  186. #if !defined(SINGLESPEED)
  187. #define SINGLESPEED 0
  188. #endif
  189. /* LED Options */
  190. #if !defined(LED_START_FLASHES)
  191. #define LED_START_FLASHES 0
  192. #endif
  193. #if !defined(LED_DATA_FLASH)
  194. # define LED_DATA_FLASH 0
  195. #endif
  196. #if !defined(LED_START_ON)
  197. # define LED_START_ON 0
  198. #endif
  199. /**********************************************************/
  200. /* Version Numbers! */
  201. /* */
  202. /* Arduino Optiboot now includes this Version number in */
  203. /* the source and object code. */
  204. /* */
  205. /* Version 3 was released as zip from the optiboot */
  206. /* repository and was distributed with Arduino 0022. */
  207. /* Version 4 starts with the arduino repository commit */
  208. /* that brought the arduino repository up-to-date with */
  209. /* the optiboot source tree changes since v3. */
  210. /* Version 5 was created at the time of the new Makefile */
  211. /* structure (Mar, 2013), even though no binaries changed*/
  212. /* Version 6 added EEPROM support, including causing an */
  213. /* error when trying to write eeprom with versions that */
  214. /* didn't have the code there. Makefiles were further */
  215. /* restructured. Overlapping SPM/download removed. */
  216. /* Version 7 straightened out the MCUSR and RESET */
  217. /* handling, did MORE Makefile mods. EEPROM support now */
  218. /* fits in 512 bytes, if you turn off LED Blinking. */
  219. /* Various bigboot and virboot targets were fixed. */
  220. /* Version 8.0 adds the do_spm code callable from Apps. */
  221. /* */
  222. /* It would be good if versions implemented outside the */
  223. /* official repository used an out-of-seqeunce version */
  224. /* number (like 104.6 if based on based on 4.5) to */
  225. /* prevent collisions. The CUSTOM_VERSION=n option */
  226. /* adds n to the high version to facilitate this. */
  227. /* */
  228. /**********************************************************/
  229. /**********************************************************/
  230. /* Edit History: */
  231. /* */
  232. /* Oct 2021 */
  233. /* 8.3 WestfW add section-start determination code to */
  234. /* the C source. In theory, this causes no changes */
  235. /* to the binary, but it's "risky", so ... bump. */
  236. /* Aug 2019 */
  237. /* 8.1 WestfW Fix bug in calculation of Vboot offset */
  238. /* Sep 2018 */
  239. /* 8.0 WestfW (and Majekw and MCUDude) */
  240. /* Include do_spm routine callable from the app */
  241. /* at BOOTSTART+2, controllable with compile option */
  242. /* July 2018 */
  243. /* 7.0 WestfW (with much input from Others) */
  244. /* Fix MCUSR treatement as per much discussion, */
  245. /* Patches by MarkG55, majekw. Preserve value */
  246. /* for the application, as much as possible. */
  247. /* see https://github.com/Optiboot/optiboot/issues/97 */
  248. /* Optimize a bit by implementing a union for the */
  249. /* various 16bit address values used (based on */
  250. /* observation by "aweatherguy", but different.) */
  251. /* Slightly optimize math in VIRTUAL_BOOT code */
  252. /* Add some virboot targets, fix some fuses. */
  253. /* Implement LED_START_ON; less code than flashes */
  254. /* Aug 2014 */
  255. /* 6.2 WestfW: make size of length variables dependent */
  256. /* on the SPM_PAGESIZE. This saves space */
  257. /* on the chips where it's most important. */
  258. /* 6.1 WestfW: Fix OPTIBOOT_CUSTOMVER (send it!) */
  259. /* Make no-wait mod less picky about */
  260. /* skipping the bootloader. */
  261. /* Remove some dead code */
  262. /* Jun 2014 */
  263. /* 6.0 WestfW: Modularize memory read/write functions */
  264. /* Remove serial/flash overlap */
  265. /* (and all references to NRWWSTART/etc) */
  266. /* Correctly handle pagesize > 255bytes */
  267. /* Add EEPROM support in BIGBOOT (1284) */
  268. /* EEPROM write on small chips now causes err */
  269. /* Split Makefile into smaller pieces */
  270. /* Add Wicked devices Wildfire */
  271. /* Move UART=n conditionals into pin_defs.h */
  272. /* Remove LUDICOUS_SPEED option */
  273. /* Replace inline assembler for .version */
  274. /* and add OPTIBOOT_CUSTOMVER for user code */
  275. /* Fix LED value for Bobuino (Makefile) */
  276. /* Make all functions explicitly inline or */
  277. /* noinline, so we fit when using gcc4.8 */
  278. /* Change optimization options for gcc4.8 */
  279. /* Make ENV=arduino work in 1.5.x trees. */
  280. /* May 2014 */
  281. /* 5.0 WestfW: Add support for 1Mbps UART */
  282. /* Mar 2013 */
  283. /* 5.0 WestfW: Major Makefile restructuring. */
  284. /* See Makefile and pin_defs.h */
  285. /* (no binary changes) */
  286. /* */
  287. /* 4.6 WestfW/Pito: Add ATmega32 support */
  288. /* 4.6 WestfW/radoni: Don't set LED_PIN as an output if */
  289. /* not used. (LED_START_FLASHES = 0) */
  290. /* Jan 2013 */
  291. /* 4.6 WestfW/dkinzer: use autoincrement lpm for read */
  292. /* 4.6 WestfW/dkinzer: pass reset cause to app in R2 */
  293. /* Mar 2012 */
  294. /* 4.5 WestfW: add infrastructure for non-zero UARTS. */
  295. /* 4.5 WestfW: fix SIGNATURE_2 for m644 (bad in avr-libc) */
  296. /* Jan 2012: */
  297. /* 4.5 WestfW: fix NRWW value for m1284. */
  298. /* 4.4 WestfW: use attribute OS_main instead of naked for */
  299. /* main(). This allows optimizations that we */
  300. /* count on, which are prohibited in naked */
  301. /* functions due to PR42240. (keeps us less */
  302. /* than 512 bytes when compiler is gcc4.5 */
  303. /* (code from 4.3.2 remains the same.) */
  304. /* 4.4 WestfW and Maniacbug: Add m1284 support. This */
  305. /* does not change the 328 binary, so the */
  306. /* version number didn't change either. (?) */
  307. /* June 2011: */
  308. /* 4.4 WestfW: remove automatic soft_uart detect (didn't */
  309. /* know what it was doing or why.) Added a */
  310. /* check of the calculated BRG value instead. */
  311. /* Version stays 4.4; existing binaries are */
  312. /* not changed. */
  313. /* 4.4 WestfW: add initialization of address to keep */
  314. /* the compiler happy. Change SC'ed targets. */
  315. /* Return the SW version via READ PARAM */
  316. /* 4.3 WestfW: catch framing errors in getch(), so that */
  317. /* AVRISP works without HW kludges. */
  318. /* http://code.google.com/p/arduino/issues/detail?id=368n*/
  319. /* 4.2 WestfW: reduce code size, fix timeouts, change */
  320. /* verifySpace to use WDT instead of appstart */
  321. /* 4.1 WestfW: put version number in binary. */
  322. /**********************************************************/
  323. #define OPTIBOOT_MAJVER 8
  324. #define OPTIBOOT_MINVER 3
  325. /*
  326. * OPTIBOOT_CUSTOMVER should be defined (by the makefile) for custom edits
  327. * of optiboot. That way you don't wind up with very different code that
  328. * matches the version number of a "released" optiboot.
  329. */
  330. #if !defined(OPTIBOOT_CUSTOMVER)
  331. #define OPTIBOOT_CUSTOMVER 0
  332. #endif
  333. unsigned const int __attribute__((section(".version")))
  334. optiboot_version = 256*(OPTIBOOT_MAJVER + OPTIBOOT_CUSTOMVER) + OPTIBOOT_MINVER;
  335. #define __AVR_LIBC_DEPRECATED_ENABLE__ 1 // don't poison MCUSR on some chips
  336. #include <inttypes.h>
  337. #include <avr/io.h>
  338. #include <avr/pgmspace.h>
  339. #include <avr/eeprom.h>
  340. /*
  341. * optiboot uses several "address" variables that are sometimes byte pointers,
  342. * sometimes word pointers. sometimes 16bit quantities, and sometimes built
  343. * up from 8bit input characters. avr-gcc is not great at optimizing the
  344. * assembly of larger words from bytes, but we can use the usual union to
  345. * do this manually. Expanding it a little, we can also get rid of casts.
  346. */
  347. typedef union {
  348. uint8_t *bptr;
  349. uint16_t *wptr;
  350. uint16_t word;
  351. uint8_t bytes[2];
  352. } addr16_t;
  353. /*
  354. * Note that we use a replacement of "boot.h"
  355. * <avr/boot.h> uses sts instructions, but this version uses out instructions
  356. * This saves cycles and program memory, if possible.
  357. * boot_opt.h pulls in the standard boot.h for the odd target (?)
  358. */
  359. #include "boot_opt.h"
  360. // We don't use <avr/wdt.h> as those routines have interrupt overhead we don't need.
  361. /*
  362. * pin_defs.h
  363. * This contains most of the rather ugly defines that implement our
  364. * ability to use UART=n and LED=D3, and some avr family bit name differences.
  365. */
  366. #include "pin_defs.h"
  367. /*
  368. * stk500.h contains the constant definitions for the stk500v1 comm protocol
  369. */
  370. #include "stk500.h"
  371. /* set the UART baud rate defaults */
  372. #ifndef BAUD_RATE
  373. #if F_CPU >= 8000000L
  374. #define BAUD_RATE 115200L // Highest rate Avrdude win32 will support
  375. #elif F_CPU >= 1000000L
  376. #define BAUD_RATE 9600L // 19200 also supported, but with significant error
  377. #elif F_CPU >= 128000L
  378. #define BAUD_RATE 4800L // Good for 128kHz internal RC
  379. #else
  380. #define BAUD_RATE 1200L // Good even at 32768Hz
  381. #endif
  382. #endif
  383. #if (SOFT_UART == 0)
  384. #if SINGLESPEED
  385. /* Single speed option */
  386. #define BAUD_SETTING (( (F_CPU + BAUD_RATE * 8L) / ((BAUD_RATE * 16L))) - 1 )
  387. #define BAUD_ACTUAL (F_CPU/(16 * ((BAUD_SETTING)+1)))
  388. #else
  389. /* Normal U2X usage */
  390. #define BAUD_SETTING (( (F_CPU + BAUD_RATE * 4L) / ((BAUD_RATE * 8L))) - 1 )
  391. #define BAUD_ACTUAL (F_CPU/(8 * ((BAUD_SETTING)+1)))
  392. #endif
  393. #if BAUD_ACTUAL <= BAUD_RATE
  394. #define BAUD_ERROR (( 100*(BAUD_RATE - BAUD_ACTUAL) ) / BAUD_RATE)
  395. #if BAUD_ERROR >= 5
  396. #error BAUD_RATE off by greater than -5%
  397. #elif BAUD_ERROR >= 2 && !defined(PRODUCTION)
  398. #warning BAUD_RATE off by greater than -2%
  399. #endif
  400. #else
  401. #define BAUD_ERROR (( 100*(BAUD_ACTUAL - BAUD_RATE) ) / BAUD_RATE)
  402. #if BAUD_ERROR >= 5
  403. #error BAUD_RATE off by greater than 5%
  404. #elif BAUD_ERROR >= 2 && !defined(PRODUCTION)
  405. #warning BAUD_RATE off by greater than 2%
  406. #endif
  407. #endif
  408. #if BAUD_SETTING > 250
  409. #error Unachievable baud rate (too slow) BAUD_RATE
  410. #endif // baud rate slow check
  411. #if (BAUD_SETTING - 1) < 3
  412. #if BAUD_ERROR != 0 // permit high bitrates (ie 1Mbps@16MHz) if error is zero
  413. #error Unachievable baud rate (too fast) BAUD_RATE
  414. #endif
  415. #endif // baud rate fast check
  416. #endif // SOFT_UART
  417. /* Watchdog settings */
  418. #define WATCHDOG_OFF (0)
  419. #define WATCHDOG_16MS (_BV(WDE))
  420. #define WATCHDOG_32MS (_BV(WDP0) | _BV(WDE))
  421. #define WATCHDOG_64MS (_BV(WDP1) | _BV(WDE))
  422. #define WATCHDOG_125MS (_BV(WDP1) | _BV(WDP0) | _BV(WDE))
  423. #define WATCHDOG_250MS (_BV(WDP2) | _BV(WDE))
  424. #define WATCHDOG_500MS (_BV(WDP2) | _BV(WDP0) | _BV(WDE))
  425. #define WATCHDOG_1S (_BV(WDP2) | _BV(WDP1) | _BV(WDE))
  426. #define WATCHDOG_2S (_BV(WDP2) | _BV(WDP1) | _BV(WDP0) | _BV(WDE))
  427. #ifdef WDP3
  428. #define WATCHDOG_4S (_BV(WDP3) | _BV(WDE))
  429. #define WATCHDOG_8S (_BV(WDP3) | _BV(WDP0) | _BV(WDE))
  430. #endif
  431. /*
  432. * Watchdog timeout translations from human readable to config vals
  433. */
  434. #ifndef WDTTIME
  435. # define WDTPERIOD WATCHDOG_1S // 1 second default
  436. #elif WDTTIME == 1
  437. # define WDTPERIOD WATCHDOG_1S // 1 second
  438. #elif WDTTIME == 2
  439. # define WDTPERIOD WATCHDOG_2S // 2 seconds
  440. #elif defined(WDP3) && (WDTTIME == 4)
  441. # define WDTPERIOD WATCHDOG_4S // 4 seconds
  442. #elif defined(WDP3) && (WDTTIME == 8)
  443. # define WDTPERIOD WATCHDOG_8S // 8 seconds
  444. #else
  445. #error Invalid TIMEOUT
  446. #endif
  447. /*
  448. * We can never load flash with more than 1 page at a time, so we can save
  449. * some code space on parts with smaller pagesize by using a smaller int.
  450. */
  451. #if SPM_PAGESIZE > 255
  452. typedef uint16_t pagelen_t ;
  453. #define GETLENGTH(len) len = getch()<<8; len |= getch()
  454. #else
  455. typedef uint8_t pagelen_t;
  456. #define GETLENGTH(len) (void) getch() /* skip high byte */; len = getch()
  457. #endif
  458. /* Function Prototypes
  459. * The main() function is in init9, which removes the interrupt vector table
  460. * we don't need. It is also 'OS_main', which means the compiler does not
  461. * generate any entry or exit code itself (but unlike 'naked', it doesn't
  462. * suppress some compile-time options we want.)
  463. */
  464. void pre_main(void) __attribute__ ((naked)) __attribute__ ((section (".init8")));
  465. int main(void) __attribute__ ((OS_main)) __attribute__ ((section (".init9"))) __attribute__((used));
  466. void __attribute__((noinline)) __attribute__((leaf)) putch(char);
  467. uint8_t __attribute__((noinline)) __attribute__((leaf)) getch(void) ;
  468. void __attribute__((noinline)) verifySpace();
  469. void __attribute__((noinline)) watchdogConfig(uint8_t x);
  470. static void getNch(uint8_t);
  471. #if LED_START_FLASHES > 0
  472. static inline void flash_led(uint8_t);
  473. #endif
  474. static inline void watchdogReset();
  475. static inline void writebuffer(int8_t memtype, addr16_t mybuff,
  476. addr16_t address, pagelen_t len);
  477. static inline void read_mem(uint8_t memtype,
  478. addr16_t, pagelen_t len);
  479. #if SOFT_UART
  480. void uartDelay() __attribute__ ((naked));
  481. #endif
  482. /*
  483. * RAMSTART should be self-explanatory. It's bigger on parts with a
  484. * lot of peripheral registers. Let 0x100 be the default
  485. * Note that RAMSTART (for optiboot) need not be exactly at the start of RAM.
  486. */
  487. #if !defined(RAMSTART) // newer versions of gcc avr-libc define RAMSTART
  488. #define RAMSTART 0x100
  489. #if defined (__AVR_ATmega644P__)
  490. // correct for a bug in avr-libc
  491. #undef SIGNATURE_2
  492. #define SIGNATURE_2 0x0A
  493. #elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
  494. #undef RAMSTART
  495. #define RAMSTART (0x200)
  496. #endif
  497. #endif
  498. /* C zero initialises all global variables. However, that requires */
  499. /* These definitions are NOT zero initialised, but that doesn't matter */
  500. /* This allows us to drop the zero init code, saving us memory */
  501. static addr16_t buff = {(uint8_t *)(RAMSTART)};
  502. /* Virtual boot partition support */
  503. #ifdef VIRTUAL_BOOT_PARTITION
  504. // RAM locations to save vector info (temporarilly)
  505. #define rstVect0_sav (*(uint8_t*)(RAMSTART+SPM_PAGESIZE*2+4))
  506. #define rstVect1_sav (*(uint8_t*)(RAMSTART+SPM_PAGESIZE*2+5))
  507. #define saveVect0_sav (*(uint8_t*)(RAMSTART+SPM_PAGESIZE*2+6))
  508. #define saveVect1_sav (*(uint8_t*)(RAMSTART+SPM_PAGESIZE*2+7))
  509. #define RSTVEC_ADDRESS 0 // flash address where vectors start.
  510. // Vector to save original reset jump:
  511. // SPM Ready is least probably used, so it's default
  512. // if not, use old way WDT_vect_num,
  513. // or simply set custom save_vect_num in Makefile using vector name
  514. // or even raw number.
  515. #if !defined (save_vect_num)
  516. #if defined (SPM_RDY_vect_num)
  517. #define save_vect_num (SPM_RDY_vect_num)
  518. #elif defined (SPM_READY_vect_num)
  519. #define save_vect_num (SPM_READY_vect_num)
  520. #elif defined (EE_RDY_vect_num)
  521. #define save_vect_num (EE_RDY_vect_num)
  522. #elif defined (EE_READY_vect_num)
  523. #define save_vect_num (EE_READY_vect_num)
  524. #elif defined (WDT_vect_num)
  525. #define save_vect_num (WDT_vect_num)
  526. #else
  527. #error "Can't find SPM or WDT interrupt vector for this CPU"
  528. #endif
  529. #endif //save_vect_num
  530. // check if it's on the same page (code assumes that)
  531. #if FLASHEND > 8192
  532. // AVRs with more than 8k of flash have 4-byte vectors, and use jmp.
  533. // We save only 16 bits of address, so devices with more than 128KB
  534. // may behave wrong for upper part of address space.
  535. #define rstVect0 2
  536. #define rstVect1 3
  537. #define saveVect0 (save_vect_num*4+2)
  538. #define saveVect1 (save_vect_num*4+3)
  539. #define appstart_vec (save_vect_num*2)
  540. // address of page that will have the saved vector
  541. #define SAVVEC_ADDRESS (SPM_PAGESIZE*(save_vect_num/(SPM_PAGESIZE/4)))
  542. #else
  543. // AVRs with up to 8k of flash have 2-byte vectors, and use rjmp.
  544. #define rstVect0 0
  545. #define rstVect1 1
  546. #define saveVect0 (save_vect_num*2)
  547. #define saveVect1 (save_vect_num*2+1)
  548. #define appstart_vec (save_vect_num)
  549. // address of page that will have the saved vector
  550. #define SAVVEC_ADDRESS (SPM_PAGESIZE*(save_vect_num/(SPM_PAGESIZE/2)))
  551. #endif
  552. #else
  553. #define appstart_vec (0)
  554. #endif // VIRTUAL_BOOT_PARTITION
  555. void sectionOpts() __attribute__((naked));
  556. void sectionOpts() {
  557. /*
  558. * Mysterious Magic code to allow section-start addresses to be
  559. * specifed by the C code (which, after all, has access to CPP symbols
  560. * like FLASHEND, and can make a "safer" guess than putting manually
  561. * determined constants in the Makefile. This is dependent on a custom
  562. * linker script that makes use of the __BOOT_ symbols that we define.
  563. * Fortunately, that script can be used to link optiboot on any of its
  564. * usual chips.
  565. *
  566. * with some judicious use of asm directives, we can define symbols
  567. * that the linker will look at for positioning our segments (in
  568. * combination with a custom linker script) based on the flash size
  569. * defined via io.h, instead of requiring magic --section-start
  570. * constants on the build line.
  571. *
  572. * This apparently needs to be inside a function in order to pass
  573. * arguments to the asm command (even though the asm doesn't
  574. * generate any code) But we can make sure the function (which doesn't
  575. * actually contain any code) doesn't actually end up in the binary.
  576. */
  577. #if BIGBOOT
  578. /*
  579. * BIGBOOT images are easy, because they're much smaller than the
  580. * flash size that they are defined to occupy (1k)
  581. */
  582. asm(" .global __BOOT_SIZE__, __BOOT_START__, __VERSION_START__\n"
  583. " .equ __BOOT_SIZE__, 1024\n"
  584. " .equ __BOOT_START__, (%0-1023)\n"
  585. " .equ __VERSION_START__, (%0-1)\n"
  586. ::"i"((uint32_t)FLASHEND));
  587. #else
  588. /*
  589. * non-BIGBOOT images try to fit in 512bytes, but don't quite fit
  590. * on chips that don't have HW support for a boot section. We try
  591. * to guess how big the extra bits of code are, and then round up
  592. * to the next larger flash page boundry (which can be nearly 4 pages
  593. * away on chips with FOURPAGEERASE)
  594. * These numbers are determined manually by building a reference
  595. * implementation with various options and comparing sizes.
  596. */
  597. # if VIRTUAL_BOOT_PARTITION
  598. /* VIRTUAL_BOOT_PARTITION code is about 100 bytes */
  599. # define VBSIZE 110
  600. # else
  601. # define VBSIZE 0
  602. # endif
  603. # if LED_START_FLASHES==0
  604. /* if LED_START_FLASHES is 0 (eg on 8pin chips), it saves some code */
  605. # define LEDSIZE (-30)
  606. # else
  607. # define LEDSIZE 0
  608. # endif
  609. # if SOFT_UART
  610. /* But not having a hardware UART costs a bit */
  611. # define SOFTUSIZE 16
  612. # else
  613. # define SOFTUSIZE 0
  614. # endif
  615. # if FOURPAGEERASE
  616. /* FOURPAGEERASE adds some code, and also affects how we round */
  617. # define ERASESIZE 8
  618. # define PAGSIZ_B (SPM_PAGESIZE*4)
  619. # else
  620. # define PAGSIZ_B (SPM_PAGESIZE)
  621. # define ERASESIZE 0
  622. # endif
  623. /*
  624. * Round our guess up to next page size. So 560 byte images occupy 576bytes,
  625. * 600 byte images occupy 640 bytes, etc. Depending on chip.
  626. * Note that SPM_PAGESIZE is already in bytes in the .h files.
  627. */
  628. # define ROUNDTOPAGE(size) (((size + (PAGSIZ_B/2))/(PAGSIZ_B))*(PAGSIZ_B))
  629. /* use 511 here so we don't round up to the next page on normal systems. */
  630. # define BOOTSIZE (511+ERASESIZE+VBSIZE+SOFTUSIZE+LEDSIZE)
  631. asm(" .global __BOOT_SIZE__, __BOOT_START__, __VERSION_START__\n"
  632. " .equ __BOOT_SIZE__, %1\n"
  633. " .equ __BOOT_START__, ((%0+1)-%1)\n"
  634. " .equ __VERSION_START__, (%0-1)\n"
  635. ::"i"((uint32_t)FLASHEND), "i"(ROUNDTOPAGE(BOOTSIZE)));
  636. #endif
  637. /* Wasn't that FUN! */
  638. }
  639. /* everything that needs to run VERY early */
  640. void pre_main(void) {
  641. // Allow convenient way of calling do_spm function - jump table, so
  642. // entry to this function will always be here, independent of
  643. // compilation, features etc
  644. asm volatile (
  645. " rjmp 1f\n"
  646. #if APP_NOSPM
  647. " ret\n" // if do_spm isn't include, return without doing anything
  648. #else
  649. " rjmp do_spm\n"
  650. #endif
  651. "1:\n"
  652. );
  653. }
  654. /* main program starts here */
  655. int main(void) {
  656. uint8_t ch;
  657. /*
  658. * Making these local and in registers prevents the need for initializing
  659. * them, and also saves space because code no longer stores to memory.
  660. * (initializing address keeps the compiler happy, but isn't really
  661. * necessary, and uses 4 bytes of flash.)
  662. */
  663. register addr16_t address;
  664. register pagelen_t length;
  665. // After the zero init loop, this is the first code to run.
  666. //
  667. // This code makes the following assumptions:
  668. // No interrupts will execute
  669. // SP points to RAMEND
  670. // r1 contains zero
  671. //
  672. // If not, uncomment the following instructions:
  673. // cli();
  674. asm volatile (" clr __zero_reg__");
  675. #if defined(__AVR_ATmega8__) || defined(__AVR_ATmega8515__) || \
  676. defined(__AVR_ATmega8535__) || defined (__AVR_ATmega16__) || \
  677. defined (__AVR_ATmega32__) || defined (__AVR_ATmega64__) || \
  678. defined (__AVR_ATmega128__) || defined (__AVR_ATmega162__)
  679. SP=RAMEND; // This is done by hardware reset on newer chips
  680. #endif
  681. #if defined(OSCCAL_VALUE)
  682. OSCCAL = OSCCAL_VALUE;
  683. #endif
  684. /*
  685. * Protect as much from MCUSR as possible for application
  686. * and still skip bootloader if not necessary
  687. *
  688. * Code by MarkG55
  689. * see discussion in https://github.com/Optiboot/optiboot/issues/97
  690. */
  691. #ifndef MCUSR // Backward compatability with old AVRs
  692. #define MCUSR MCUCSR
  693. #endif
  694. #if (START_APP_ON_EXTR == 0 && NO_START_APP_ON_POR == 0)
  695. /*
  696. * Normal behavior. Start if EXTRF in on and WDRF is off
  697. */
  698. # define APP_START_REASONS ((ch & (_BV(WDRF) | _BV(EXTRF))) != _BV(EXTRF))
  699. # define WDRF_CLR_REASONS (ch & _BV(EXTRF))
  700. #elif (START_APP_ON_EXTR && NO_START_APP_ON_POR)
  701. /*
  702. * If NO_START_APP_ON_POR is defined, run bootloader after POR.
  703. * This allows use with reset disabled: power on and immediately
  704. * program.
  705. */
  706. # define APP_START_REASONS ((ch & (_BV(PORF) | _BV(WDRF) | _BV(EXTRF))) != _BV(PORF))
  707. # define WDRF_CLR_REASONS ((ch & (_BV(PORF) | _BV(WDRF))) == (_BV(PORF) | _BV(WDRF)))
  708. #elif ((START_APP_ON_EXTR == 0) && NO_START_APP_ON_POR)
  709. /*
  710. * If START_APP_ON_EXTR is defined, don't run bootloader after
  711. * an external reset - only useful in combination with above,
  712. * for some unusual use cases.
  713. */
  714. # define APP_START_REASONS (ch & _BV(WDRF))
  715. # define WDRF_CLR_REASONS (ch & (_BV(PORF) | _BV(EXTRF)))
  716. #else
  717. /*
  718. * Only run bootloader via jmp to 0 with MCUSR==0.
  719. * Probably an error.
  720. */
  721. # warning "Bootloader can only start via app request because "
  722. # warning "START_APP_ON_EXTR is defined and NO_START_APP_ON_POR isn't"
  723. # define APP_START_REASONS 1 /* Always start rge App. */
  724. # define WDRF_CLR_REASONS 0 /* Never clear WDRF */
  725. #endif
  726. ch = MCUSR;
  727. // Skip all logic and run bootloader if MCUSR is cleared (application request)
  728. if (ch != 0) {
  729. /*
  730. * To run the boot loader, External Reset Flag must be set.
  731. * If not, we could make shortcut and jump directly to application code.
  732. * Also WDRF set with EXTRF is a result of Optiboot timeout, so we
  733. * shouldn't run bootloader in loop :-) That's why:
  734. * 1. application is running if WDRF is cleared
  735. * 2. we clear WDRF if it's set with EXTRF to avoid loops
  736. * One problematic scenario: broken application code sets watchdog timer
  737. * without clearing MCUSR before and triggers it quickly. But it's
  738. * recoverable by power-on with pushed reset button.
  739. */
  740. if (APP_START_REASONS) {
  741. if (WDRF_CLR_REASONS) {
  742. /*
  743. * Clear WDRF if it was most probably set by wdr in bootloader.
  744. */
  745. if ((uint16_t)&MCUSR > 0x1F) {
  746. MCUSR = ~(_BV(WDRF)); // optimize to LDI/OUT
  747. } else {
  748. MCUSR &= ~(_BV(WDRF)); // or optimize to CBI if possible
  749. }
  750. }
  751. /*
  752. * save the reset flags in the designated register
  753. * This can be saved in a main program by putting code in .init0 (which
  754. * executes before normal c init code) to save R2 to a global variable.
  755. */
  756. __asm__ __volatile__ (" mov r2, %0\n" :: "r" (ch));
  757. // switch off watchdog
  758. watchdogConfig(WATCHDOG_OFF);
  759. // Note that appstart_vec is defined so that this works with either
  760. // real or virtual boot partitions.
  761. __asm__ __volatile__ (
  762. // Jump to 'save' or RST vector
  763. #ifdef VIRTUAL_BOOT_PARTITION
  764. // full code version for virtual boot partition
  765. " ldi r30,%[rstvec]\n"
  766. " clr r31\n"
  767. " ijmp\n"::[rstvec] "M"(appstart_vec)
  768. #else
  769. #ifdef RAMPZ
  770. // use absolute jump for devices with lot of flash
  771. " jmp 0\n"::
  772. #else
  773. // use rjmp to go around end of flash to address 0
  774. // it uses fact that optiboot_version constant is 2 bytes before end of flash
  775. " rjmp optiboot_version+2\n"
  776. #endif //RAMPZ
  777. #endif //VIRTUAL_BOOT_PARTITION
  778. );
  779. }
  780. } //end handling of MCUSR !=0
  781. #if LED_START_FLASHES > 0
  782. // Set up Timer 1 for timeout counter
  783. #if defined(__AVR_ATtiny261__)||defined(__AVR_ATtiny461__)||defined(__AVR_ATtiny861__)
  784. TCCR1B = 0x0E; //div 8196 - we could divide by less since it's a 10-bit counter, but why?
  785. #elif defined(__AVR_ATtiny25__)||defined(__AVR_ATtiny45__)||defined(__AVR_ATtiny85__)
  786. TCCR1 = 0x0E; //div 8196 - it's an 8-bit timer.
  787. #elif defined(__AVR_ATtiny43__)
  788. #error "LED flash for Tiny43 not yet supported"
  789. #else
  790. TCCR1B = _BV(CS12) | _BV(CS10); // div 1024
  791. #endif
  792. #endif
  793. #if (SOFT_UART == 0)
  794. #if defined(__AVR_ATmega8__) || defined (__AVR_ATmega8515__) || \
  795. defined (__AVR_ATmega8535__) || defined (__AVR_ATmega16__) || \
  796. defined (__AVR_ATmega32__)
  797. #if (SINGLESPEED == 0)
  798. UCSRA = _BV(U2X); //Double speed mode USART
  799. #endif //singlespeed
  800. UCSRB = _BV(RXEN) | _BV(TXEN); // enable Rx & Tx
  801. UCSRC = _BV(URSEL) | _BV(UCSZ1) | _BV(UCSZ0); // config USART; 8N1
  802. UBRRL = (uint8_t)BAUD_SETTING;
  803. #else // mega8/etc
  804. #ifdef LIN_UART
  805. //DDRB|=3;
  806. LINCR = (1 << LSWRES);
  807. //LINBRRL = (((F_CPU * 10L / 32L / BAUD_RATE) + 5L) / 10L) - 1;
  808. LINBRRL=(uint8_t)BAUD_SETTING;
  809. LINBTR = (1 << LDISR) | (8 << LBT0);
  810. LINCR = _BV(LENA) | _BV(LCMD2) | _BV(LCMD1) | _BV(LCMD0);
  811. LINDAT=0;
  812. #else
  813. #if (SINGLESPEED == 0)
  814. UART_SRA = _BV(U2X0); //Double speed mode USART0
  815. #endif
  816. UART_SRB = _BV(RXEN0) | _BV(TXEN0);
  817. UART_SRC = _BV(UCSZ00) | _BV(UCSZ01);
  818. UART_SRL = (uint8_t)BAUD_SETTING;
  819. #endif // LIN_UART
  820. #endif // mega8/etc
  821. #endif // soft_uart
  822. #ifdef RS485
  823. RS485_DDR |= _BV(RS485_BIT);
  824. #ifdef RS485_INVERT
  825. RS485_PORT |= _BV(RS485_BIT);
  826. #else
  827. RS485_PORT &= ~_BV(RS485_BIT);
  828. #endif
  829. #endif
  830. // Set up watchdog to trigger after desired timeout
  831. watchdogConfig(WDTPERIOD);
  832. #if (LED_START_FLASHES > 0) || LED_DATA_FLASH || LED_START_ON
  833. /* Set LED pin as output */
  834. LED_DDR |= _BV(LED);
  835. #endif
  836. /* hold POWER_ON (GPStracker) */
  837. DDRA |= _BV(PA3);
  838. PORTA |= _BV(PA3);
  839. #if SOFT_UART
  840. /* Set TX pin as HIGH output */
  841. UART_PORT |= _BV(UART_TX_BIT);
  842. UART_DDR |= _BV(UART_TX_BIT);
  843. #endif
  844. #if LED_START_FLASHES > 0
  845. /* Flash onboard LED to signal entering of bootloader */
  846. flash_led(LED_START_FLASHES * 2);
  847. #else
  848. #if LED_START_ON
  849. /* Turn on LED to indicate starting bootloader (less code!) */
  850. LED_PORT |= _BV(LED);
  851. #endif
  852. #endif
  853. /* Forever loop: exits by causing WDT reset */
  854. for (;;) {
  855. /* get character from UART */
  856. ch = getch();
  857. if (ch == STK_GET_PARAMETER) {
  858. unsigned char which = getch();
  859. verifySpace();
  860. /*
  861. * Send optiboot version as "SW version"
  862. * Note that the references to memory are optimized away.
  863. */
  864. if (which == STK_SW_MINOR) {
  865. putch(optiboot_version & 0xFF);
  866. } else if (which == STK_SW_MAJOR) {
  867. putch(optiboot_version >> 8);
  868. } else {
  869. /*
  870. * GET PARAMETER returns a generic 0x03 reply for
  871. * other parameters - enough to keep Avrdude happy
  872. */
  873. putch(0x03);
  874. }
  875. }
  876. else if (ch == STK_SET_DEVICE) {
  877. // SET DEVICE is ignored
  878. getNch(20);
  879. }
  880. else if (ch == STK_SET_DEVICE_EXT) {
  881. // SET DEVICE EXT is ignored
  882. getNch(5);
  883. }
  884. else if (ch == STK_LOAD_ADDRESS) {
  885. // LOAD ADDRESS
  886. address.bytes[0] = getch();
  887. address.bytes[1] = getch();
  888. #ifdef RAMPZ
  889. // Transfer top bit to LSB in RAMPZ
  890. if (address.bytes[1] & 0x80) {
  891. RAMPZ |= 0x01;
  892. }
  893. else {
  894. RAMPZ &= 0xFE;
  895. }
  896. #endif
  897. address.word *= 2; // Convert from word address to byte address
  898. verifySpace();
  899. }
  900. else if (ch == STK_UNIVERSAL) {
  901. #ifdef RAMPZ
  902. // LOAD_EXTENDED_ADDRESS is needed in STK_UNIVERSAL for addressing more than 128kB
  903. if ( AVR_OP_LOAD_EXT_ADDR == getch() ) {
  904. // get address
  905. getch(); // get '0'
  906. RAMPZ = (RAMPZ & 0x01) | ((getch() << 1) & 0xff); // get address and put it in RAMPZ
  907. getNch(1); // get last '0'
  908. // response
  909. putch(0x00);
  910. }
  911. else {
  912. // everything else is ignored
  913. getNch(3);
  914. putch(0x00);
  915. }
  916. #else
  917. // UNIVERSAL command is ignored
  918. getNch(4);
  919. putch(0x00);
  920. #endif
  921. }
  922. /* Write memory, length is big endian and is in bytes */
  923. else if (ch == STK_PROG_PAGE) {
  924. // PROGRAM PAGE - we support flash programming only, not EEPROM
  925. uint8_t desttype;
  926. uint8_t *bufPtr;
  927. pagelen_t savelength;
  928. GETLENGTH(length);
  929. savelength = length;
  930. desttype = getch();
  931. // read a page worth of contents
  932. bufPtr = buff.bptr;
  933. do *bufPtr++ = getch();
  934. while (--length);
  935. // Read command terminator, start reply
  936. verifySpace();
  937. #ifdef VIRTUAL_BOOT_PARTITION
  938. /*
  939. * How the Virtual Boot Partition works:
  940. * At the beginning of a normal AVR program are a set of vectors that
  941. * implement the interrupt mechanism. Each vector is usually a single
  942. * instruction that dispatches to the appropriate ISR.
  943. * The instruction is normally an rjmp (on AVRs with 8k or less of flash)
  944. * or jmp instruction, and the 0th vector is executed on reset and jumps
  945. * to the start of the user program:
  946. * vectors: jmp startup
  947. * jmp ISR1
  948. * jmp ISR2
  949. * : ;; etc
  950. * jmp lastvector
  951. * To implement the "Virtual Boot Partition", Optiboot detects when the
  952. * flash page containing the vectors is being programmed, and replaces the
  953. * startup vector with a jump to te beginning of Optiboot. Then it saves
  954. * the applications's startup vector in another (must be unused by the
  955. * application), and finally programs the page with the changed vectors.
  956. * Thereafter, on reset, the vector will dispatch to the beginning of
  957. * Optiboot. When Optiboot decides that it will run the user application,
  958. * it fetches the saved start address from the unused vector, and jumps
  959. * there.
  960. * The logic is dependent on size of flash, and whether the reset vector is
  961. * on the same flash page as the saved start address.
  962. */
  963. #if FLASHEND > 8192
  964. /*
  965. * AVR with 4-byte ISR Vectors and "jmp"
  966. * WARNING: this works only up to 128KB flash!
  967. */
  968. #if FLASHEND > (128*1024)
  969. #error "Can't use VIRTUAL_BOOT_PARTITION with more than 128k of Flash"
  970. #endif
  971. if (address.word == RSTVEC_ADDRESS) {
  972. // This is the reset vector page. We need to live-patch the
  973. // code so the bootloader runs first.
  974. //
  975. // Save jmp targets (for "Verify")
  976. rstVect0_sav = buff.bptr[rstVect0];
  977. rstVect1_sav = buff.bptr[rstVect1];
  978. // Add "jump to Optiboot" at RESET vector
  979. // WARNING: this works as long as 'main' is in first section
  980. buff.bptr[rstVect0] = ((uint16_t)pre_main) & 0xFF;
  981. buff.bptr[rstVect1] = ((uint16_t)pre_main) >> 8;
  982. #if (SAVVEC_ADDRESS != RSTVEC_ADDRESS)
  983. // the save_vector is not necessarilly on the same flash page as the reset
  984. // vector. If it isn't, we've waiting to actually write it.
  985. } else if (address.word == SAVVEC_ADDRESS) {
  986. // Save old values for Verify
  987. saveVect0_sav = buff.bptr[saveVect0 - SAVVEC_ADDRESS];
  988. saveVect1_sav = buff.bptr[saveVect1 - SAVVEC_ADDRESS];
  989. // Move RESET jmp target to 'save' vector
  990. buff.bptr[saveVect0 - SAVVEC_ADDRESS] = rstVect0_sav;
  991. buff.bptr[saveVect1 - SAVVEC_ADDRESS] = rstVect1_sav;
  992. }
  993. #else
  994. // Save old values for Verify
  995. saveVect0_sav = buff.bptr[saveVect0];
  996. saveVect1_sav = buff.bptr[saveVect1];
  997. // Move RESET jmp target to 'save' vector
  998. buff.bptr[saveVect0] = rstVect0_sav;
  999. buff.bptr[saveVect1] = rstVect1_sav;
  1000. }
  1001. #endif
  1002. #else // bigger flash
  1003. #ifdef KeepBracesMatched
  1004. {
  1005. #endif
  1006. /*
  1007. * AVR with 2-byte ISR Vectors and rjmp
  1008. */
  1009. if (address.word == rstVect0) {
  1010. // This is the reset vector page. We need to live-patch
  1011. // the code so the bootloader runs first.
  1012. //
  1013. // Move RESET vector to 'save' vector
  1014. // Save jmp targets (for "Verify")
  1015. rstVect0_sav = buff.bptr[rstVect0];
  1016. rstVect1_sav = buff.bptr[rstVect1];
  1017. addr16_t vect;
  1018. vect.word = ((uint16_t)pre_main-1);
  1019. // Instruction is a relative jump (rjmp), so recalculate.
  1020. // an RJMP instruction is 0b1100xxxx xxxxxxxx, so we should be able to
  1021. // do math on the offsets without masking it off first.
  1022. // Note that rjmp is relative to the already incremented PC, so the
  1023. // offset is one less than you might expect.
  1024. buff.bptr[0] = vect.bytes[0]; // rjmp to start of bootloader
  1025. buff.bptr[1] = vect.bytes[1] | 0xC0; // make an "rjmp"
  1026. #if (SAVVEC_ADDRESS != RSTVEC_ADDRESS)
  1027. } else if (address.word == SAVVEC_ADDRESS) {
  1028. addr16_t vect;
  1029. vect.bytes[0] = rstVect0_sav;
  1030. vect.bytes[1] = rstVect1_sav;
  1031. // Save old values for Verify
  1032. saveVect0_sav = buff.bptr[saveVect0 - SAVVEC_ADDRESS];
  1033. saveVect1_sav = buff.bptr[saveVect1 - SAVVEC_ADDRESS];
  1034. vect.word = (vect.word-save_vect_num); //substract 'save' interrupt position
  1035. // Move RESET jmp target to 'save' vector
  1036. buff.bptr[saveVect0 - SAVVEC_ADDRESS] = vect.bytes[0];
  1037. buff.bptr[saveVect1 - SAVVEC_ADDRESS] = (vect.bytes[1] & 0x0F)| 0xC0; // make an "rjmp"
  1038. }
  1039. #else
  1040. #ifdef KeepBracesMatched
  1041. {
  1042. #endif
  1043. // Save old values for Verify
  1044. saveVect0_sav = buff.bptr[saveVect0];
  1045. saveVect1_sav = buff.bptr[saveVect1];
  1046. vect.bytes[0] = rstVect0_sav;
  1047. vect.bytes[1] = rstVect1_sav;
  1048. vect.word = (vect.word-save_vect_num); //substract 'save' interrupt position
  1049. // Move RESET jmp target to 'save' vector
  1050. buff.bptr[saveVect0] = vect.bytes[0];
  1051. buff.bptr[saveVect1] = (vect.bytes[1] & 0x0F)| 0xC0; // make an "rjmp"
  1052. // Add rjmp to bootloader at RESET vector
  1053. vect.word = ((uint16_t)pre_main-1); // (main) is always <= 0x0FFF; no masking needed.
  1054. buff.bptr[0] = vect.bytes[0]; // rjmp 0x1c00 instruction
  1055. }
  1056. #endif
  1057. #endif // FLASHEND
  1058. #endif // VBP
  1059. writebuffer(desttype, buff, address, savelength);
  1060. }
  1061. /* Read memory block mode, length is big endian. */
  1062. else if (ch == STK_READ_PAGE) {
  1063. uint8_t desttype;
  1064. GETLENGTH(length);
  1065. desttype = getch();
  1066. verifySpace();
  1067. read_mem(desttype, address, length);
  1068. }
  1069. /* Get device signature bytes */
  1070. else if (ch == STK_READ_SIGN) {
  1071. // READ SIGN - return what Avrdude wants to hear
  1072. verifySpace();
  1073. putch(SIGNATURE_0);
  1074. putch(SIGNATURE_1);
  1075. putch(SIGNATURE_2);
  1076. }
  1077. else if (ch == STK_LEAVE_PROGMODE) { /* 'Q' */
  1078. // Adaboot no-wait mod
  1079. watchdogConfig(WATCHDOG_16MS);
  1080. verifySpace();
  1081. }
  1082. else {
  1083. // This covers the response to commands like STK_ENTER_PROGMODE
  1084. verifySpace();
  1085. }
  1086. putch(STK_OK);
  1087. }
  1088. }
  1089. void putch(char ch) {
  1090. #if (SOFT_UART == 0)
  1091. // Hardware UARTs.
  1092. #ifndef LIN_UART
  1093. #ifdef RS485
  1094. uint8_t x;
  1095. do {
  1096. x = UART_SRA;
  1097. } while (!(x & _BV(UDRE0)));
  1098. // clear transmitted flag
  1099. x |= _BV(TXC0);
  1100. UART_SRA = x;
  1101. // put transceiver to output mode
  1102. # ifdef RS485_INVERT
  1103. RS485_PORT &= ~_BV(RS485_BIT);
  1104. # else
  1105. RS485_PORT |= _BV(RS485_BIT);
  1106. # endif
  1107. // put char
  1108. UART_UDR = ch;
  1109. // wait for char transmitted
  1110. while (!(UART_SRA & _BV(TXC0))) { /* Spin */ }
  1111. // put transceiver to input mode
  1112. # ifdef RS485_INVERT
  1113. RS485_PORT |= _BV(RS485_BIT);
  1114. # else
  1115. RS485_PORT &= ~_BV(RS485_BIT);
  1116. # endif
  1117. #else //not RS485
  1118. while (!(UART_SRA & _BV(UDRE0))) { /* Spin */ }
  1119. UART_UDR = ch;
  1120. #endif
  1121. #else //is LIN UART
  1122. while (!(LINSIR & _BV(LTXOK))) { /* Spin */ }
  1123. UART_UDR = ch;
  1124. #endif
  1125. #else // SOFT_UART
  1126. #ifdef RS485
  1127. // put transceiver to output mode
  1128. #ifdef RS485_INVERT
  1129. RS485_PORT &= ~_BV(RS485_BIT);
  1130. #else
  1131. RS485_PORT |= _BV(RS485_BIT);
  1132. #endif
  1133. #endif
  1134. __asm__ __volatile__ (
  1135. " com %[ch]\n" // ones complement, carry set
  1136. " sec\n"
  1137. "1: brcc 2f\n"
  1138. " cbi %[uartPort],%[uartBit]\n"
  1139. " rjmp 3f\n"
  1140. "2: sbi %[uartPort],%[uartBit]\n"
  1141. " nop\n"
  1142. "3: rcall uartDelay\n"
  1143. " rcall uartDelay\n"
  1144. " lsr %[ch]\n"
  1145. " dec %[bitcnt]\n"
  1146. " brne 1b\n"
  1147. :
  1148. :
  1149. [bitcnt] "d" (10),
  1150. [ch] "r" (ch),
  1151. [uartPort] "I" (_SFR_IO_ADDR(UART_PORT)),
  1152. [uartBit] "I" (UART_TX_BIT)
  1153. :
  1154. "r25"
  1155. );
  1156. #ifdef RS485
  1157. // put transceiver to input mode
  1158. #ifdef RS485_INVERT
  1159. RS485_PORT |= _BV(RS485_BIT);
  1160. #else
  1161. RS485_PORT &= ~_BV(RS485_BIT);
  1162. #endif
  1163. #endif
  1164. #endif // SOFT_UART
  1165. }
  1166. static void inline toggle_led(void) {
  1167. #if defined(__AVR_ATmega8__) || defined(__AVR_ATmega8515__) || \
  1168. defined(__AVR_ATmega8535__) || defined(__AVR_ATmega16__) || \
  1169. defined(__AVR_ATmega162__) || defined(__AVR_ATmega32__) || \
  1170. defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__)
  1171. LED_PORT ^= _BV(LED);
  1172. #else
  1173. LED_PIN |= _BV(LED); // Newer AVRs can toggle by writing PINx
  1174. #endif
  1175. }
  1176. uint8_t getch(void) {
  1177. uint8_t ch;
  1178. #if LED_DATA_FLASH
  1179. toggle_led();
  1180. #endif
  1181. #if SOFT_UART
  1182. watchdogReset();
  1183. __asm__ __volatile__ (
  1184. "1: sbic %[uartPin],%[uartBit]\n" // Wait for start edge
  1185. " rjmp 1b\n"
  1186. " rcall uartDelay\n" // Get to middle of start bit
  1187. "2: rcall uartDelay\n" // Wait 1 bit period
  1188. " rcall uartDelay\n" // Wait 1 bit period
  1189. " clc\n"
  1190. " sbic %[uartPin],%[uartBit]\n"
  1191. " sec\n"
  1192. " dec %[bitCnt]\n"
  1193. " breq 3f\n"
  1194. " ror %[ch]\n"
  1195. " rjmp 2b\n"
  1196. "3:\n"
  1197. :
  1198. [ch] "=r" (ch)
  1199. :
  1200. [bitCnt] "d" (9),
  1201. [uartPin] "I" (_SFR_IO_ADDR(UART_PIN)),
  1202. [uartBit] "I" (UART_RX_BIT)
  1203. :
  1204. "r25"
  1205. );
  1206. #else
  1207. #ifndef LIN_UART
  1208. while (!(UART_SRA & _BV(RXC0))) { /* Spin */ }
  1209. if (!(UART_SRA & _BV(FE0))) {
  1210. /*
  1211. * A Framing Error indicates (probably) that something is talking
  1212. * to us at the wrong bit rate. Assume that this is because it
  1213. * expects to be talking to the application, and DON'T reset the
  1214. * watchdog. This should cause the bootloader to abort and run
  1215. * the application "soon", if it keeps happening. (Note that we
  1216. * don't care that an invalid char is returned...)
  1217. */
  1218. watchdogReset();
  1219. }
  1220. #else
  1221. while (!(LINSIR & _BV(LRXOK))) { /* Spin */ }
  1222. if (!(LINSIR & _BV(LFERR))) {
  1223. watchdogReset(); /* Eventually abort if wrong speed */
  1224. }
  1225. #endif
  1226. ch = UART_UDR;
  1227. #endif
  1228. #if LED_DATA_FLASH
  1229. toggle_led();
  1230. #endif
  1231. return ch;
  1232. }
  1233. #if SOFT_UART
  1234. // AVR305 equation: #define UART_B_VALUE (((F_CPU/BAUD_RATE)-23)/6)
  1235. // Adding 3 to numerator simulates nearest rounding for more accurate baud rates
  1236. #define UART_B_VALUE (((F_CPU/BAUD_RATE)-20)/6)
  1237. #if UART_B_VALUE > 255
  1238. #error Baud rate too slow for soft UART
  1239. #endif
  1240. #if UART_B_VALUE < 6
  1241. // (this value is a "guess" at when loop/call overhead might become too
  1242. // significant for the soft uart to work. It tests OK with the popular
  1243. // "ATtinycore" chips that need SOFT_UART, at the usual clock/baud combos.)
  1244. #error Baud rate too high for soft UART
  1245. #endif
  1246. void uartDelay() {
  1247. __asm__ __volatile__ (
  1248. " ldi r25,%[count]\n"
  1249. "1: dec r25\n"
  1250. " brne 1b\n"
  1251. " ret\n"
  1252. ::[count] "M" (UART_B_VALUE)
  1253. );
  1254. }
  1255. #endif
  1256. void getNch(uint8_t count) {
  1257. do getch(); while (--count);
  1258. verifySpace();
  1259. }
  1260. void verifySpace() {
  1261. if (getch() != CRC_EOP) {
  1262. watchdogConfig(WATCHDOG_16MS); // shorten WD timeout
  1263. while (1) // and busy-loop so that WD causes
  1264. ; // a reset and app start.
  1265. }
  1266. putch(STK_INSYNC);
  1267. }
  1268. #if LED_START_FLASHES > 0
  1269. void flash_led(uint8_t count) {
  1270. do {
  1271. #if defined(__AVR_ATtiny261__)||defined(__AVR_ATtiny461__)||defined(__AVR_ATtiny861__) || defined(__AVR_ATtiny25__)||defined(__AVR_ATtiny45__)||defined(__AVR_ATtiny85__)
  1272. TCNT1 = 0xFF & (-(F_CPU/(8196L*16)));
  1273. TIFR = _BV(TOV1);
  1274. while (!(TIFR & _BV(TOV1)));
  1275. #elif defined(__AVR_ATtiny43__)
  1276. #error "LED flash for Tiny43 not yet supported"
  1277. #else
  1278. TCNT1 = -(F_CPU/(1024*16));
  1279. TIFR1 = _BV(TOV1);
  1280. while (!(TIFR1 & _BV(TOV1)));
  1281. #endif
  1282. toggle_led();
  1283. watchdogReset();
  1284. #if (SOFT_UART == 0)
  1285. /*
  1286. * While in theory, the STK500 initial commands would be buffered
  1287. * by the UART hardware, avrdude sends several attempts in rather
  1288. * quick succession, some of which will be lost and cause us to
  1289. * get out of sync. So if we see any data; stop blinking.
  1290. */
  1291. #ifndef LIN_UART
  1292. if (UART_SRA & _BV(RXC0))
  1293. #else
  1294. if (LINSIR & _BV(LRXOK))
  1295. #endif
  1296. break;
  1297. #else
  1298. // This doesn't seem to work?
  1299. // if ((UART_PIN & (1<<UART_RX_BIT)) == 0)
  1300. // break; // detect start bit on soft uart too.
  1301. #endif
  1302. } while (--count);
  1303. }
  1304. #endif
  1305. // Watchdog functions. These are only safe with interrupts turned off.
  1306. void watchdogReset() {
  1307. __asm__ __volatile__ (
  1308. " wdr\n"
  1309. );
  1310. }
  1311. void watchdogConfig(uint8_t x) {
  1312. #ifdef WDCE //does it have a Watchdog Change Enable?
  1313. #ifdef WDTCSR
  1314. WDTCSR = _BV(WDCE) | _BV(WDE);
  1315. #else
  1316. WDTCR= _BV(WDCE) | _BV(WDE);
  1317. #endif
  1318. #else //then it must be one of those newfangled ones that use CCP
  1319. CCP=0xD8; //so write this magic number to CCP
  1320. #endif
  1321. #ifdef WDTCSR
  1322. WDTCSR = x;
  1323. #else
  1324. WDTCR= x;
  1325. #endif
  1326. }
  1327. /*
  1328. * void writebuffer(memtype, buffer, address, length)
  1329. */
  1330. static inline void writebuffer(int8_t memtype, addr16_t mybuff,
  1331. addr16_t address, pagelen_t len)
  1332. {
  1333. switch (memtype) {
  1334. case 'E': // EEPROM
  1335. #if SUPPORT_EEPROM || BIGBOOT
  1336. while (len--) {
  1337. eeprom_write_byte((address.bptr++), *(mybuff.bptr++));
  1338. }
  1339. #else
  1340. /*
  1341. * On systems where EEPROM write is not supported, just busy-loop
  1342. * until the WDT expires, which will eventually cause an error on
  1343. * host system (which is what it should do.)
  1344. */
  1345. while (1)
  1346. ; // Error: wait for WDT
  1347. #endif
  1348. break;
  1349. default: // FLASH
  1350. /*
  1351. * Default to writing to Flash program memory. By making this
  1352. * the default rather than checking for the correct code, we save
  1353. * space on chips that don't support any other memory types.
  1354. */
  1355. {
  1356. // Copy buffer into programming buffer
  1357. uint16_t addrPtr = address.word;
  1358. /*
  1359. * Start the page erase and wait for it to finish. There
  1360. * used to be code to do this while receiving the data over
  1361. * the serial link, but the performance improvement was slight,
  1362. * and we needed the space back.
  1363. */
  1364. #ifdef FOURPAGEERASE
  1365. if ((address.bytes[0] & ((SPM_PAGESIZE<<2)-1))==0) {
  1366. #endif
  1367. __boot_page_erase_short(address.word);
  1368. boot_spm_busy_wait();
  1369. #ifdef FOURPAGEERASE
  1370. }
  1371. #endif
  1372. /*
  1373. * Copy data from the buffer into the flash write buffer.
  1374. */
  1375. do {
  1376. __boot_page_fill_short((uint16_t)(void*)addrPtr, *(mybuff.wptr++));
  1377. addrPtr += 2;
  1378. } while (len -= 2);
  1379. /*
  1380. * Actually Write the buffer to flash (and wait for it to finish.)
  1381. */
  1382. __boot_page_write_short(address.word);
  1383. boot_spm_busy_wait();
  1384. #if defined(RWWSRE)
  1385. // Reenable read access to flash
  1386. __boot_rww_enable_short();
  1387. #endif
  1388. } // default block
  1389. break;
  1390. } // switch
  1391. }
  1392. static inline void read_mem(uint8_t memtype, addr16_t address, pagelen_t length)
  1393. {
  1394. uint8_t ch;
  1395. switch (memtype) {
  1396. #if SUPPORT_EEPROM || BIGBOOT
  1397. case 'E': // EEPROM
  1398. do {
  1399. putch(eeprom_read_byte((address.bptr++)));
  1400. } while (--length);
  1401. break;
  1402. #endif
  1403. default:
  1404. do {
  1405. #ifdef VIRTUAL_BOOT_PARTITION
  1406. // Undo vector patch in bottom page so verify passes
  1407. if (address.word == rstVect0) ch = rstVect0_sav;
  1408. else if (address.word == rstVect1) ch = rstVect1_sav;
  1409. else if (address.word == saveVect0) ch = saveVect0_sav;
  1410. else if (address.word == saveVect1) ch = saveVect1_sav;
  1411. else ch = pgm_read_byte_near(address.bptr);
  1412. address.bptr++;
  1413. #elif defined(RAMPZ)
  1414. // Since RAMPZ should already be set, we need to use EPLM directly.
  1415. // Also, we can use the autoincrement version of lpm to update "address"
  1416. // do putch(pgm_read_byte_near(address++));
  1417. // while (--length);
  1418. // read a Flash and increment the address (may increment RAMPZ)
  1419. __asm__ (" elpm %0,Z+\n" : "=r" (ch), "=z" (address.bptr): "1" (address));
  1420. #else
  1421. // read a Flash byte and increment the address
  1422. __asm__ (" lpm %0,Z+\n" : "=r" (ch), "=z" (address.bptr): "1" (address));
  1423. #endif
  1424. putch(ch);
  1425. } while (--length);
  1426. break;
  1427. } // switch
  1428. }
  1429. #if (APP_NOSPM == 0)
  1430. /*
  1431. * Separate function for doing spm stuff
  1432. * It's needed for application to do SPM, as SPM instruction works only
  1433. * from bootloader.
  1434. *
  1435. * How it works:
  1436. * - do SPM
  1437. * - wait for SPM to complete
  1438. * - if chip have RWW/NRWW sections it does additionaly:
  1439. * - if command is WRITE or ERASE, AND data=0 then reenable RWW section
  1440. *
  1441. * In short:
  1442. * If you play erase-fill-write, just set data to 0 in ERASE and WRITE
  1443. * If you are brave, you have your code just below bootloader in NRWW section
  1444. * you could do fill-erase-write sequence with data!=0 in ERASE and
  1445. * data=0 in WRITE
  1446. */
  1447. static void do_spm(uint16_t address, uint8_t command, uint16_t data) __attribute__ ((used));
  1448. static void do_spm(uint16_t address, uint8_t command, uint16_t data) {
  1449. // Do spm stuff
  1450. asm volatile (
  1451. " movw r0, %3\n"
  1452. " __wr_spmcsr %0, %1\n"
  1453. " spm\n"
  1454. " clr r1\n"
  1455. :
  1456. : "i" (_SFR_MEM_ADDR(__SPM_REG)),
  1457. "r" ((uint8_t)command),
  1458. "z" ((uint16_t)address),
  1459. "r" ((uint16_t)data)
  1460. : "r0"
  1461. );
  1462. // wait for spm to complete
  1463. // it doesn't have much sense for __BOOT_PAGE_FILL,
  1464. // but it doesn't hurt and saves some bytes on 'if'
  1465. boot_spm_busy_wait();
  1466. #if defined(RWWSRE)
  1467. // this 'if' condition should be: (command == __BOOT_PAGE_WRITE || command == __BOOT_PAGE_ERASE)...
  1468. // but it's tweaked a little assuming that in every command we are interested in here, there
  1469. // must be also SELFPRGEN set. If we skip checking this bit, we save here 4B
  1470. if ((command & (_BV(PGWRT)|_BV(PGERS))) && (data == 0) ) {
  1471. // Reenable read access to flash
  1472. __boot_rww_enable_short();
  1473. }
  1474. #endif
  1475. }
  1476. #endif
  1477. #if BIGBOOT
  1478. /*
  1479. * Optiboot is designed to fit in 512 bytes, with a minimum feature set.
  1480. * Some chips have a minimum bootloader size of 1024 bytes, and sometimes
  1481. * it is desirable to add extra features even though 512bytes is exceedded.
  1482. * In that case, the BIGBOOT can be used.
  1483. * Our extra features so far don't come close to filling 1k, so we can
  1484. * add extra "frivolous" data to the image. In particular, we can add
  1485. * information about how Optiboot was built (which options were selected,
  1486. * what version, all in human-readable form (and extractable from the
  1487. * binary with avr-strings.)
  1488. *
  1489. * This can always be removed or trimmed if more actual program space
  1490. * is needed in the future. Currently the data occupies about 160 bytes,
  1491. */
  1492. #define xstr(s) str(s)
  1493. #define str(s) #s
  1494. __attribute__((section(".fini9"))) const char f_delimit = 0xFF;
  1495. #define OPTFLASHSECT __attribute__((section(".fini8")))
  1496. #define OPT2FLASH(o) OPTFLASHSECT const char f##o[] = #o "=" xstr(o)
  1497. #if LED_START_FLASHES
  1498. OPT2FLASH(LED_START_FLASHES);
  1499. #endif
  1500. #if LED_DATA_FLASH
  1501. OPT2FLASH(LED_DATA_FLASH);
  1502. #endif
  1503. #if LED_START_ON
  1504. OPT2FLASH(LED_START_ON);
  1505. #endif
  1506. #ifdef LED_NAME
  1507. OPTFLASHSECT const char f_LED[] = "LED=" LED_NAME;
  1508. #endif
  1509. #if SUPPORT_EEPROM
  1510. OPT2FLASH(SUPPORT_EEPROM);
  1511. #endif
  1512. #if defined(RS485)
  1513. OPTFLASHSECT const char f_rs485[] = "RS485=" RS485_NAME;
  1514. #endif
  1515. #if BAUD_RATE
  1516. OPT2FLASH(BAUD_RATE);
  1517. #endif
  1518. #if SOFT_UART
  1519. OPT2FLASH(SOFT_UART);
  1520. #endif
  1521. #if defined(UART)
  1522. OPT2FLASH(UART);
  1523. #endif
  1524. #if (!defined(NODATE)) || (NODATE == 0)
  1525. // Leave out the date, useful if we want to compare binaries
  1526. OPTFLASHSECT const char f_date[] = "Built:" __DATE__ ":" __TIME__;
  1527. #endif
  1528. #if BIGBOOT
  1529. OPT2FLASH(BIGBOOT);
  1530. #endif
  1531. #ifdef VIRTUAL_BOOT_PARTITION
  1532. OPTFLASHSECT const char f_boot[] = "Virtual_Boot_Partition";
  1533. #endif
  1534. OPT2FLASH(F_CPU);
  1535. OPTFLASHSECT const char f_device[] = "Device=" xstr(__AVR_DEVICE_NAME__);
  1536. #if OPTIBOOT_CUSTOMVER
  1537. OPT2FLASH(OPTIBOOT_CUSTOMVER);
  1538. #endif
  1539. OPTFLASHSECT const char f_version[] = "Version=" xstr(OPTIBOOT_MAJVER) "." xstr(OPTIBOOT_MINVER);
  1540. #endif