isp2.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. /*
  2. * Copyright (C) 2003 by egnite Software GmbH
  3. *
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. *
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. * 3. Neither the name of the copyright holders nor the names of
  16. * contributors may be used to endorse or promote products derived
  17. * from this software without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  22. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  23. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  24. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  25. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  26. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  27. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  28. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  29. * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  30. * SUCH DAMAGE.
  31. *
  32. * For additional information see http://www.ethernut.de/
  33. */
  34. /*!
  35. * $Log$
  36. * Revision 1.1 2003/11/03 15:51:31 haraldkipp
  37. * First check in
  38. *
  39. */
  40. /*
  41. * This application will update the ISP Adapter software.
  42. */
  43. #include <stdio.h>
  44. #include <io.h>
  45. #include <sys/timer.h>
  46. #include <dev/debug.h>
  47. #include <dev/urom.h>
  48. /*
  49. * Port Layout
  50. *
  51. * Coconut
  52. * -------
  53. * PB0(O): SS
  54. * PB1(O): SCK
  55. * PB2(O): MOSI
  56. * PB3(I): MISO
  57. *
  58. * PB4(O): Reset target
  59. * PB5(-): Unused
  60. * PB6(-): Unused
  61. * PB7(-): Unused
  62. *
  63. * ISP at Ethernut 2
  64. * -----------------
  65. * PE0(O): ISP-MOSI
  66. * PE1(I): ISP-MISO
  67. * PB1(O): ISP-SCK
  68. */
  69. #define ISPMOSI_PORT PORTE
  70. #define ISPMOSI_DDR DDRE
  71. #define ISPMOSI_BIT 0
  72. #define ISPMISO_PORT PORTE
  73. #define ISPMISO_DDR DDRE
  74. #define ISPMISO_PIN PINE
  75. #define ISPMISO_BIT 1
  76. #define ISPSCK_PORT PORTB
  77. #define ISPSCK_DDR DDRB
  78. #define ISPSCK_BIT 1
  79. /*!
  80. * \brief Exchange SPI byte.
  81. */
  82. static uint8_t SpiByte(uint8_t c)
  83. {
  84. uint8_t i;
  85. for(i = 0; i < 8; i++) {
  86. if(c & 0x80)
  87. sbi(ISPMOSI_PORT, ISPMOSI_BIT);
  88. else
  89. cbi(ISPMOSI_PORT, ISPMOSI_BIT);
  90. sbi(ISPSCK_PORT, ISPSCK_BIT);
  91. c <<= 1;
  92. if(bit_is_set(ISPMISO_PIN, ISPMISO_BIT))
  93. c++;
  94. cbi(ISPSCK_PORT, ISPSCK_BIT);
  95. }
  96. cbi(ISPMOSI_PORT, ISPMOSI_BIT);
  97. return c;
  98. }
  99. /*!
  100. * \brief Enable SPI device flash programming.
  101. *
  102. * \return 0 if device could be located, -1 otherwise.
  103. */
  104. int SpiFlashEnable(void)
  105. {
  106. uint8_t i;
  107. uint8_t rc;
  108. cbi(ISPMOSI_PORT, ISPMOSI_BIT);
  109. sbi(ISPMOSI_DDR, ISPMOSI_BIT);
  110. cbi(ISPMISO_PORT, ISPMISO_BIT);
  111. cbi(ISPMISO_DDR, ISPMISO_BIT);
  112. cbi(ISPSCK_PORT, ISPSCK_BIT);
  113. sbi(ISPSCK_DDR, ISPSCK_BIT);
  114. for (i = 0; i < 32; i++) {
  115. /*
  116. * Try to enable programming.
  117. */
  118. SpiByte(0xAC);
  119. SpiByte(0x53);
  120. rc = SpiByte(0xFF);
  121. SpiByte(0xff);
  122. if (rc == 0x53)
  123. return 0;
  124. /*
  125. * Programming enable failed. This may be because the
  126. * target is not synchronized. A positive pulse on the
  127. * clock line should help.
  128. */
  129. sbi(ISPSCK_PORT, ISPSCK_BIT);
  130. cbi(ISPSCK_PORT, ISPSCK_BIT);
  131. }
  132. return -1;
  133. }
  134. /*!
  135. * Read SPI device ID.
  136. *
  137. * \param id Three byte character array, which receives
  138. * the CPU ID.
  139. */
  140. void SpiFlashId(uint8_t * id)
  141. {
  142. uint8_t i;
  143. for (i = 0; i < 3; i++) {
  144. SpiByte(0x30);
  145. SpiByte(0x00);
  146. SpiByte(i);
  147. id[i] = SpiByte(0x00);
  148. }
  149. }
  150. /*!
  151. * \brief Write byte to the target's flash memory.
  152. *
  153. * The target must have been erased by a previous call
  154. * to SpiFlashErase().
  155. *
  156. * \param high Must be 0 to write the low byte or 8 to
  157. * write the high byte.
  158. * \param addr Word address to write to.
  159. * \param data Byte value to write.
  160. *
  161. * \return 0 on success, -1 otherwise.
  162. */
  163. int SpiFlashWriteByte(uint8_t high, uint16_t addr, uint8_t data)
  164. {
  165. uint8_t d;
  166. if (data != 0xff) {
  167. SpiByte(0x40 | high);
  168. SpiByte(addr >> 8);
  169. SpiByte(addr & 0xFF);
  170. SpiByte(data);
  171. /*
  172. * During programming a value of 0x7F appears at the memory location.
  173. * If we are programming this value, we delay execution by 10 ms.
  174. * Otherwise we poll the memory location until we read back the
  175. * programmed value.
  176. */
  177. if (data == 0x7f)
  178. NutDelay(10);
  179. else {
  180. for (d = 0; d < 255; d++) {
  181. /*
  182. * Read program flash byte.
  183. */
  184. SpiByte(0x20 | high);
  185. SpiByte(addr >> 8);
  186. SpiByte(addr & 0xFF);
  187. if (SpiByte(0xFF) == data)
  188. break;
  189. }
  190. if (d == 255) {
  191. return -1;
  192. }
  193. }
  194. }
  195. return 0;
  196. }
  197. /*!
  198. * \brief Write word to the target's flash memory.
  199. *
  200. * \param addr Word address to write to.
  201. * \param data Word value to write.
  202. *
  203. * \return 0 on success, -1 otherwise.
  204. */
  205. int SpiFlashWriteWord(uint16_t addr, uint16_t data)
  206. {
  207. if (SpiFlashWriteByte(0, addr, data & 0xFF))
  208. return -1;
  209. if (SpiFlashWriteByte(8, addr, data >> 8))
  210. return -1;
  211. return 0;
  212. }
  213. /*!
  214. * \brief Erase target's flash memory.
  215. *
  216. * Sets all bytes on the target's flash memory to 0xFF.
  217. * In addtion all lock bits are set to 1 (unprogrammed).
  218. */
  219. void SpiFlashErase(void)
  220. {
  221. /*
  222. * Send chip erase command.
  223. */
  224. SpiByte(0xAC);
  225. SpiByte(0x80);
  226. SpiByte(0x00);
  227. SpiByte(0x00);
  228. NutDelay(50);
  229. }
  230. int main(void)
  231. {
  232. uint8_t id[3];
  233. uint32_t baud = 115200;
  234. char *filename = "UROM:sisp.bin";
  235. int val;
  236. uint16_t word;
  237. uint16_t addr;
  238. FILE *fp;
  239. /*
  240. * Register Nut/OS devices. We can't use UART0, because
  241. * it uses the same pins as the ISP port.
  242. */
  243. NutRegisterDevice(&devDebug1, 0, 0);
  244. NutRegisterDevice(&devUrom, 0, 0);
  245. /*
  246. * Open stdout for displaying our progress.
  247. */
  248. freopen("uart1", "w", stdout);
  249. _ioctl(_fileno(stdout), UART_SETSPEED, &baud);
  250. puts("\nISP2 1.0.1");
  251. /*
  252. * Open the file to burn into the adapter's flash memory.
  253. */
  254. fp = fopen(filename, "rb");
  255. if (fp == 0) {
  256. printf("ERROR: Failed to open %s\n", filename);
  257. for(;;);
  258. }
  259. /*
  260. * Try to enter programming mode.
  261. */
  262. printf("Enable programming...");
  263. if(SpiFlashEnable()) {
  264. puts("failed\n"
  265. "Make sure that the ISP adapter is connected to the\n"
  266. "Ethernut ISP port and that the MCU on the adapter\n"
  267. "is held in reset state.");
  268. for(;;);
  269. }
  270. puts("OK");
  271. /*
  272. * Read the target device's signature.
  273. */
  274. printf("Reading signature... ");
  275. SpiFlashId(id);
  276. if(id[0] != 0x1E || id[1] != 0x91 || id[2] != 0x01) {
  277. printf("unexpected %02X%02X%02X\n", id[0], id[1], id[2]);
  278. }
  279. else {
  280. puts("OK");
  281. }
  282. /*
  283. * Erase the target device.
  284. */
  285. printf("Erasing device... ");
  286. SpiFlashErase();
  287. puts("OK");
  288. printf("Programming device");
  289. addr = 0;
  290. for (;;) {
  291. if((addr & 0xFF) == 0)
  292. putchar('.');
  293. if((val = fgetc(fp)) == EOF) {
  294. puts("OK");
  295. break;
  296. }
  297. word = ((uint8_t)fgetc(fp) << 8) + (uint8_t)val;
  298. if (SpiFlashWriteWord(addr, word)) {
  299. printf("failed at %04X\n", addr);
  300. break;
  301. }
  302. addr++;
  303. }
  304. for(;;);
  305. }