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.
 
 

456 lines
12 KiB

  1. /***************************************************************************
  2. * Copyright (C) 11/2014 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. #include <string.h>
  24. #include "target.h"
  25. #include "rfm12.h"
  26. /* *********************************************************************** */
  27. #define BOOTWAIT_EXPIRED 0x0000
  28. #define BOOTWAIT_INTERRUPTED 0xFFFF
  29. #define MSG_TYPE_REQUEST 0x00 /* master -> slave req */
  30. #define MSG_TYPE_CONFIRMATION 0x40 /* master -> slave rsp */
  31. #define MSG_TYPE_INDICATION 0x80 /* slave -> master req */
  32. #define MSG_TYPE_RESPONSE 0xC0 /* slave -> master rsp */
  33. #define MSG_TYPE_MASK 0xC0
  34. #define MSG_CMD_MASK 0x3F
  35. #define MSG_CMD_SWITCHAPP_REQUEST (MSG_TYPE_REQUEST | 0x20)
  36. #define MSG_CMD_SWITCHAPP_RESPONSE (MSG_TYPE_RESPONSE | 0x20)
  37. #define MSG_CMD_VERSION_REQUEST (MSG_TYPE_REQUEST | 0x21)
  38. #define MSG_CMD_VERSION_RESPONSE (MSG_TYPE_RESPONSE | 0x21)
  39. #define MSG_CMD_CHIPINFO_REQUEST (MSG_TYPE_REQUEST | 0x22)
  40. #define MSG_CMD_CHIPINFO_RESPONSE (MSG_TYPE_RESPONSE | 0x22)
  41. #define MSG_CMD_READ_REQUEST (MSG_TYPE_REQUEST | 0x23)
  42. #define MSG_CMD_READ_RESPONSE (MSG_TYPE_RESPONSE | 0x23)
  43. #define MSG_CMD_WRITE_REQUEST (MSG_TYPE_REQUEST | 0x24)
  44. #define MSG_CMD_WRITE_RESPONSE (MSG_TYPE_RESPONSE | 0x24)
  45. #define CAUSE_SUCCESS 0x00
  46. #define CAUSE_NOT_SUPPORTED 0xF0
  47. #define CAUSE_INVALID_PARAMETER 0xF1
  48. #define CAUSE_UNSPECIFIED_ERROR 0xFF
  49. #define BOOTMODE_BOOTLOADER 0x00
  50. #define BOOTMODE_APPLICATION 0x80
  51. #define MEMTYPE_FLASH 0x01
  52. #define MEMTYPE_EEPROM 0x02
  53. /* *********************************************************************** */
  54. struct bootloader_msg
  55. {
  56. uint8_t command;
  57. uint8_t seqnum;
  58. uint8_t cause;
  59. union {
  60. struct {
  61. uint8_t app;
  62. } switchapp;
  63. struct {
  64. uint8_t data[16];
  65. } version;
  66. struct {
  67. uint8_t data[8];
  68. } chipinfo;
  69. struct {
  70. uint16_t address;
  71. uint8_t mem_type;
  72. uint8_t size;
  73. } read_req;
  74. struct {
  75. uint8_t data[32];
  76. } read_rsp;
  77. struct {
  78. uint16_t address;
  79. uint8_t mem_type;
  80. uint8_t size;
  81. uint8_t data[32];
  82. } write_req;
  83. } p;
  84. };
  85. /* *********************************************************************** */
  86. #define LED_RX 0
  87. #define LED_TX 1
  88. static uint8_t led_timer[2];
  89. volatile static uint8_t clock_tick;
  90. const static uint8_t version_info[16] = VERSION_STRING;
  91. const static uint8_t chip_info[8] = {
  92. SIGNATURE_BYTES,
  93. SPM_PAGESIZE,
  94. ((BOOTLOADER_START) >> 8) & 0xFF,
  95. (BOOTLOADER_START) & 0xFF,
  96. ((E2END +1) >> 8 & 0xFF),
  97. (E2END +1) & 0xFF
  98. };
  99. /* *********************************************************************** */
  100. static void read_flash(uint8_t *data, uint16_t address, uint8_t size)
  101. {
  102. while (size--)
  103. {
  104. *data++ = pgm_read_byte_near(address++);
  105. }
  106. } /* read_flash_byte */
  107. static void write_flash(uint8_t *data, uint16_t address, uint8_t size)
  108. {
  109. static uint16_t pagestart;
  110. static uint8_t pagesize;
  111. if ((address & (SPM_PAGESIZE -1)) == 0x00)
  112. {
  113. pagestart = address;
  114. pagesize = SPM_PAGESIZE;
  115. boot_page_erase(pagestart);
  116. boot_spm_busy_wait();
  117. }
  118. while (size && pagesize)
  119. {
  120. uint16_t dataword;
  121. dataword = (*data++);
  122. dataword |= (*data++) << 8;
  123. boot_page_fill(address, dataword);
  124. address += 2;
  125. pagesize -= 2;
  126. size -= 2;
  127. }
  128. if (pagesize == 0)
  129. {
  130. boot_page_write(pagestart);
  131. boot_spm_busy_wait();
  132. boot_rww_enable();
  133. }
  134. } /* write_flash */
  135. static void read_eeprom(uint8_t *data, uint16_t address, uint8_t size)
  136. {
  137. while (size--)
  138. {
  139. EEARL = address;
  140. EEARH = (address >> 8);
  141. EECR |= (1<<EERE);
  142. address++;
  143. *data++ = EEDR;
  144. }
  145. } /* read_eeprom */
  146. static void write_eeprom(uint8_t *data, uint16_t address, uint8_t size)
  147. {
  148. while (size--)
  149. {
  150. EEARL = address;
  151. EEARH = (address >> 8);
  152. EEDR = *data++;
  153. address++;
  154. cli();
  155. #if defined (__AVR_ATmega168__)
  156. EECR |= (1<<EEMPE);
  157. EECR |= (1<<EEPE);
  158. #endif
  159. sei();
  160. eeprom_busy_wait();
  161. }
  162. } /* write_eeprom */
  163. ISR(TIMER0_OVF_vect)
  164. {
  165. TCNT0 = TIMER_RELOAD;
  166. clock_tick = 1;
  167. } /* TIMER0_OVF_vect */
  168. static void (*jump_to_app)(void) __attribute__ ((noreturn)) = 0x0000;
  169. #if defined(__AVR_ATmega168__)
  170. /*
  171. * For newer devices the watchdog timer remains active even after a
  172. * system reset. So disable it as soon as possible.
  173. * automagically called on startup
  174. */
  175. void disable_wdt_timer(void) __attribute__((naked, section(".init3")));
  176. void disable_wdt_timer(void)
  177. {
  178. MCUSR = 0;
  179. WDTCSR = (1<<WDCE) | (1<<WDE);
  180. WDTCSR = (0<<WDE);
  181. } /* disable_wdt_timer */
  182. #endif
  183. int main(void) __attribute__ ((noreturn));
  184. int main(void)
  185. {
  186. /* init LEDs */
  187. LED_INIT();
  188. #if defined (__AVR_ATmega168__)
  189. /* move interrupt-vectors to bootloader */
  190. MCUCR = (1<<IVCE);
  191. MCUCR = (1<<IVSEL);
  192. /* timer0, FCPU/64, overflow interrupt */
  193. TCCR0B = (1<<CS01) | (1<<CS00);
  194. TIMSK0 = (1<<TOIE0);
  195. #endif
  196. rfm12_init(RFM12_ADDRESS);
  197. sei();
  198. uint16_t boot_timeout = TIMEOUT;
  199. while (1)
  200. {
  201. if (clock_tick == 0)
  202. continue;
  203. clock_tick = 0;
  204. if (led_timer[LED_RX] > 0)
  205. {
  206. led_timer[LED_RX]--;
  207. LED_GN_ON();
  208. }
  209. else
  210. {
  211. LED_GN_OFF();
  212. }
  213. if (led_timer[LED_TX] > 0)
  214. {
  215. led_timer[LED_TX]--;
  216. LED_RT_ON();
  217. }
  218. else
  219. {
  220. LED_RT_OFF();
  221. }
  222. /* do periodic work (wait for 5 ticks silence before start TX) */
  223. rfm12_tick(5);
  224. /* get TX buffer */
  225. struct rfm12_packet *rsp_pkt = rfm12_get_txpkt();
  226. if (boot_timeout == BOOTWAIT_EXPIRED)
  227. {
  228. /* timeout elapsed and TX buffer available (tx completed) -> start application */
  229. if (rsp_pkt != NULL)
  230. {
  231. break;
  232. }
  233. }
  234. else if (boot_timeout != BOOTWAIT_INTERRUPTED)
  235. {
  236. boot_timeout--;
  237. }
  238. if ((boot_timeout & 0x3F) == 0)
  239. {
  240. led_timer[LED_TX] = 5;
  241. }
  242. /* get RX data */
  243. struct rfm12_packet *req_pkt = rfm12_get_rxpkt();
  244. if (req_pkt == NULL)
  245. {
  246. /* no data available */
  247. continue;
  248. }
  249. else
  250. {
  251. led_timer[LED_RX] = 5;
  252. /* no tx buffer available, ignore request */
  253. if (rsp_pkt == NULL)
  254. {
  255. rfm12_clear_rx();
  256. continue;
  257. }
  258. }
  259. /* stay in bootloader */
  260. boot_timeout = BOOTWAIT_INTERRUPTED;
  261. struct bootloader_msg *req_msg = (struct bootloader_msg *)req_pkt->data;
  262. struct bootloader_msg *rsp_msg = (struct bootloader_msg *)rsp_pkt->data;
  263. /* retransmitted request -> retransmit response */
  264. if ((req_pkt->source_address == rsp_pkt->dest_address) &&
  265. ((req_msg->command & MSG_CMD_MASK) == (rsp_msg->command & MSG_CMD_MASK)) &&
  266. (req_msg->seqnum == rsp_msg->seqnum)
  267. )
  268. {
  269. /* RX packet no longer needed */
  270. rfm12_clear_rx();
  271. /* transmit response */
  272. if (rfm12_start_tx())
  273. {
  274. led_timer[LED_TX] = 5;
  275. }
  276. continue;
  277. }
  278. rsp_pkt->dest_address = req_pkt->source_address;
  279. rsp_pkt->data_length = 3;
  280. rsp_msg->command = req_msg->command | MSG_TYPE_RESPONSE;
  281. rsp_msg->seqnum = req_msg->seqnum;
  282. rsp_msg->cause = CAUSE_SUCCESS;
  283. switch (req_msg->command)
  284. {
  285. case MSG_CMD_SWITCHAPP_REQUEST:
  286. if (req_msg->p.switchapp.app == BOOTMODE_APPLICATION)
  287. {
  288. boot_timeout = BOOTWAIT_EXPIRED;
  289. }
  290. else if (req_msg->p.switchapp.app != BOOTMODE_BOOTLOADER)
  291. {
  292. rsp_msg->cause = CAUSE_INVALID_PARAMETER;
  293. }
  294. break;
  295. case MSG_CMD_VERSION_REQUEST:
  296. memcpy(rsp_msg->p.version.data, version_info, sizeof(rsp_msg->p.version.data));
  297. rsp_pkt->data_length += sizeof(rsp_msg->p.version.data);
  298. break;
  299. case MSG_CMD_CHIPINFO_REQUEST:
  300. memcpy(rsp_msg->p.chipinfo.data, chip_info, sizeof(rsp_msg->p.chipinfo.data));
  301. rsp_pkt->data_length += sizeof(rsp_msg->p.chipinfo.data);
  302. break;
  303. case MSG_CMD_READ_REQUEST:
  304. if (req_msg->p.read_req.mem_type == MEMTYPE_FLASH)
  305. {
  306. read_flash(rsp_msg->p.read_rsp.data,
  307. req_msg->p.read_req.address,
  308. req_msg->p.read_req.size);
  309. rsp_pkt->data_length += req_msg->p.read_req.size;
  310. }
  311. else if (req_msg->p.read_req.mem_type == MEMTYPE_EEPROM)
  312. {
  313. read_eeprom(rsp_msg->p.read_rsp.data,
  314. req_msg->p.read_req.address,
  315. req_msg->p.read_req.size);
  316. rsp_pkt->data_length += req_msg->p.read_req.size;
  317. }
  318. else
  319. {
  320. rsp_msg->cause = CAUSE_INVALID_PARAMETER;
  321. }
  322. break;
  323. case MSG_CMD_WRITE_REQUEST:
  324. if (req_msg->p.write_req.mem_type == MEMTYPE_FLASH)
  325. {
  326. write_flash(req_msg->p.write_req.data,
  327. req_msg->p.write_req.address,
  328. req_msg->p.write_req.size);
  329. }
  330. else if (req_msg->p.write_req.mem_type == MEMTYPE_EEPROM)
  331. {
  332. write_eeprom(req_msg->p.write_req.data,
  333. req_msg->p.write_req.address,
  334. req_msg->p.write_req.size);
  335. }
  336. else
  337. {
  338. rsp_msg->cause = CAUSE_INVALID_PARAMETER;
  339. }
  340. break;
  341. default:
  342. rsp_msg->cause = CAUSE_NOT_SUPPORTED;
  343. break;
  344. }
  345. /* RX packet no longer needed */
  346. rfm12_clear_rx();
  347. /* transmit response */
  348. if (rfm12_start_tx())
  349. {
  350. led_timer[LED_TX] = 5;
  351. }
  352. }
  353. cli();
  354. #if defined (__AVR_ATmega168__)
  355. /* disable timer0 */
  356. TIMSK0 = 0x00;
  357. TCCR0B = 0x00;
  358. /* move interrupt vectors back to application */
  359. MCUCR = (1<<IVCE);
  360. MCUCR = (0<<IVSEL);
  361. #endif
  362. LED_OFF();
  363. jump_to_app();
  364. } /* main */