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.
 
 

537 lines
16 KiB

  1. /***************************************************************************
  2. * Copyright (C) 02/2017 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. #define F_CPU 8000000
  21. #include <util/delay.h>
  22. /*
  23. * attiny2313
  24. * lfuse: 0xe4 (int rc osc, max startup time)
  25. * hfuse: 0xdf (no BOD)
  26. * efuse: 0xff (no self programming)
  27. *
  28. * PA0 -> HC590 /MRC (Counter Reset)
  29. * PB0:7 <-> D0:7
  30. * PD0 <- RXD
  31. * PD1 -> TXD
  32. * PD2 -> HC590 CPC (Counter Clock)
  33. * PD3 -> HC590 CPR (Register Clock)
  34. * PD4 -> EEPROM /CS
  35. * PD5 -> EEPROM /WR
  36. * PD6 -> EEPROM /OE
  37. */
  38. #define nCNTRES PORTA0
  39. #define RXD PORTD0
  40. #define TXD PORTD1
  41. #define CNTCLK PORTD2
  42. #define REGCLK PORTD3
  43. #define nCHIPSELECT PORTD4
  44. #define nWRITE PORTD5
  45. #define nREAD PORTD6
  46. #define BAUDRATE 115200
  47. #define UART_CALC_BAUDRATE(baudRate) (((uint32_t)F_CPU) / (((uint32_t)baudRate)*16) -1)
  48. #define NOP asm volatile ("nop")
  49. /* ************************************************************************* */
  50. #define MSGTYPE_VERSION_REQ 0x01 /* no payload */
  51. #define MSGTYPE_PAGESIZE_REQ 0x02 /* no payload */
  52. #define MSGTYPE_CONFIG_REQ 0x03 /* eprom_type(1), pagesize(1), reset_polarity(1) */
  53. #define MSGTYPE_PROGMODE_REQ 0x04 /* progmode(1) */
  54. #define MSGTYPE_SETADDRESS_REQ 0x05 /* address(3) msb first */
  55. #define MSGTYPE_WRITE_REQ 0x06 /* data(0-pagesize) */
  56. #define MSGTYPE_READ_REQ 0x07 /* length(1) */
  57. #define MSGTYPE_ERROR_RSP 0x80 /* error_code(1) */
  58. #define MSGTYPE_VERSION_RSP 0x81 /* version(?) */
  59. #define MSGTYPE_PAGESIZE_RSP 0x82 /* pagesize(1) */
  60. #define MSGTYPE_CONFIG_RSP 0x83 /* no payload */
  61. #define MSGTYPE_PROGMODE_RSP 0x84 /* no payload */
  62. #define MSGTYPE_SETADDRESS_RSP 0x85 /* no payload */
  63. #define MSGTYPE_WRITE_RSP 0x86 /* no payload */
  64. #define MSGTYPE_READ_RSP 0x87 /* data(0-pagesize) */
  65. #define SUCCESS 0x00
  66. #define ERROR_UNKNOWN_COMMAND 0x01 /* unknown message type */
  67. #define ERROR_NOT_SUPPORTED 0x02 /* command not supported */
  68. #define ERROR_INVALID_MODE 0x03 /* invalid progmode */
  69. #define ERROR_INVALID_PARAMETER 0x04 /* invalid parameter in request */
  70. #define ERROR_INVALID_ADDRESS 0x05 /* write outside of configured region */
  71. #define RESET_POLARITY_LOW 0x00 /* low active reset */
  72. #define RESET_POLARITY_HIGH 0x01 /* high active reset */
  73. #define EPROM_TYPE_2K 0x02 /* 2716 */
  74. #define EPROM_TYPE_4K 0x04 /* 2732 */
  75. #define EPROM_TYPE_8K 0x08 /* 2764 */
  76. #define EPROM_TYPE_16K 0x10 /* 27128 */
  77. #define EPROM_TYPE_32K 0x20 /* 27256 */
  78. #define EPROM_TYPE_64K 0x40 /* 27512 */
  79. #define EPROM_TYPE_128K 0x80 /* 27010 */
  80. #define PROGMODE_DISABLED 0x00 /* target running, no write access to RAM */
  81. #define PROGMODE_ENABLED 0x01 /* target reset, write access to RAM */
  82. #define PAGESIZE_MAX 64
  83. /* ************************************************************************* */
  84. struct _globdata {
  85. uint32_t address_max;
  86. uint32_t address;
  87. uint8_t progmode;
  88. uint8_t pagesize;
  89. };
  90. static const uint8_t version_str[] = "e2prog v1.00";
  91. static struct _globdata gdata = { 0 };
  92. /* *************************************************************************
  93. * send one byte to UART
  94. * ************************************************************************* */
  95. static void ser_send(uint8_t data)
  96. {
  97. loop_until_bit_is_set(UCSRA, UDRIE);
  98. UDR = data;
  99. } /* ser_send */
  100. /* *************************************************************************
  101. * receive one byte from UART
  102. * ************************************************************************* */
  103. static uint8_t ser_recv(void)
  104. {
  105. loop_until_bit_is_set(UCSRA, RXC);
  106. return UDR;
  107. } /* ser_recv */
  108. /* *************************************************************************
  109. *
  110. * ************************************************************************* */
  111. static void address_clear(void)
  112. {
  113. /* reset address counter */
  114. PORTA &= ~(1<<nCNTRES);
  115. NOP;
  116. PORTA |= (1<<nCNTRES);
  117. /* clock address into register */
  118. PORTD |= (1<<REGCLK);
  119. NOP;
  120. PORTD &= ~(1<<REGCLK);
  121. gdata.address = 0;
  122. } /* address_clear */
  123. /* *************************************************************************
  124. * set address counter to value
  125. * ************************************************************************* */
  126. static void address_set(uint16_t address)
  127. {
  128. uint16_t count;
  129. /* address already higher then target */
  130. if (gdata.address > address)
  131. {
  132. /* reset address counter */
  133. PORTA &= ~(1<<nCNTRES);
  134. NOP;
  135. PORTA |= (1<<nCNTRES);
  136. count = address;
  137. }
  138. else
  139. {
  140. count = (address - gdata.address);
  141. }
  142. /* increase address counter */
  143. while (count--)
  144. {
  145. PORTD |= (1<<CNTCLK);
  146. NOP;
  147. PORTD &= ~(1<<CNTCLK);
  148. }
  149. /* clock address into register */
  150. PORTD |= (1<<REGCLK);
  151. NOP;
  152. PORTD &= ~(1<<REGCLK);
  153. gdata.address = address;
  154. } /* address_set */
  155. /* *************************************************************************
  156. * increase address by one
  157. * ************************************************************************* */
  158. static void address_inc(void)
  159. {
  160. /* increase address counter */
  161. PORTD |= (1<<CNTCLK);
  162. NOP;
  163. PORTD &= ~(1<<CNTCLK);
  164. /* clock address into register */
  165. PORTD |= (1<<REGCLK);
  166. NOP;
  167. PORTD &= ~(1<<REGCLK);
  168. gdata.address++;
  169. } /* address_inc */
  170. /* *************************************************************************
  171. * configures max. address
  172. * ************************************************************************* */
  173. static uint8_t set_eprom_type(uint8_t type)
  174. {
  175. switch (type)
  176. {
  177. case EPROM_TYPE_2K:
  178. gdata.address_max = 0x0800;
  179. break;
  180. case EPROM_TYPE_4K:
  181. gdata.address_max = 0x1000;
  182. break;
  183. case EPROM_TYPE_8K:
  184. gdata.address_max = 0x2000;
  185. break;
  186. case EPROM_TYPE_16K:
  187. gdata.address_max = 0x4000;
  188. break;
  189. case EPROM_TYPE_32K:
  190. gdata.address_max = 0x8000;
  191. break;
  192. case EPROM_TYPE_64K:
  193. gdata.address_max = 0x10000;
  194. break;
  195. default:
  196. return ERROR_INVALID_PARAMETER;
  197. }
  198. return SUCCESS;
  199. } /* set_eprom_type */
  200. /* *************************************************************************
  201. * read data from eeprom
  202. * ************************************************************************* */
  203. static void data_read(uint8_t length)
  204. {
  205. uint8_t i;
  206. uint8_t data;
  207. DDRB = 0x00;
  208. PORTB = 0x00;
  209. for (i = 0; i < length; i++)
  210. {
  211. PORTD &= ~((1<<nCHIPSELECT) | (1<<nREAD));
  212. NOP;
  213. data = PINB;
  214. PORTD |= (1<<nCHIPSELECT) | (1<<nREAD);
  215. address_inc();
  216. ser_send(data);
  217. }
  218. } /* data_read */
  219. /* *************************************************************************
  220. *
  221. * ************************************************************************* */
  222. static void data_poll(uint8_t value)
  223. {
  224. uint16_t retry = 2000;
  225. uint8_t data;
  226. DDRB = 0x00;
  227. PORTB = 0x00;
  228. do {
  229. PORTD &= ~((1<<nCHIPSELECT) | (1<<nREAD));
  230. NOP;
  231. data = PINB;
  232. PORTD |= (1<<nCHIPSELECT) | (1<<nREAD);
  233. } while (retry-- && (data != value));
  234. } /* data_poll */
  235. /* *************************************************************************
  236. * read data to eeprom
  237. * ************************************************************************* */
  238. static void data_write(uint8_t length)
  239. {
  240. static uint8_t buffer[PAGESIZE_MAX];
  241. uint8_t i;
  242. for (i = 0; i < length; i++)
  243. {
  244. buffer[i] = ser_recv();
  245. }
  246. DDRB = 0xFF;
  247. for (i = 0; i < length; i++)
  248. {
  249. PORTB = buffer[i];
  250. PORTD &= ~((1<<nCHIPSELECT) | (1<<nWRITE));
  251. NOP;
  252. PORTD |= (1<<nCHIPSELECT) | (1<<nWRITE);
  253. /* last address of page -> start polling */
  254. if ((gdata.address & (gdata.pagesize -1)) == (gdata.pagesize -1))
  255. {
  256. data_poll(buffer[i]);
  257. DDRB = 0xFF;
  258. }
  259. address_inc();
  260. }
  261. data_poll(buffer[length -1]);
  262. DDRB = 0x00;
  263. PORTB = 0x00;
  264. } /* data_write */
  265. /* *************************************************************************
  266. *
  267. * ************************************************************************* */
  268. int main(void) __attribute__ ((noreturn));
  269. int main(void)
  270. {
  271. PORTA = (1<<nCNTRES);
  272. DDRA = (1<<nCNTRES);
  273. PORTB = 0x00;
  274. DDRB = 0x00;
  275. PORTD = (1<<RXD) | (1<<TXD) | (1<<nCHIPSELECT) | (1<<nWRITE) | (1<<nREAD);
  276. DDRD = ~(1<<RXD);
  277. /* increase rc osc frequency to reach 115200 baud */
  278. OSCCAL = 0xCC;
  279. /* enable UART 8n1 */
  280. UBRRH = (UART_CALC_BAUDRATE(BAUDRATE)>>8) & 0xFF;
  281. UBRRL = (UART_CALC_BAUDRATE(BAUDRATE) & 0xFF);
  282. UCSRC = (1<<UCSZ1) | (1<<UCSZ0);
  283. UCSRB = (1<<RXEN) | (1<<TXEN);
  284. address_clear();
  285. while (1)
  286. {
  287. uint8_t msgtype = ser_recv();
  288. uint8_t length = ser_recv();
  289. uint8_t error_code = ERROR_INVALID_PARAMETER;
  290. switch (msgtype)
  291. {
  292. case MSGTYPE_VERSION_REQ:
  293. if (length == 0x00)
  294. {
  295. ser_send(MSGTYPE_VERSION_RSP);
  296. ser_send(sizeof(version_str) -1);
  297. const uint8_t * p_data = version_str;
  298. while (*p_data)
  299. {
  300. ser_send(*p_data++);
  301. }
  302. error_code = SUCCESS;
  303. }
  304. break;
  305. case MSGTYPE_PAGESIZE_REQ:
  306. if (length == 0x00)
  307. {
  308. ser_send(MSGTYPE_PAGESIZE_RSP);
  309. ser_send(0x01);
  310. ser_send(PAGESIZE_MAX);
  311. error_code = SUCCESS;
  312. }
  313. break;
  314. case MSGTYPE_CONFIG_REQ:
  315. if (length == 0x03)
  316. {
  317. uint8_t eprom_type = ser_recv();
  318. uint8_t pagesize = ser_recv();
  319. /* reset polarity not used on this target */
  320. ser_recv();
  321. if (gdata.progmode == PROGMODE_ENABLED)
  322. {
  323. error_code = ERROR_INVALID_MODE;
  324. }
  325. else if ((pagesize <= PAGESIZE_MAX) &&
  326. (set_eprom_type(eprom_type) == SUCCESS)
  327. )
  328. {
  329. gdata.pagesize = pagesize;
  330. ser_send(MSGTYPE_CONFIG_RSP);
  331. ser_send(0x00);
  332. error_code = SUCCESS;
  333. }
  334. }
  335. break;
  336. case MSGTYPE_PROGMODE_REQ:
  337. if (length == 0x01)
  338. {
  339. uint8_t progmode = ser_recv();
  340. if (progmode <= PROGMODE_ENABLED)
  341. {
  342. gdata.progmode = progmode;
  343. ser_send(MSGTYPE_PROGMODE_RSP);
  344. ser_send(0x00);
  345. error_code = SUCCESS;
  346. }
  347. }
  348. break;
  349. case MSGTYPE_SETADDRESS_REQ:
  350. if (length == 0x03)
  351. {
  352. uint32_t address;
  353. address = ser_recv();
  354. address = (address<<8) | ser_recv();
  355. address = (address<<8) | ser_recv();
  356. if (address < gdata.address_max)
  357. {
  358. if (gdata.progmode == PROGMODE_DISABLED)
  359. {
  360. error_code = ERROR_INVALID_MODE;
  361. }
  362. else
  363. {
  364. address_set(address);
  365. ser_send(MSGTYPE_SETADDRESS_RSP);
  366. ser_send(0x00);
  367. error_code = SUCCESS;
  368. }
  369. }
  370. }
  371. break;
  372. case MSGTYPE_WRITE_REQ:
  373. if ((length > 0) &&
  374. (length <= gdata.pagesize)
  375. )
  376. {
  377. if ((gdata.address >= gdata.address_max) ||
  378. ((gdata.address + length) > gdata.address_max)
  379. )
  380. {
  381. error_code = ERROR_INVALID_ADDRESS;
  382. }
  383. else if (gdata.progmode == PROGMODE_DISABLED)
  384. {
  385. error_code = ERROR_INVALID_MODE;
  386. }
  387. else
  388. {
  389. data_write(length);
  390. ser_send(MSGTYPE_WRITE_RSP);
  391. ser_send(0x00);
  392. error_code = SUCCESS;
  393. }
  394. }
  395. break;
  396. case MSGTYPE_READ_REQ:
  397. if (length == 0x01)
  398. {
  399. uint8_t size = ser_recv();
  400. if (size <= PAGESIZE_MAX)
  401. {
  402. if ((gdata.address >= gdata.address_max) ||
  403. ((gdata.address + size) > gdata.address_max)
  404. )
  405. {
  406. error_code = ERROR_INVALID_ADDRESS;
  407. }
  408. else if (gdata.progmode == PROGMODE_DISABLED)
  409. {
  410. error_code = ERROR_INVALID_MODE;
  411. }
  412. else
  413. {
  414. ser_send(MSGTYPE_READ_RSP);
  415. ser_send(size);
  416. data_read(size);
  417. error_code = SUCCESS;
  418. }
  419. }
  420. }
  421. break;
  422. default:
  423. error_code = ERROR_UNKNOWN_COMMAND;
  424. break;
  425. }
  426. if (error_code != SUCCESS)
  427. {
  428. /* read remaining request */
  429. while (length--)
  430. {
  431. (void)ser_recv();
  432. }
  433. ser_send(MSGTYPE_ERROR_RSP);
  434. ser_send(0x01);
  435. ser_send(error_code);
  436. }
  437. }
  438. } /* main */