avrtarget.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492
  1. /*!
  2. * Copyright (C) 2007 by egnite Software GmbH. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. Neither the name of the copyright holders nor the names of
  14. * contributors may be used to endorse or promote products derived
  15. * from this software without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  18. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  19. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  20. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  21. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  22. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  23. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  24. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  25. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  26. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  27. * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  28. * SUCH DAMAGE.
  29. *
  30. * For additional information see http://www.ethernut.de/
  31. */
  32. /*!
  33. * \file avrtarget.c
  34. * \brief External AVR device programming.
  35. *
  36. * \verbatim
  37. *
  38. * $Log$
  39. * Revision 1.3 2009/01/17 11:26:46 haraldkipp
  40. * Getting rid of two remaining BSD types in favor of stdint.
  41. * Replaced 'u_int' by 'unsinged int' and 'uptr_t' by 'uintptr_t'.
  42. *
  43. * Revision 1.2 2008/08/11 06:59:41 haraldkipp
  44. * BSD types replaced by stdint types (feature request #1282721).
  45. *
  46. * Revision 1.1 2007/04/12 09:01:38 haraldkipp
  47. * New API allows to program external AVR devices.
  48. *
  49. *
  50. * \endverbatim
  51. */
  52. #include <sys/timer.h>
  53. #include <dev/avrtarget.h>
  54. /*!
  55. * \addtogroup xgAvrTarget
  56. */
  57. /*@{*/
  58. #ifndef AVRTARGET_CHIPERASE_TIMEOUT
  59. /*!
  60. * \brief Maximum time (in milliseconds) to wait for chip erase done.
  61. */
  62. #define AVRTARGET_CHIPERASE_TIMEOUT 200
  63. #endif
  64. #ifndef AVRTARGET_PAGEWRITE_TIMEOUT
  65. /*!
  66. * \brief Maximum time (in milliseconds) to wait for page write done.
  67. */
  68. #define AVRTARGET_PAGEWRITE_TIMEOUT 10
  69. #endif
  70. /*!
  71. * \brief Safe fuse programming mask.
  72. *
  73. * If a bit is set in this mask, the corresponding fuse should
  74. * never be programmed to 0.
  75. *
  76. * Used in AvrTargetFusesWriteSafe() to avoid dead chips. However,
  77. * it is still possible to break hardware. Triple check any new
  78. * fuse configuration.
  79. *
  80. * This unsigned long value is interpreted as follows:
  81. *
  82. * - Least significant byte is fuse low byte.
  83. * - Second byte is fuse high byte.
  84. * - Third byte is fuse extended byte.
  85. * - Most significant byte is not used.
  86. */
  87. #define AVR_FUSES_NEVER_PROG 0x00F88062UL
  88. /*!
  89. * \brief Safe fuse unprogramming mask.
  90. *
  91. * If a bit is set in this mask, the corresponding fuse should
  92. * never be left unprogrammed (set to 1).
  93. *
  94. * Used in AvrTargetFusesWriteSafe() to avoid dead chips. However,
  95. * it is still possible to break hardware. Triple check any new
  96. * fuse configuration.
  97. *
  98. * This unsigned long value is interpreted as follows:
  99. *
  100. * - Least significant byte is fuse low byte.
  101. * - Second byte is fuse high byte.
  102. * - Third byte is fuse extended byte.
  103. * - Most significant byte is not used.
  104. */
  105. #define AVR_FUSES_ALWAYS_PROG 0x0000201DUL
  106. #ifndef AVRTARGET_SPI_MODE
  107. #define AVRTARGET_SPI_MODE 0
  108. #endif
  109. #ifndef AVRTARGET_SPI_RATE
  110. #define AVRTARGET_SPI_RATE 500000
  111. #endif
  112. #if defined(AVRTARGET_SPI0_DEVICE) /* SPI device. */
  113. #include <dev/sppif0.h>
  114. #if defined(AVRTARGET_SELECT_ACTIVE_HIGH)
  115. #define TargetReset(act) Sppi0ChipReset(AVRTARGET_SPI0_DEVICE, act)
  116. #else
  117. #define TargetReset(act) Sppi0ChipReset(AVRTARGET_SPI0_DEVICE, !act)
  118. #endif
  119. #define SpiSetMode() Sppi0SetMode(AVRTARGET_SPI0_DEVICE, AVRTARGET_SPI_MODE)
  120. #define SpiSetSpeed() Sppi0SetSpeed(AVRTARGET_SPI0_DEVICE, AVRTARGET_SPI_RATE)
  121. #if defined(AVRTARGET_SELECT_ACTIVE_HIGH)
  122. #define SpiSelect() Sppi0SelectDevice(AVRTARGET_SPI0_DEVICE)
  123. #define SpiDeselect() Sppi0DeselectDevice(AVRTARGET_SPI0_DEVICE)
  124. #else
  125. #define SpiSelect() Sppi0NegSelectDevice(AVRTARGET_SPI0_DEVICE)
  126. #define SpiDeselect() Sppi0NegDeselectDevice(AVRTARGET_SPI0_DEVICE)
  127. #endif
  128. #define SpiByte Sppi0Byte
  129. #elif defined(AVRTARGET_SBBI0_DEVICE) /* SPI device. */
  130. #include <dev/sbbif0.h>
  131. #if defined(AVRTARGET_SELECT_ACTIVE_HIGH)
  132. #define TargetReset(act) Sbbi0ChipReset(AVRTARGET_SBBI0_DEVICE, act)
  133. #else
  134. #define TargetReset(act) Sbbi0ChipReset(AVRTARGET_SBBI0_DEVICE, !act)
  135. #endif
  136. #define SpiSetMode() Sbbi0SetMode(AVRTARGET_SBBI0_DEVICE, AVRTARGET_SPI_MODE)
  137. #define SpiSetSpeed() Sbbi0SetSpeed(AVRTARGET_SBBI0_DEVICE, AVRTARGET_SPI_RATE)
  138. #if defined(AVRTARGET_SELECT_ACTIVE_HIGH)
  139. #define SpiSelect() Sbbi0SelectDevice(AVRTARGET_SBBI0_DEVICE)
  140. #define SpiDeselect() Sbbi0DeselectDevice(AVRTARGET_SBBI0_DEVICE)
  141. #else
  142. #define SpiSelect() Sbbi0NegSelectDevice(AVRTARGET_SBBI0_DEVICE)
  143. #define SpiDeselect() Sbbi0NegDeselectDevice(AVRTARGET_SBBI0_DEVICE)
  144. #endif
  145. #define SpiByte Sbbi0Byte
  146. #elif defined(AVRTARGET_SBBI1_DEVICE) /* SPI device. */
  147. #include <dev/sbbif1.h>
  148. #if defined(AVRTARGET_SELECT_ACTIVE_HIGH)
  149. #define TargetReset(act) Sbbi1ChipReset(AVRTARGET_SBBI1_DEVICE, act)
  150. #else
  151. #define TargetReset(act) Sbbi1ChipReset(AVRTARGET_SBBI1_DEVICE, !act)
  152. #endif
  153. #define SpiSetMode() Sbbi1SetMode(AVRTARGET_SBBI1_DEVICE, AVRTARGET_SPI_MODE)
  154. #define SpiSetSpeed() Sbbi1SetSpeed(AVRTARGET_SBBI1_DEVICE, AVRTARGET_SPI_RATE)
  155. #if defined(AVRTARGET_SELECT_ACTIVE_HIGH)
  156. #define SpiSelect() Sbbi1SelectDevice(AVRTARGET_SBBI1_DEVICE)
  157. #define SpiDeselect() Sbbi1DeselectDevice(AVRTARGET_SBBI1_DEVICE)
  158. #else
  159. #define SpiSelect() Sbbi1NegSelectDevice(AVRTARGET_SBBI1_DEVICE)
  160. #define SpiDeselect() Sbbi1NegDeselectDevice(AVRTARGET_SBBI1_DEVICE)
  161. #endif
  162. #define SpiByte Sbbi1Byte
  163. #elif defined(AVRTARGET_SBBI2_DEVICE) /* SPI device. */
  164. #include <dev/sbbif2.h>
  165. #if defined(AVRTARGET_SELECT_ACTIVE_HIGH)
  166. #define TargetReset(act) Sbbi2ChipReset(AVRTARGET_SBBI2_DEVICE, act)
  167. #else
  168. #define TargetReset(act) Sbbi2ChipReset(AVRTARGET_SBBI2_DEVICE, !act)
  169. #endif
  170. #define SpiSetMode() Sbbi2SetMode(AVRTARGET_SBBI2_DEVICE, AVRTARGET_SPI_MODE)
  171. #define SpiSetSpeed() Sbbi2SetSpeed(AVRTARGET_SBBI2_DEVICE, AVRTARGET_SPI_RATE)
  172. #if defined(AVRTARGET_SELECT_ACTIVE_HIGH)
  173. #define SpiSelect() Sbbi2SelectDevice(AVRTARGET_SBBI2_DEVICE)
  174. #define SpiDeselect() Sbbi2DeselectDevice(AVRTARGET_SBBI2_DEVICE)
  175. #else
  176. #define SpiSelect() Sbbi2NegSelectDevice(AVRTARGET_SBBI2_DEVICE)
  177. #define SpiDeselect() Sbbi2NegDeselectDevice(AVRTARGET_SBBI2_DEVICE)
  178. #endif
  179. #define SpiByte Sbbi2Byte
  180. #elif defined(AVRTARGET_SBBI3_DEVICE) /* SPI device. */
  181. #include <dev/sbbif3.h>
  182. #if defined(AVRTARGET_SELECT_ACTIVE_HIGH)
  183. #define TargetReset(act) Sbbi3ChipReset(AVRTARGET_SBBI3_DEVICE, act)
  184. #else
  185. #define TargetReset(act) Sbbi3ChipReset(AVRTARGET_SBBI3_DEVICE, !act)
  186. #endif
  187. #define SpiSetMode() Sbbi3SetMode(AVRTARGET_SBBI3_DEVICE, AVRTARGET_SPI_MODE)
  188. #define SpiSetSpeed() Sbbi3SetSpeed(AVRTARGET_SBBI3_DEVICE, AVRTARGET_SPI_RATE)
  189. #if defined(AVRTARGET_SELECT_ACTIVE_HIGH)
  190. #define SpiSelect() Sbbi3SelectDevice(AVRTARGET_SBBI3_DEVICE)
  191. #define SpiDeselect() Sbbi3DeselectDevice(AVRTARGET_SBBI3_DEVICE)
  192. #else
  193. #define SpiSelect() Sbbi3NegSelectDevice(AVRTARGET_SBBI3_DEVICE)
  194. #define SpiDeselect() Sbbi3NegDeselectDevice(AVRTARGET_SBBI3_DEVICE)
  195. #endif
  196. #define SpiByte Sbbi3Byte
  197. #else /* SPI device. */
  198. #define AVRTARGET_NO_SPI_DEVICE
  199. #endif /* SPI device. */
  200. /*!
  201. * \brief Initialize programming interface.
  202. *
  203. * Sets the configured SPI mode and rate. This must be called before
  204. * using any other routine in this module.
  205. *
  206. * \return 0 on success, -1 otherwise.
  207. */
  208. int AvrTargetInit(void)
  209. {
  210. #if defined(AVRTARGET_NO_SPI_DEVICE)
  211. return -1;
  212. #else
  213. if (SpiSetMode()) {
  214. return -1;
  215. }
  216. SpiSetSpeed();
  217. SpiDeselect();
  218. return 0;
  219. #endif
  220. }
  221. /*!
  222. * \brief Set or clear the chip select line.
  223. *
  224. * Must be called before sending programming commands to the target device,
  225. * even if no chip selects are implemented by the hardware. Beside activating
  226. * an optional chip select, this routine will also properly initialize the
  227. * SPI hardware.
  228. *
  229. * \param act When 0, the chip will be deactivated and the serial peripheral
  230. * interface may be used to communicate with another device.
  231. * When not 0, the SPI bus is allocated for the attached AVR target.
  232. */
  233. void AvrTargetSelect(ureg_t act)
  234. {
  235. #if !defined(AVRTARGET_NO_SPI_DEVICE)
  236. if (act) {
  237. SpiSelect();
  238. } else {
  239. SpiDeselect();
  240. }
  241. #endif
  242. }
  243. /*!
  244. * \brief Set or release the target's reset line.
  245. *
  246. * The target must be held in reset state during programming.
  247. *
  248. * \param on When not 0, the reset line will be activated.
  249. */
  250. void AvrTargetReset(ureg_t act)
  251. {
  252. #if !defined(AVRTARGET_NO_SPI_DEVICE)
  253. TargetReset(act);
  254. #endif
  255. }
  256. /*!
  257. * \brief Send programming command and return response.
  258. *
  259. * \param cmd 4-byte command.
  260. *
  261. * \return 4-byte response.
  262. */
  263. uint32_t AvrTargetCmd(uint32_t cmd)
  264. {
  265. uint32_t rc = 0;
  266. #if !defined(AVRTARGET_NO_SPI_DEVICE)
  267. ureg_t i;
  268. for (i = 0; i < 4; i++) {
  269. rc <<= 8;
  270. rc |= SpiByte((uint8_t) (cmd >> 24));
  271. cmd <<= 8;
  272. }
  273. #endif
  274. return rc;
  275. }
  276. /*!
  277. * \brief Enable target's programming mode.
  278. *
  279. * \return 0 on success, -1 otherwise.
  280. */
  281. int AvrTargetProgEnable(void)
  282. {
  283. #if defined(AVRTARGET_NO_SPI_DEVICE)
  284. return -1;
  285. #else
  286. if ((uint8_t) (AvrTargetCmd(AVRCMD_PROG_ENABLE) >> 8) != 0x53) {
  287. return -1;
  288. }
  289. return 0;
  290. #endif
  291. }
  292. /*!
  293. * \brief Retrieve the target's signature.
  294. *
  295. * \return Signature in the 3 least significant bytes.
  296. */
  297. uint32_t AvrTargetSignature(void)
  298. {
  299. uint32_t rc = 0;
  300. #if !defined(AVRTARGET_NO_SPI_DEVICE)
  301. ureg_t i;
  302. for (i = 0; i < 3; i++) {
  303. rc <<= 8;
  304. rc |= (uint8_t) AvrTargetCmd(AVRCMD_READ_SIGNATURE_BYTE | ((uint32_t) i << 8));
  305. }
  306. #endif
  307. return rc;
  308. }
  309. /*!
  310. * \brief Retrieve the target's fuses.
  311. *
  312. * \return Fuse bits in the 3 least significant bytes.
  313. */
  314. uint32_t AvrTargetFusesRead(void)
  315. {
  316. uint32_t rc = 0;
  317. rc = (uint8_t) AvrTargetCmd(AVRCMD_READ_FUSE_EXT_BITS);
  318. rc <<= 8;
  319. rc |= (uint8_t) AvrTargetCmd(AVRCMD_READ_FUSE_HI_BITS);
  320. rc <<= 8;
  321. rc |= (uint8_t) AvrTargetCmd(AVRCMD_READ_FUSE_BITS);
  322. return rc;
  323. }
  324. /*!
  325. * \brief Program the target's fuses in a safe way.
  326. *
  327. * Fuses with corresponding bits set in \ref AVR_FUSES_NEVER_PROG will
  328. * never be programmed. Fuses with corresponding bits set in
  329. * \ref AVR_FUSES_ALWAYS_PROG will always be programmed.
  330. *
  331. * \param fuses Fuse bits are expected in the 3 least significant bytes,
  332. * Lower fuses in the LSB, followed by the high fuses and
  333. * last no least the extended fuses.
  334. */
  335. uint32_t AvrTargetFusesWriteSafe(uint32_t fuses)
  336. {
  337. uint32_t rc;
  338. fuses |= AVR_FUSES_NEVER_PROG;
  339. fuses &= ~AVR_FUSES_ALWAYS_PROG;
  340. rc = fuses;
  341. AvrTargetCmd(AVRCMD_WRITE_FUSE_BITS | (uint8_t)fuses);
  342. fuses >>= 8;
  343. AvrTargetCmd(AVRCMD_WRITE_FUSE_HI_BITS | (uint8_t)fuses);
  344. fuses >>= 8;
  345. AvrTargetCmd(AVRCMD_WRITE_FUSE_EXT_BITS | (uint8_t)fuses);
  346. fuses >>= 8;
  347. return rc;
  348. }
  349. /*!
  350. * \brief Poll target for becoming ready.
  351. *
  352. * May switch to another thread while waiting. After switching back to
  353. * the calling thread, the SPI is re-selected.
  354. *
  355. * \param tmo Maximum number of milliseconds to wait.
  356. *
  357. * \return 0 on success, -1 on time out.
  358. */
  359. int AvrTargetPollReady(unsigned int tmo)
  360. {
  361. #if !defined(AVRTARGET_NO_SPI_DEVICE)
  362. while (AvrTargetCmd(AVRCMD_POLL_READY) & 1UL) {
  363. if (tmo-- == 0) {
  364. return -1;
  365. }
  366. NutSleep(1);
  367. /* We may have lost the SPI. */
  368. SpiSelect();
  369. }
  370. #endif
  371. return 0;
  372. }
  373. /*!
  374. * \brief Erase the target chip.
  375. *
  376. * Be aware, that this routine calls AvrTargetPollReady(), which may
  377. * initiate a context switch while waiting for the erase to finish.
  378. *
  379. * \return 0 on success, -1 on time out.
  380. */
  381. int AvrTargetChipErase(void)
  382. {
  383. AvrTargetCmd(AVRCMD_CHIP_ERASE);
  384. return AvrTargetPollReady(AVRTARGET_CHIPERASE_TIMEOUT);
  385. }
  386. /*!
  387. * \brief Load target's program memory page buffer.
  388. *
  389. * \param page Program memory page number.
  390. * \param data Points to the data.
  391. *
  392. */
  393. void AvrTargetPageLoad(uint32_t page, const uint8_t * data)
  394. {
  395. ureg_t bc;
  396. page <<= 6;
  397. for (bc = 0; bc < (AVRTARGET_PAGESIZE / 2); bc++) {
  398. AvrTargetCmd(AVRCMD_LOAD_PROG_MEM_PAGE_LO | (page << 8) | *data);
  399. data++;
  400. AvrTargetCmd(AVRCMD_LOAD_PROG_MEM_PAGE_HI | (page << 8) | *data);
  401. data++;
  402. page++;
  403. }
  404. }
  405. /*!
  406. * \brief Write page buffer contents to program memory.
  407. *
  408. * Calls AvrTargetPollReady(), which may initiate a context switch
  409. * while waiting for the page write to finish.
  410. *
  411. * \param page Program memory page number.
  412. *
  413. * \return 0 on success, -1 on time out.
  414. */
  415. int AvrTargetPageWrite(uint32_t page)
  416. {
  417. AvrTargetCmd(AVRCMD_WRITE_PROG_MEM_PAGE | (page << 14));
  418. return AvrTargetPollReady(AVRTARGET_PAGEWRITE_TIMEOUT);
  419. }
  420. /*!
  421. * \brief Verify program memory page contents.
  422. *
  423. * \param page Program memory page number.
  424. * \param data Points to a buffer with the expected contents.
  425. *
  426. * \return 0 if the buffer contents equals the memory page contents or
  427. * -1 if it doesn't.
  428. */
  429. int AvrTargetPageVerify(uint32_t page, const uint8_t * data)
  430. {
  431. uint32_t waddr = page << 6;
  432. ureg_t bc;
  433. for (bc = 0; bc < (AVRTARGET_PAGESIZE / 2); bc++) {
  434. if ((uint8_t) AvrTargetCmd(AVRCMD_READ_PROG_MEM_LO | (waddr << 8)) != *data++) {
  435. return -1;
  436. }
  437. if ((uint8_t) AvrTargetCmd(AVRCMD_READ_PROG_MEM_HI | (waddr << 8)) != *data++) {
  438. return -1;
  439. }
  440. waddr++;
  441. }
  442. return 0;
  443. }
  444. /*@}*/