A TWI / I2C bootloader for AVR MCUs
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

901 lines
26 KiB

  1. /***************************************************************************
  2. * Copyright (C) 10/2020 by Olaf Rempel *
  3. * razzor@kopf-tisch.de *
  4. * *
  5. * This program is free software; you can redistribute it and/or modify *
  6. * it under the terms of the GNU General Public License as published by *
  7. * the Free Software Foundation; version 2 of the License, *
  8. * *
  9. * This program is distributed in the hope that it will be useful, *
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  12. * GNU General Public License for more details. *
  13. * *
  14. * You should have received a copy of the GNU General Public License *
  15. * along with this program; if not, write to the *
  16. * Free Software Foundation, Inc., *
  17. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
  18. ***************************************************************************/
  19. #include <avr/io.h>
  20. #include <avr/interrupt.h>
  21. #include <avr/boot.h>
  22. #include <avr/pgmspace.h>
  23. #define VERSION_STRING "TWIBOOT v3.1"
  24. #define EEPROM_SUPPORT 1
  25. #define LED_SUPPORT 1
  26. #ifndef USE_CLOCKSTRETCH
  27. #define USE_CLOCKSTRETCH 0
  28. #endif
  29. #ifndef VIRTUAL_BOOT_SECTION
  30. #define VIRTUAL_BOOT_SECTION 0
  31. #endif
  32. #ifndef TWI_ADDRESS
  33. #define TWI_ADDRESS 0x29
  34. #endif
  35. #define F_CPU 8000000ULL
  36. #define TIMER_DIVISOR 1024
  37. #define TIMER_IRQFREQ_MS 25
  38. #define TIMEOUT_MS 1000
  39. #define TIMER_MSEC2TICKS(x) ((x * F_CPU) / (TIMER_DIVISOR * 1000ULL))
  40. #define TIMER_MSEC2IRQCNT(x) (x / TIMER_IRQFREQ_MS)
  41. #if (LED_SUPPORT)
  42. #define LED_INIT() DDRB = ((1<<PORTB4) | (1<<PORTB5))
  43. #define LED_RT_ON() PORTB |= (1<<PORTB4)
  44. #define LED_RT_OFF() PORTB &= ~(1<<PORTB4)
  45. #define LED_GN_ON() PORTB |= (1<<PORTB5)
  46. #define LED_GN_OFF() PORTB &= ~(1<<PORTB5)
  47. #define LED_GN_TOGGLE() PORTB ^= (1<<PORTB5)
  48. #define LED_OFF() PORTB = 0x00
  49. #else
  50. #define LED_INIT()
  51. #define LED_RT_ON()
  52. #define LED_RT_OFF()
  53. #define LED_GN_ON()
  54. #define LED_GN_OFF()
  55. #define LED_GN_TOGGLE()
  56. #define LED_OFF()
  57. #endif /* LED_SUPPORT */
  58. #if !defined(TWCR) && defined(USICR)
  59. #define USI_PIN_INIT() { PORTB |= ((1<<PORTB0) | (1<<PORTB2)); \
  60. DDRB |= (1<<PORTB2); \
  61. }
  62. #define USI_PIN_SDA_INPUT() DDRB &= ~(1<<PORTB0)
  63. #define USI_PIN_SDA_OUTPUT() DDRB |= (1<<PORTB0)
  64. #define USI_PIN_SCL() (PINB & (1<<PINB2))
  65. #if (USE_CLOCKSTRETCH == 0)
  66. #error "USI peripheral requires enabled USE_CLOCKSTRETCH"
  67. #endif
  68. #define USI_STATE_MASK 0x0F
  69. #define USI_STATE_IDLE 0x00 /* wait for Start Condition */
  70. #define USI_STATE_SLA 0x01 /* wait for Slave Address */
  71. #define USI_STATE_SLAW_ACK 0x02 /* ACK Slave Address + Write (Master writes) */
  72. #define USI_STATE_SLAR_ACK 0x03 /* ACK Slave Address + Read (Master reads) */
  73. #define USI_STATE_NAK 0x04 /* send NAK */
  74. #define USI_STATE_DATW 0x05 /* receive Data */
  75. #define USI_STATE_DATW_ACK 0x06 /* transmit ACK for received Data */
  76. #define USI_STATE_DATR 0x07 /* transmit Data */
  77. #define USI_STATE_DATR_ACK 0x08 /* receive ACK for transmitted Data */
  78. #define USI_WAIT_FOR_ACK 0x10 /* wait for ACK bit (2 SCL clock edges) */
  79. #define USI_ENABLE_SDA_OUTPUT 0x20 /* SDA is output (slave transmitting) */
  80. #define USI_ENABLE_SCL_HOLD 0x40 /* Hold SCL low after clock overflow */
  81. #endif /* !defined(TWCR) && defined(USICR) */
  82. #if (VIRTUAL_BOOT_SECTION)
  83. /* unused vector to store application start address */
  84. #define APPVECT_NUM EE_RDY_vect_num
  85. /* each vector table entry is a 2byte RJMP opcode */
  86. #define RSTVECT_ADDR 0x0000
  87. #define APPVECT_ADDR (APPVECT_NUM * 2)
  88. #define RSTVECT_PAGE_OFFSET (RSTVECT_ADDR % SPM_PAGESIZE)
  89. #define APPVECT_PAGE_OFFSET (APPVECT_ADDR % SPM_PAGESIZE)
  90. /* create RJMP opcode for the vector table */
  91. #define OPCODE_RJMP(addr) (((addr) & 0x0FFF) | 0xC000)
  92. #elif (!defined(ASRE) && !defined (RWWSRE))
  93. #error "Device without bootloader section requires VIRTUAL_BOOT_SECTION"
  94. #endif
  95. /* SLA+R */
  96. #define CMD_WAIT 0x00
  97. #define CMD_READ_VERSION 0x01
  98. #define CMD_ACCESS_MEMORY 0x02
  99. /* internal mappings */
  100. #define CMD_ACCESS_CHIPINFO (0x10 | CMD_ACCESS_MEMORY)
  101. #define CMD_ACCESS_FLASH (0x20 | CMD_ACCESS_MEMORY)
  102. #define CMD_ACCESS_EEPROM (0x30 | CMD_ACCESS_MEMORY)
  103. #define CMD_WRITE_FLASH_PAGE (0x40 | CMD_ACCESS_MEMORY)
  104. #define CMD_WRITE_EEPROM_PAGE (0x50 | CMD_ACCESS_MEMORY)
  105. /* SLA+W */
  106. #define CMD_SWITCH_APPLICATION CMD_READ_VERSION
  107. /* internal mappings */
  108. #define CMD_BOOT_BOOTLOADER (0x10 | CMD_SWITCH_APPLICATION) /* only in APP */
  109. #define CMD_BOOT_APPLICATION (0x20 | CMD_SWITCH_APPLICATION)
  110. /* CMD_SWITCH_APPLICATION parameter */
  111. #define BOOTTYPE_BOOTLOADER 0x00 /* only in APP */
  112. #define BOOTTYPE_APPLICATION 0x80
  113. /* CMD_{READ|WRITE}_* parameter */
  114. #define MEMTYPE_CHIPINFO 0x00
  115. #define MEMTYPE_FLASH 0x01
  116. #define MEMTYPE_EEPROM 0x02
  117. /*
  118. * LED_GN flashes with 20Hz (while bootloader is running)
  119. * LED_RT flashes on TWI activity
  120. *
  121. * bootloader twi-protocol:
  122. * - abort boot timeout:
  123. * SLA+W, 0x00, STO
  124. *
  125. * - show bootloader version
  126. * SLA+W, 0x01, SLA+R, {16 bytes}, STO
  127. *
  128. * - start application
  129. * SLA+W, 0x01, 0x80, STO
  130. *
  131. * - read chip info: 3byte signature, 1byte page size, 2byte flash size, 2byte eeprom size
  132. * SLA+W, 0x02, 0x00, 0x00, 0x00, SLA+R, {8 bytes}, STO
  133. *
  134. * - read one (or more) flash bytes
  135. * SLA+W, 0x02, 0x01, addrh, addrl, SLA+R, {* bytes}, STO
  136. *
  137. * - read one (or more) eeprom bytes
  138. * SLA+W, 0x02, 0x02, addrh, addrl, SLA+R, {* bytes}, STO
  139. *
  140. * - write one flash page
  141. * SLA+W, 0x02, 0x01, addrh, addrl, {* bytes}, STO
  142. *
  143. * - write one (or more) eeprom bytes
  144. * SLA+W, 0x02, 0x02, addrh, addrl, {* bytes}, STO
  145. */
  146. const static uint8_t info[16] = VERSION_STRING;
  147. const static uint8_t chipinfo[8] = {
  148. SIGNATURE_0, SIGNATURE_1, SIGNATURE_2,
  149. SPM_PAGESIZE,
  150. (BOOTLOADER_START >> 8) & 0xFF,
  151. BOOTLOADER_START & 0xFF,
  152. #if (EEPROM_SUPPORT)
  153. ((E2END +1) >> 8 & 0xFF),
  154. (E2END +1) & 0xFF
  155. #else
  156. 0x00, 0x00
  157. #endif
  158. };
  159. static uint8_t boot_timeout = TIMER_MSEC2IRQCNT(TIMEOUT_MS);
  160. static uint8_t cmd = CMD_WAIT;
  161. /* flash buffer */
  162. static uint8_t buf[SPM_PAGESIZE];
  163. static uint16_t addr;
  164. #if (VIRTUAL_BOOT_SECTION)
  165. /* reset/application vectors received from host, needed for verify read */
  166. static uint8_t rstvect_save[2];
  167. static uint8_t appvect_save[2];
  168. #endif /* (VIRTUAL_BOOT_SECTION) */
  169. /* *************************************************************************
  170. * write_flash_page
  171. * ************************************************************************* */
  172. static void write_flash_page(void)
  173. {
  174. uint16_t pagestart = addr;
  175. uint8_t size = SPM_PAGESIZE;
  176. uint8_t *p = buf;
  177. #if (VIRTUAL_BOOT_SECTION)
  178. if (pagestart == (RSTVECT_ADDR & ~(SPM_PAGESIZE -1)))
  179. {
  180. /* save original vectors for verify read */
  181. rstvect_save[0] = buf[RSTVECT_PAGE_OFFSET];
  182. rstvect_save[1] = buf[RSTVECT_PAGE_OFFSET + 1];
  183. appvect_save[0] = buf[APPVECT_PAGE_OFFSET];
  184. appvect_save[1] = buf[APPVECT_PAGE_OFFSET + 1];
  185. /* replace reset vector with jump to bootloader address */
  186. uint16_t rst_vector = OPCODE_RJMP(BOOTLOADER_START -1);
  187. buf[RSTVECT_PAGE_OFFSET] = (rst_vector & 0xFF);
  188. buf[RSTVECT_PAGE_OFFSET + 1] = (rst_vector >> 8) & 0xFF;
  189. /* replace application vector with jump to original reset vector */
  190. uint16_t app_vector = rstvect_save[0] | (rstvect_save[1] << 8);
  191. app_vector = OPCODE_RJMP(app_vector - APPVECT_NUM);
  192. buf[APPVECT_PAGE_OFFSET] = (app_vector & 0xFF);
  193. buf[APPVECT_PAGE_OFFSET + 1] = (app_vector >> 8) & 0xFF;
  194. }
  195. #endif /* (VIRTUAL_BOOT_SECTION) */
  196. if (pagestart < BOOTLOADER_START)
  197. {
  198. boot_page_erase(pagestart);
  199. boot_spm_busy_wait();
  200. do {
  201. uint16_t data = *p++;
  202. data |= *p++ << 8;
  203. boot_page_fill(addr, data);
  204. addr += 2;
  205. size -= 2;
  206. } while (size);
  207. boot_page_write(pagestart);
  208. boot_spm_busy_wait();
  209. #if defined (ASRE) || defined (RWWSRE)
  210. /* only required for bootloader section */
  211. boot_rww_enable();
  212. #endif
  213. }
  214. } /* write_flash_page */
  215. #if (EEPROM_SUPPORT)
  216. /* *************************************************************************
  217. * read_eeprom_byte
  218. * ************************************************************************* */
  219. static uint8_t read_eeprom_byte(uint16_t address)
  220. {
  221. EEARL = address;
  222. EEARH = (address >> 8);
  223. EECR |= (1<<EERE);
  224. return EEDR;
  225. } /* read_eeprom_byte */
  226. /* *************************************************************************
  227. * write_eeprom_byte
  228. * ************************************************************************* */
  229. static void write_eeprom_byte(uint8_t val)
  230. {
  231. EEARL = addr;
  232. EEARH = (addr >> 8);
  233. EEDR = val;
  234. addr++;
  235. #if defined (EEWE)
  236. EECR |= (1<<EEMWE);
  237. EECR |= (1<<EEWE);
  238. #elif defined (EEPE)
  239. EECR |= (1<<EEMPE);
  240. EECR |= (1<<EEPE);
  241. #else
  242. #error "EEWE/EEPE not defined"
  243. #endif
  244. eeprom_busy_wait();
  245. } /* write_eeprom_byte */
  246. #if (USE_CLOCKSTRETCH == 0)
  247. /* *************************************************************************
  248. * write_eeprom_buffer
  249. * ************************************************************************* */
  250. static void write_eeprom_buffer(uint8_t size)
  251. {
  252. uint8_t *p = buf;
  253. while (size--)
  254. {
  255. write_eeprom_byte(*p++);
  256. }
  257. } /* write_eeprom_buffer */
  258. #endif /* (USE_CLOCKSTRETCH == 0) */
  259. #endif /* EEPROM_SUPPORT */
  260. /* *************************************************************************
  261. * TWI_data_write
  262. * ************************************************************************* */
  263. static uint8_t TWI_data_write(uint8_t bcnt, uint8_t data)
  264. {
  265. uint8_t ack = 0x01;
  266. switch (bcnt)
  267. {
  268. case 0:
  269. switch (data)
  270. {
  271. case CMD_SWITCH_APPLICATION:
  272. case CMD_ACCESS_MEMORY:
  273. /* no break */
  274. case CMD_WAIT:
  275. /* abort countdown */
  276. boot_timeout = 0;
  277. cmd = data;
  278. break;
  279. default:
  280. /* boot app now */
  281. cmd = CMD_BOOT_APPLICATION;
  282. ack = 0x00;
  283. break;
  284. }
  285. break;
  286. case 1:
  287. switch (cmd)
  288. {
  289. case CMD_SWITCH_APPLICATION:
  290. if (data == BOOTTYPE_APPLICATION)
  291. {
  292. cmd = CMD_BOOT_APPLICATION;
  293. }
  294. ack = 0x00;
  295. break;
  296. case CMD_ACCESS_MEMORY:
  297. if (data == MEMTYPE_CHIPINFO)
  298. {
  299. cmd = CMD_ACCESS_CHIPINFO;
  300. }
  301. else if (data == MEMTYPE_FLASH)
  302. {
  303. cmd = CMD_ACCESS_FLASH;
  304. }
  305. #if (EEPROM_SUPPORT)
  306. else if (data == MEMTYPE_EEPROM)
  307. {
  308. cmd = CMD_ACCESS_EEPROM;
  309. }
  310. #endif /* (EEPROM_SUPPORT) */
  311. else
  312. {
  313. ack = 0x00;
  314. }
  315. break;
  316. default:
  317. ack = 0x00;
  318. break;
  319. }
  320. break;
  321. case 2:
  322. case 3:
  323. addr <<= 8;
  324. addr |= data;
  325. break;
  326. default:
  327. switch (cmd)
  328. {
  329. #if (EEPROM_SUPPORT)
  330. #if (USE_CLOCKSTRETCH)
  331. case CMD_ACCESS_EEPROM:
  332. write_eeprom_byte(data);
  333. break;
  334. #else
  335. case CMD_ACCESS_EEPROM:
  336. cmd = CMD_WRITE_EEPROM_PAGE;
  337. /* fall through */
  338. case CMD_WRITE_EEPROM_PAGE:
  339. #endif /* (USE_CLOCKSTRETCH) */
  340. #endif /* (EEPROM_SUPPORT) */
  341. case CMD_ACCESS_FLASH:
  342. {
  343. uint8_t pos = bcnt -4;
  344. buf[pos] = data;
  345. if (pos >= (sizeof(buf) -2))
  346. {
  347. ack = 0x00;
  348. }
  349. if ((cmd == CMD_ACCESS_FLASH) &&
  350. (pos >= (sizeof(buf) -1))
  351. )
  352. {
  353. #if (USE_CLOCKSTRETCH)
  354. write_flash_page();
  355. #else
  356. cmd = CMD_WRITE_FLASH_PAGE;
  357. #endif
  358. }
  359. break;
  360. }
  361. default:
  362. ack = 0x00;
  363. break;
  364. }
  365. break;
  366. }
  367. return ack;
  368. } /* TWI_data_write */
  369. /* *************************************************************************
  370. * TWI_data_read
  371. * ************************************************************************* */
  372. static uint8_t TWI_data_read(uint8_t bcnt)
  373. {
  374. uint8_t data;
  375. switch (cmd)
  376. {
  377. case CMD_READ_VERSION:
  378. bcnt %= sizeof(info);
  379. data = info[bcnt];
  380. break;
  381. case CMD_ACCESS_CHIPINFO:
  382. bcnt %= sizeof(chipinfo);
  383. data = chipinfo[bcnt];
  384. break;
  385. case CMD_ACCESS_FLASH:
  386. switch (addr)
  387. {
  388. /* return cached values for verify read */
  389. #if (VIRTUAL_BOOT_SECTION)
  390. case RSTVECT_ADDR:
  391. data = rstvect_save[0];
  392. break;
  393. case (RSTVECT_ADDR + 1):
  394. data = rstvect_save[1];
  395. break;
  396. case APPVECT_ADDR:
  397. data = appvect_save[0];
  398. break;
  399. case (APPVECT_ADDR + 1):
  400. data = appvect_save[1];
  401. break;
  402. #endif /* (VIRTUAL_BOOT_SECTION) */
  403. default:
  404. data = pgm_read_byte_near(addr);
  405. break;
  406. }
  407. addr++;
  408. break;
  409. #if (EEPROM_SUPPORT)
  410. case CMD_ACCESS_EEPROM:
  411. data = read_eeprom_byte(addr++);
  412. break;
  413. #endif /* (EEPROM_SUPPORT) */
  414. default:
  415. data = 0xFF;
  416. break;
  417. }
  418. return data;
  419. } /* TWI_data_read */
  420. #if defined (TWCR)
  421. /* *************************************************************************
  422. * TWI_vect
  423. * ************************************************************************* */
  424. static void TWI_vect(void)
  425. {
  426. static uint8_t bcnt;
  427. uint8_t control = TWCR;
  428. switch (TWSR & 0xF8)
  429. {
  430. /* SLA+W received, ACK returned -> receive data and ACK */
  431. case 0x60:
  432. bcnt = 0;
  433. LED_RT_ON();
  434. break;
  435. /* prev. SLA+W, data received, ACK returned -> receive data and ACK */
  436. case 0x80:
  437. if (TWI_data_write(bcnt++, TWDR) == 0x00)
  438. {
  439. /* the ACK returned by TWI_data_write() is not for the current
  440. * data in TWDR, but for the next byte received
  441. */
  442. control &= ~(1<<TWEA);
  443. }
  444. break;
  445. /* SLA+R received, ACK returned -> send data */
  446. case 0xA8:
  447. bcnt = 0;
  448. LED_RT_ON();
  449. /* fall through */
  450. /* prev. SLA+R, data sent, ACK returned -> send data */
  451. case 0xB8:
  452. TWDR = TWI_data_read(bcnt++);
  453. break;
  454. /* prev. SLA+W, data received, NACK returned -> IDLE */
  455. case 0x88:
  456. TWI_data_write(bcnt++, TWDR);
  457. /* fall through */
  458. /* STOP or repeated START -> IDLE */
  459. case 0xA0:
  460. #if (USE_CLOCKSTRETCH == 0)
  461. if ((cmd == CMD_WRITE_FLASH_PAGE)
  462. #if (EEPROM_SUPPORT)
  463. || (cmd == CMD_WRITE_EEPROM_PAGE)
  464. #endif
  465. )
  466. {
  467. /* disable ACK for now, re-enable after page write */
  468. control &= ~(1<<TWEA);
  469. TWCR = (1<<TWINT) | control;
  470. #if (EEPROM_SUPPORT)
  471. if (cmd == CMD_WRITE_EEPROM_PAGE)
  472. {
  473. write_eeprom_buffer(bcnt -4);
  474. }
  475. else
  476. #endif /* (EEPROM_SUPPORT) */
  477. {
  478. write_flash_page();
  479. }
  480. }
  481. #endif /* (USE_CLOCKSTRETCH) */
  482. bcnt = 0;
  483. /* fall through */
  484. /* prev. SLA+R, data sent, NACK returned -> IDLE */
  485. case 0xC0:
  486. LED_RT_OFF();
  487. control |= (1<<TWEA);
  488. break;
  489. /* illegal state(s) -> reset hardware */
  490. default:
  491. control |= (1<<TWSTO);
  492. break;
  493. }
  494. TWCR = (1<<TWINT) | control;
  495. } /* TWI_vect */
  496. #endif /* defined (TWCR) */
  497. #if defined (USICR)
  498. /* *************************************************************************
  499. * usi_statemachine
  500. * ************************************************************************* */
  501. static void usi_statemachine(uint8_t usisr)
  502. {
  503. static uint8_t usi_state;
  504. static uint8_t bcnt;
  505. uint8_t data = USIDR;
  506. uint8_t state = usi_state & USI_STATE_MASK;
  507. /* Start Condition detected */
  508. if (usisr & (1<<USISIF))
  509. {
  510. /* wait until SCL goes low */
  511. while (USI_PIN_SCL());
  512. usi_state = USI_STATE_SLA | USI_ENABLE_SCL_HOLD;
  513. state = USI_STATE_IDLE;
  514. }
  515. /* Stop Condition detected */
  516. if (usisr & (1<<USIPF))
  517. {
  518. LED_RT_OFF();
  519. usi_state = USI_STATE_IDLE;
  520. state = USI_STATE_IDLE;
  521. }
  522. if (state == USI_STATE_IDLE)
  523. {
  524. /* do nothing */
  525. }
  526. /* Slave Address received => prepare ACK/NAK */
  527. else if (state == USI_STATE_SLA)
  528. {
  529. bcnt = 0;
  530. /* SLA+W received -> send ACK */
  531. if (data == ((TWI_ADDRESS<<1) | 0x00))
  532. {
  533. LED_RT_ON();
  534. usi_state = USI_STATE_SLAW_ACK | USI_WAIT_FOR_ACK | USI_ENABLE_SDA_OUTPUT | USI_ENABLE_SCL_HOLD;
  535. USIDR = 0x00;
  536. }
  537. /* SLA+R received -> send ACK */
  538. else if (data == ((TWI_ADDRESS<<1) | 0x01))
  539. {
  540. LED_RT_ON();
  541. usi_state = USI_STATE_SLAR_ACK | USI_WAIT_FOR_ACK | USI_ENABLE_SDA_OUTPUT | USI_ENABLE_SCL_HOLD;
  542. USIDR = 0x00;
  543. }
  544. /* not addressed -> send NAK */
  545. else
  546. {
  547. usi_state = USI_STATE_NAK | USI_WAIT_FOR_ACK | USI_ENABLE_SDA_OUTPUT | USI_ENABLE_SCL_HOLD;
  548. USIDR = 0x80;
  549. }
  550. }
  551. /* sent NAK -> go to idle */
  552. else if (state == USI_STATE_NAK)
  553. {
  554. usi_state = USI_STATE_IDLE;
  555. }
  556. /* sent ACK after SLA+W -> wait for data */
  557. /* sent ACK after DAT+W -> wait for more data */
  558. else if ((state == USI_STATE_SLAW_ACK) ||
  559. (state == USI_STATE_DATW_ACK)
  560. )
  561. {
  562. usi_state = USI_STATE_DATW | USI_ENABLE_SCL_HOLD;
  563. }
  564. /* data received -> send ACK/NAK */
  565. else if (state == USI_STATE_DATW)
  566. {
  567. if (TWI_data_write(bcnt++, data))
  568. {
  569. usi_state = USI_STATE_DATW_ACK | USI_WAIT_FOR_ACK | USI_ENABLE_SDA_OUTPUT | USI_ENABLE_SCL_HOLD;
  570. USIDR = 0x00;
  571. }
  572. else
  573. {
  574. usi_state = USI_STATE_NAK | USI_WAIT_FOR_ACK | USI_ENABLE_SDA_OUTPUT | USI_ENABLE_SCL_HOLD;
  575. USIDR = 0x80;
  576. }
  577. }
  578. /* sent ACK after SLA+R -> send data */
  579. /* received ACK after DAT+R -> send more data */
  580. else if ((state == USI_STATE_SLAR_ACK) ||
  581. ((state == USI_STATE_DATR_ACK) && !(data & 0x01))
  582. )
  583. {
  584. USIDR = TWI_data_read(bcnt++);
  585. usi_state = USI_STATE_DATR | USI_ENABLE_SDA_OUTPUT | USI_ENABLE_SCL_HOLD;
  586. }
  587. /* sent data after SLA+R -> receive ACK/NAK */
  588. else if (state == USI_STATE_DATR)
  589. {
  590. usi_state = USI_STATE_DATR_ACK | USI_WAIT_FOR_ACK | USI_ENABLE_SCL_HOLD;
  591. USIDR = 0x80;
  592. }
  593. /* received NAK after DAT+R -> go to idle */
  594. else if ((state == USI_STATE_DATR_ACK) && (data & 0x01))
  595. {
  596. usi_state = USI_STATE_IDLE;
  597. }
  598. /* default -> go to idle */
  599. else
  600. {
  601. usi_state = USI_STATE_IDLE;
  602. }
  603. /* set SDA direction according to current state */
  604. if (usi_state & USI_ENABLE_SDA_OUTPUT)
  605. {
  606. USI_PIN_SDA_OUTPUT();
  607. }
  608. else
  609. {
  610. USI_PIN_SDA_INPUT();
  611. }
  612. if (usi_state & USI_ENABLE_SCL_HOLD)
  613. {
  614. /* Enable TWI Mode, hold SCL low after counter overflow, count both SCL edges */
  615. USICR = (1<<USIWM1) | (1<<USIWM0) | (1<<USICS1);
  616. }
  617. else
  618. {
  619. /* Enable TWI, hold SCL low only after start condition, count both SCL edges */
  620. USICR = (1<<USIWM1) | (1<<USICS1);
  621. }
  622. /* clear start/overflow/stop condition flags */
  623. usisr &= ((1<<USISIF) | (1<<USIOIF) | (1<<USIPF));
  624. if (usi_state & USI_WAIT_FOR_ACK)
  625. {
  626. /* count 2 SCL edges (ACK/NAK bit) */
  627. USISR = usisr | ((16 -2)<<USICNT0);
  628. }
  629. else
  630. {
  631. /* count 16 SCL edges (8bit data) */
  632. USISR = usisr | ((16 -16)<<USICNT0);
  633. }
  634. } /* usi_statemachine */
  635. #endif /* defined (USICR) */
  636. /* *************************************************************************
  637. * TIMER0_OVF_vect
  638. * ************************************************************************* */
  639. static void TIMER0_OVF_vect(void)
  640. {
  641. /* restart timer */
  642. TCNT0 = 0xFF - TIMER_MSEC2TICKS(TIMER_IRQFREQ_MS);
  643. /* blink LED while running */
  644. LED_GN_TOGGLE();
  645. /* count down for app-boot */
  646. if (boot_timeout > 1)
  647. {
  648. boot_timeout--;
  649. }
  650. else if (boot_timeout == 1)
  651. {
  652. /* trigger app-boot */
  653. cmd = CMD_BOOT_APPLICATION;
  654. }
  655. } /* TIMER0_OVF_vect */
  656. #if (VIRTUAL_BOOT_SECTION)
  657. static void (*jump_to_app)(void) __attribute__ ((noreturn)) = (void*)APPVECT_ADDR;
  658. #else
  659. static void (*jump_to_app)(void) __attribute__ ((noreturn)) = (void*)0x0000;
  660. #endif
  661. /* *************************************************************************
  662. * init1
  663. * ************************************************************************* */
  664. void init1(void) __attribute__((naked, section(".init1")));
  665. void init1(void)
  666. {
  667. /* make sure r1 is 0x00 */
  668. asm volatile ("clr __zero_reg__");
  669. /* on some MCUs the stack pointer defaults NOT to RAMEND */
  670. #if defined(__AVR_ATmega8__) || defined(__AVR_ATmega8515__) || \
  671. defined(__AVR_ATmega8535__) || defined (__AVR_ATmega16__) || \
  672. defined (__AVR_ATmega32__) || defined (__AVR_ATmega64__) || \
  673. defined (__AVR_ATmega128__) || defined (__AVR_ATmega162__)
  674. SP = RAMEND;
  675. #endif
  676. } /* init1 */
  677. /*
  678. * For newer devices the watchdog timer remains active even after a
  679. * system reset. So disable it as soon as possible.
  680. * automagically called on startup
  681. */
  682. #if defined (__AVR_ATmega88__) || defined (__AVR_ATmega168__) || \
  683. defined (__AVR_ATmega328P__)
  684. /* *************************************************************************
  685. * disable_wdt_timer
  686. * ************************************************************************* */
  687. void disable_wdt_timer(void) __attribute__((naked, section(".init3")));
  688. void disable_wdt_timer(void)
  689. {
  690. MCUSR = 0;
  691. WDTCSR = (1<<WDCE) | (1<<WDE);
  692. WDTCSR = (0<<WDE);
  693. } /* disable_wdt_timer */
  694. #endif
  695. /* *************************************************************************
  696. * main
  697. * ************************************************************************* */
  698. int main(void) __attribute__ ((OS_main, section (".init9")));
  699. int main(void)
  700. {
  701. LED_INIT();
  702. LED_GN_ON();
  703. #if (VIRTUAL_BOOT_SECTION)
  704. /* load current values (for reading flash) */
  705. rstvect_save[0] = pgm_read_byte_near(RSTVECT_ADDR);
  706. rstvect_save[1] = pgm_read_byte_near(RSTVECT_ADDR + 1);
  707. appvect_save[0] = pgm_read_byte_near(APPVECT_ADDR);
  708. appvect_save[1] = pgm_read_byte_near(APPVECT_ADDR + 1);
  709. #endif /* (VIRTUAL_BOOT_SECTION) */
  710. /* timer0: running with F_CPU/1024 */
  711. #if defined (TCCR0)
  712. TCCR0 = (1<<CS02) | (1<<CS00);
  713. #elif defined (TCCR0B)
  714. TCCR0B = (1<<CS02) | (1<<CS00);
  715. #else
  716. #error "TCCR0(B) not defined"
  717. #endif
  718. #if defined (TWCR)
  719. /* TWI init: set address, auto ACKs */
  720. TWAR = (TWI_ADDRESS<<1);
  721. TWCR = (1<<TWEA) | (1<<TWEN);
  722. #elif defined (USICR)
  723. USI_PIN_INIT();
  724. usi_statemachine(0x00);
  725. #else
  726. #error "No TWI/USI peripheral found"
  727. #endif
  728. while (cmd != CMD_BOOT_APPLICATION)
  729. {
  730. #if defined (TWCR)
  731. if (TWCR & (1<<TWINT))
  732. {
  733. TWI_vect();
  734. }
  735. #elif defined (USICR)
  736. if (USISR & ((1<<USISIF) | (1<<USIOIF) | (1<<USIPF)))
  737. {
  738. usi_statemachine(USISR);
  739. }
  740. #endif
  741. #if defined (TIFR)
  742. if (TIFR & (1<<TOV0))
  743. {
  744. TIMER0_OVF_vect();
  745. TIFR = (1<<TOV0);
  746. }
  747. #elif defined (TIFR0)
  748. if (TIFR0 & (1<<TOV0))
  749. {
  750. TIMER0_OVF_vect();
  751. TIFR0 = (1<<TOV0);
  752. }
  753. #else
  754. #error "TIFR(0) not defined"
  755. #endif
  756. }
  757. #if defined (TWCR)
  758. /* Disable TWI but keep address! */
  759. TWCR = 0x00;
  760. #elif defined (USICR)
  761. /* Disable USI peripheral */
  762. USICR = 0x00;
  763. #endif
  764. /* disable timer0 */
  765. #if defined (TCCR0)
  766. TCCR0 = 0x00;
  767. #elif defined (TCCR0B)
  768. TCCR0B = 0x00;
  769. #else
  770. #error "TCCR0(B) not defined"
  771. #endif
  772. LED_OFF();
  773. #if (LED_SUPPORT)
  774. uint16_t wait = 0x0000;
  775. do {
  776. __asm volatile ("nop");
  777. } while (--wait);
  778. #endif /* (LED_SUPPORT) */
  779. jump_to_app();
  780. } /* main */