From 63b22919310aeed53fac0a9852fdf6eb970a8850 Mon Sep 17 00:00:00 2001 From: Olaf Rempel Date: Wed, 8 Jan 2020 23:34:44 +0100 Subject: [PATCH] Move spi/isp handling to own file --- ispprog.c | 393 ++++++++++++++---------------------------------------- spi_isp.c | 233 ++++++++++++++++++++++++++++++++ spi_isp.h | 71 ++++++++++ target.h | 22 +-- 4 files changed, 419 insertions(+), 300 deletions(-) create mode 100644 spi_isp.c create mode 100644 spi_isp.h diff --git a/ispprog.c b/ispprog.c index 2b89cf2..4b180aa 100644 --- a/ispprog.c +++ b/ispprog.c @@ -24,26 +24,10 @@ #include "avrdevice.h" #include "display.h" +#include "spi_isp.h" #include "target.h" #include "uart.h" -#include - -/* F_CPU /4 (1.8432MHz) */ -#define SPI_MODE4 ((1<> 8); - spi_rxtx(addr & 0xFF); - spi_rxtx(val); - - /* remember values for polling */ - last_cmd = cmd; - last_addr = addr; - last_val = val; -} /* mem_write */ - - -/* read a byte from target flash/eeprom */ -static uint8_t mem_read(uint8_t cmd, uint16_t addr) -{ - spi_rxtx(cmd); - spi_rxtx(addr >> 8); - spi_rxtx(addr & 0xFF); - return spi_rxtx(0x00); -} /* mem_read */ - - -/* wait until byte/page is written to target memory */ -static void poll(void) -{ - uint8_t cmd, val, poll = 0xFF; - - if (((last_val == 0x00) && (m_device.flags & POLL_00)) || - ((last_val == 0x7F) && (m_device.flags & POLL_7F)) || - ((last_val == 0x80) && (m_device.flags & POLL_80)) || - ((last_val == 0xFF) && (m_device.flags & POLL_FF)) - ) { - /* wait default time */ - _delay_ms(15); - return; - } - - if (last_cmd == CMD_WRITE_EEPROM) { - cmd = CMD_READ_EEPROM; - - } else { - /* CMD_WRITE_FLASH -> CMD_READ_FLASH */ - cmd = (last_cmd & 0x08) | 0x20; - } - - /* poll until we get correct value */ - do { - val = mem_read(cmd, last_addr); - } while ((val != last_val) && poll--); -} /* poll */ - - -static void mem_pagewrite(uint16_t addr) -{ - spi_rxtx(CMD_WRITE_FLASH_PAGE); - spi_rxtx(addr >> 8); - spi_rxtx(addr & 0xFF); - spi_rxtx(0x00); - - poll(); -} /* mem_pagewrite */ +static uint16_t m_address = 0x0000; static void reset_statemachine(uint8_t event); static volatile uint16_t reset_timer = 0x0000; static volatile uint8_t reset_state; -static uint16_t addr = 0x0000; - static void cmdloop(void) __attribute__ ((noreturn)); static void cmdloop(void) { - static uint8_t page_buf[256]; - while (1) { #if (USE_DISPLAY) if (reset_state == STATE_RESET_PROGMODE) { uint16_t byte_address; - byte_address = (addr << 1); + byte_address = (m_address << 1); display_show_hex(byte_address >> 8, 0); display_show_hex(byte_address & 0xFF, 1); @@ -261,19 +110,20 @@ static void cmdloop(void) /* Set address */ case 'A': - addr = (uart_recv() << 8); - addr |= uart_recv(); + m_address = (uart_recv() << 8); + m_address |= uart_recv(); uart_send('\r'); break; /* Write program memory, low byte */ case 'c': led_mode = LED_FAST; - mem_write(CMD_LOAD_FLASH_LO, addr, uart_recv()); + isp_mem_write(CMD_LOAD_FLASH_LO, m_address, uart_recv()); /* poll on byte addressed targets */ - if (m_device.pagemask == 0x00) { - poll(); + if (m_device.pagemask == 0x00) + { + isp_mem_poll(&m_device); } uart_send('\r'); @@ -282,92 +132,82 @@ static void cmdloop(void) /* Write program memory, high byte */ case 'C': led_mode = LED_FAST; - mem_write(CMD_LOAD_FLASH_HI, addr, uart_recv()); + isp_mem_write(CMD_LOAD_FLASH_HI, m_address, uart_recv()); /* poll on byte addressed targets */ - if (m_device.pagemask == 0x00) { - poll(); + if (m_device.pagemask == 0x00) + { + isp_mem_poll(&m_device); } - addr++; + m_address++; uart_send('\r'); break; /* Issue Page Write */ case 'm': led_mode = LED_FAST; - mem_pagewrite(last_addr); + isp_mem_pagewrite(); + isp_mem_poll(&m_device); uart_send('\r'); break; /* Read Lock Bits */ case 'r': - uart_send(mem_read(CMD_READ_LOCK_1, CMD_READ_LOCK_2 << 8)); + uart_send(isp_mem_read(CMD_READ_LOCK_1, CMD_READ_LOCK_2 << 8)); uart_send('\r'); break; /* Read program memory */ case 'R': led_mode = LED_SLOW; - uart_send(mem_read(CMD_READ_FLASH_HI, addr)); - uart_send(mem_read(CMD_READ_FLASH_LO, addr)); - addr++; + uart_send(isp_mem_read(CMD_READ_FLASH_HI, m_address)); + uart_send(isp_mem_read(CMD_READ_FLASH_LO, m_address)); + m_address++; break; /* Read data memory */ case 'd': led_mode = LED_SLOW; - uart_send(mem_read(CMD_READ_EEPROM, addr)); - addr++; + uart_send(isp_mem_read(CMD_READ_EEPROM, m_address)); + m_address++; break; /* Write data memory */ case 'D': led_mode = LED_FAST; - mem_write(CMD_WRITE_EEPROM, addr, uart_recv()); - poll(); + isp_mem_write(CMD_WRITE_EEPROM, m_address, uart_recv()); + isp_mem_poll(&m_device); - addr++; + m_address++; uart_send('\r'); break; /* Chip erase */ case 'e': - spi_rxtx(CMD_CHIP_ERASE_1); - spi_rxtx(CMD_CHIP_ERASE_2); - spi_rxtx(0x00); - spi_rxtx(0x00); - - _delay_ms(10); + isp_cmd4(CMD_CHIP_ERASE_1, CMD_CHIP_ERASE_2, 0x00, 0x00); uart_send('\r'); break; /* Write lock bits */ - case 'l': { - uint8_t val = uart_recv(); - spi_rxtx(CMD_WRITE_LOCK_1); - spi_rxtx(CMD_WRITE_LOCK_2); - spi_rxtx(0x00); - spi_rxtx(val); - - _delay_ms(10); + case 'l': + isp_cmd4(CMD_WRITE_LOCK_1, CMD_WRITE_LOCK_2, 0x00, uart_recv()); uart_send('\r'); break; - } /* Read fusebits */ case 'F': - uart_send(mem_read(CMD_READ_FUSE_1, CMD_READ_FUSE_2 << 8)); + uart_send(isp_mem_read(CMD_READ_FUSE_1, CMD_READ_FUSE_2 << 8)); break; /* Read high fusebits */ case 'N': - uart_send(mem_read(CMD_READ_FUSE_H_1, CMD_READ_FUSE_H_2 << 8)); + uart_send(isp_mem_read(CMD_READ_FUSE_H_1, CMD_READ_FUSE_H_2 << 8)); break; /* Read extended fusebits */ case 'Q': - uart_send(mem_read(CMD_READ_FUSE_E_1, CMD_READ_FUSE_E_2 << 8)); + uart_send(isp_mem_read(CMD_READ_FUSE_E_1, CMD_READ_FUSE_E_2 << 8)); break; /* Leave programming mode */ @@ -440,15 +280,15 @@ static void cmdloop(void) break; /* Report Block write Mode */ - case 'b': { + case 'b': uart_send('Y'); - uart_send(sizeof(page_buf) >> 8); - uart_send(sizeof(page_buf) & 0xFF); + uart_send(sizeof(m_page_buf) >> 8); + uart_send(sizeof(m_page_buf) & 0xFF); break; - } /* Block Write */ - case 'B': { + case 'B': + { uint16_t size, i; uint8_t type; @@ -458,39 +298,49 @@ static void cmdloop(void) size |= uart_recv(); type = uart_recv(); - uart_recv_buf(page_buf, size); + uart_recv_buf(m_page_buf, size); - if (type == 'F') { - for (i = 0; i < size; i += 2) { - mem_write(CMD_LOAD_FLASH_LO, addr, page_buf[i]); - mem_write(CMD_LOAD_FLASH_HI, addr, page_buf[i+1]); + if (type == 'F') + { + for (i = 0; i < size; i += 2) + { + isp_mem_write(CMD_LOAD_FLASH_LO, m_address, m_page_buf[i]); + isp_mem_write(CMD_LOAD_FLASH_HI, m_address, m_page_buf[i+1]); - addr++; + m_address++; - if ((addr & m_device.pagemask) == 0x00) { - mem_pagewrite(last_addr); + if ((m_address & m_device.pagemask) == 0x00) + { + isp_mem_pagewrite(); + isp_mem_poll(&m_device); } } if ((m_device.pagemask != 0x00) && (size != ((m_device.pagemask +1) << 1)) - ) { - mem_pagewrite(last_addr); - } - - } else if (type == 'E') { - for (i = 0; i < size; i++) { - mem_write(CMD_WRITE_EEPROM, addr, page_buf[i]); - poll(); - addr++; + ) + { + isp_mem_pagewrite(); + isp_mem_poll(&m_device); } } + else if (type == 'E') + { + for (i = 0; i < size; i++) + { + isp_mem_write(CMD_WRITE_EEPROM, m_address, m_page_buf[i]); + isp_mem_poll(&m_device); + m_address++; + } + } + uart_send('\r'); break; } /* Block Read */ - case 'g': { + case 'g': + { uint16_t size, i; uint8_t type; @@ -500,67 +350,50 @@ static void cmdloop(void) size |= uart_recv(); type = uart_recv(); - if (type == 'F') { - for (i = 0; i < size; i += 2) { - uart_send(mem_read(CMD_READ_FLASH_LO, addr)); - uart_send(mem_read(CMD_READ_FLASH_HI, addr)); - addr++; + if (type == 'F') + { + for (i = 0; i < size; i += 2) + { + uart_send(isp_mem_read(CMD_READ_FLASH_LO, m_address)); + uart_send(isp_mem_read(CMD_READ_FLASH_HI, m_address)); + m_address++; } - - } else if (type == 'E') { - for (i = 0; i < size; i++) { - uart_send(mem_read(CMD_READ_EEPROM, addr)); - addr++; + } + else if (type == 'E') + { + for (i = 0; i < size; i++) + { + uart_send(isp_mem_read(CMD_READ_EEPROM, m_address)); + m_address++; } } break; } /* Write fusebits */ - case 'f': { - uint8_t val = uart_recv(); - spi_rxtx(CMD_WRITE_FUSE_1); - spi_rxtx(CMD_WRITE_FUSE_2); - spi_rxtx(0x00); - spi_rxtx(val); - - _delay_ms(10); + case 'f': + isp_cmd4(CMD_WRITE_FUSE_1, CMD_WRITE_FUSE_2, 0x00, uart_recv()); uart_send('\r'); break; - } /* Universial command */ - case ':': { + case ':': + { uint8_t val[3]; uart_recv_buf(val, sizeof(val)); - - spi_rxtx(val[0]); - spi_rxtx(val[1]); - uart_send(spi_rxtx(val[2])); - - _delay_ms(10); + uart_send(isp_cmd3(val[0], val[1], val[2])); uart_send('\r'); break; } /* New universal command */ - case '.': { + case '.': + { uint8_t val[4]; uart_recv_buf(val, sizeof(val)); - - spi_rxtx(val[0]); - spi_rxtx(val[1]); - spi_rxtx(val[2]); - uart_send(spi_rxtx(val[3])); - - /* most CMD_WRITE_* commands need delay */ - if (val[0] == CMD_WRITE_LOCK_1) - { - _delay_ms(10); - } - + uart_send(isp_cmd4(val[0], val[1], val[2], val[3])); uart_send('\r'); break; } @@ -603,16 +436,15 @@ static void reset_statemachine(uint8_t event) timer = 0; /* stop timer */ /* put device in RUN mode */ - set_reset(1); + spi_init(0); + RESET_INACTIVE(); } else if ((event == EV_BUTTON_PRESSED) || (event == EV_PROG_ENTER)) { reset_retries = 5; reset_cause = event; - /* probe SPI speed of device */ - if (spi_speed == SPI_SPEED_PROBE) { - spi_speed = 3; - } + /* enable SPI interface */ + spi_init(1); state = STATE_RESET_SYNC; } @@ -623,28 +455,15 @@ static void reset_statemachine(uint8_t event) led_mode = LED_ON; timer = 1; /* timeout 50ms */ - /* set SPI speed */ - SPCR = spi_modes[spi_speed]; - /* put device in ISP mode */ - set_reset(0); + RESET_ACTIVE(); } else if (event == EV_TIMEOUT) { - uint8_t sync; - spi_rxtx(CMD_PROG_ENABLE_1); - spi_rxtx(CMD_PROG_ENABLE_2); - sync = spi_rxtx(0x00); - spi_rxtx(0x00); - memset(&m_device, 0x00, sizeof(avr_device_t)); - if (sync == CMD_PROG_ENABLE_2) { - uint8_t i; - - for (i = 0; i < 3; i++) { - m_device.sig[i] = mem_read(CMD_READ_SIG_1, (CMD_READ_SIG_2 << 8) | i); - } - + if (isp_enter_progmode()) + { + isp_read_signature(m_device.sig); avrdevice_get_by_signature(&m_device, m_device.sig); state = STATE_RESET_PROGMODE; @@ -661,21 +480,18 @@ static void reset_statemachine(uint8_t event) timer = 5; /* timeout 50ms */ /* put device in RUN mode */ - set_reset(1); + RESET_INACTIVE(); } else if (event == EV_TIMEOUT) { reset_retries--; if (reset_retries > 0) { /* try lower frequency */ - if (spi_speed > 0) { - spi_speed--; - } + spi_set_clk(SPI_SET_CLK_DEC); state = STATE_RESET_SYNC; } else { - /* got no sync, probe speed again next time */ - spi_speed = SPI_SPEED_PROBE; + /* got no sync */ state = STATE_IDLE; } } @@ -688,12 +504,10 @@ static void reset_statemachine(uint8_t event) state = STATE_IDLE; } - } else if (event == EV_PROG_LEAVE) { - /* was in prog mode (osc changed?), probe speed next time */ - spi_speed = SPI_SPEED_PROBE; - state = STATE_IDLE; - - } else if (event == EV_BUTTON_PRESSED) { + } else if ((event == EV_PROG_LEAVE) || + (event == EV_BUTTON_PRESSED) + ) + { state = STATE_IDLE; } break; @@ -813,8 +627,7 @@ int main(void) uart_init(); - /* enable SPI master mode */ - SPCR = SPI_MODE4; + spi_init(0); TIMER_INIT(); diff --git a/spi_isp.c b/spi_isp.c new file mode 100644 index 0000000..ec4dad0 --- /dev/null +++ b/spi_isp.c @@ -0,0 +1,233 @@ +/*************************************************************************** + * Copyright (C) 2006 - 2020 by Olaf Rempel * + * razzor AT kopf MINUS tisch DOT de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; version 2 of the License, * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include + +#include "avrdevice.h" +#include "spi_isp.h" +#include "target.h" + +#include + +/* F_CPU /4 (1.8432MHz) */ +#define SPI_MODE4 ((1< 0) + ) + { + spi_speed--; + } + + /* enable SPI master mode */ + SPCR = m_spi_modes[spi_speed]; +} /* spi_set_clk */ + + +/* *********************************************************************** + * spi_init + * *********************************************************************** */ +void spi_init(uint8_t enable) +{ + if (enable) + { + ISP_ACTIVE(); + spi_set_clk(SPI_SET_CLK_MAX); + } + else + { + ISP_INACTIVE(); + SPCR = 0x00; + } +} /* spi_init */ + + +/* *********************************************************************** + * isp_enter_progmode + * *********************************************************************** */ +uint8_t isp_enter_progmode(void) +{ + uint8_t sync; + spi_rxtx(CMD_PROG_ENABLE_1); + spi_rxtx(CMD_PROG_ENABLE_2); + sync = spi_rxtx(0x00); + spi_rxtx(0x00); + + return (sync == CMD_PROG_ENABLE_2); +} /* isp_enter_progmode */ + + +/* *********************************************************************** + * isp_mem_write + * - write a byte to target flash/eeprom + * *********************************************************************** */ +void isp_mem_write(uint8_t cmd, uint16_t addr, uint8_t val) +{ + spi_rxtx(cmd); + spi_rxtx(addr >> 8); + spi_rxtx(addr & 0xFF); + spi_rxtx(val); + + /* remember values for polling */ + m_last_cmd = cmd; + m_last_addr = addr; + m_last_val = val; +} /* isp_mem_write */ + + +/* *********************************************************************** + * isp_mem_read + * - read a byte from target flash/eeprom + * *********************************************************************** */ +uint8_t isp_mem_read(uint8_t cmd, uint16_t addr) +{ + spi_rxtx(cmd); + spi_rxtx(addr >> 8); + spi_rxtx(addr & 0xFF); + return spi_rxtx(0x00); +} /* isp_mem_read */ + + +/* *********************************************************************** + * isp_mem_poll + * - wait until byte/page is written to target memory + * *********************************************************************** */ +void isp_mem_poll(const avr_device_t * p_device) +{ + uint8_t cmd, val, poll = 0xFF; + + if (((m_last_val == 0x00) && (p_device->flags & POLL_00)) || + ((m_last_val == 0x7F) && (p_device->flags & POLL_7F)) || + ((m_last_val == 0x80) && (p_device->flags & POLL_80)) || + ((m_last_val == 0xFF) && (p_device->flags & POLL_FF)) + ) { + /* wait default time */ + _delay_ms(15); + return; + } + + if (m_last_cmd == CMD_WRITE_EEPROM) { + cmd = CMD_READ_EEPROM; + + } else { + /* CMD_WRITE_FLASH -> CMD_READ_FLASH */ + cmd = (m_last_cmd & 0x08) | 0x20; + } + + /* poll until we get correct value */ + do { + val = isp_mem_read(cmd, m_last_addr); + } while ((val != m_last_val) && poll--); +} /* isp_mem_poll */ + + +/* *********************************************************************** + * isp_mem_pagewrite + * *********************************************************************** */ +void isp_mem_pagewrite(void) +{ + spi_rxtx(CMD_WRITE_FLASH_PAGE); + spi_rxtx(m_last_addr >> 8); + spi_rxtx(m_last_addr & 0xFF); + spi_rxtx(0x00); +} /* isp_mem_pagewrite */ + + +/* *********************************************************************** + * isp_read_signature + * *********************************************************************** */ +void isp_read_signature(uint8_t * p_signature) +{ + uint8_t i; + + for (i = 0; i < 3; i++) + { + p_signature[i] = isp_mem_read(CMD_READ_SIG_1, (CMD_READ_SIG_2 << 8) | i); + } +} /* isp_read_signature */ + + +/* *********************************************************************** + * isp_cmd3 + * *********************************************************************** */ +uint8_t isp_cmd3(uint8_t cmd1, uint8_t cmd2, + uint8_t cmd3) +{ + uint8_t result; + + spi_rxtx(cmd1); + spi_rxtx(cmd2); + result = spi_rxtx(cmd3); + + _delay_ms(10); + return result; +} /* isp_cmd3 */ + + +/* *********************************************************************** + * isp_cmd4 + * *********************************************************************** */ +uint8_t isp_cmd4(uint8_t cmd1, uint8_t cmd2, + uint8_t cmd3, uint8_t cmd4) +{ + uint8_t result; + + spi_rxtx(cmd1); + spi_rxtx(cmd2); + spi_rxtx(cmd3); + result = spi_rxtx(cmd4); + + _delay_ms(10); + return result; +} /* isp_cmd3 */ diff --git a/spi_isp.h b/spi_isp.h new file mode 100644 index 0000000..6467559 --- /dev/null +++ b/spi_isp.h @@ -0,0 +1,71 @@ +#ifndef SPI_ISP_H_ +#define SPI_ISP_H_ + +#include + +#include "avrdevice.h" + +/* *********************************************************************** */ + +#define SPI_SET_CLK_MAX 0 +#define SPI_SET_CLK_DEC 1 + +#define CMD_PROG_ENABLE_1 0xAC +#define CMD_PROG_ENABLE_2 0x53 +#define CMD_CHIP_ERASE_1 0xAC +#define CMD_CHIP_ERASE_2 0x80 +#define CMD_POLL_BUSY_1 0xF0 /* not used */ +#define CMD_POLL_BUSY_2 0x00 /* not used */ + +#define CMD_LOAD_EADDR_1 0x4D /* not used */ +#define CMD_LOAD_EADDR_2 0x00 /* not used */ +#define CMD_LOAD_FLASH_HI 0x48 +#define CMD_LOAD_FLASH_LO 0x40 +#define CMD_LOAD_EEPROM_PAGE 0xC1 /* not used */ + +#define CMD_READ_FLASH_LO 0x20 +#define CMD_READ_FLASH_HI 0x28 +#define CMD_READ_EEPROM 0xA0 +#define CMD_READ_LOCK_1 0x58 +#define CMD_READ_LOCK_2 0x00 +#define CMD_READ_SIG_1 0x30 +#define CMD_READ_SIG_2 0x00 +#define CMD_READ_FUSE_1 0x50 +#define CMD_READ_FUSE_2 0x00 +#define CMD_READ_FUSE_H_1 0x58 +#define CMD_READ_FUSE_H_2 0x08 +#define CMD_READ_FUSE_E_1 0x50 +#define CMD_READ_FUSE_E_2 0x08 +#define CMD_READ_CAL 0x38 /* not used */ + +#define CMD_WRITE_FLASH_PAGE 0x4C +#define CMD_WRITE_EEPROM 0xC0 +#define CMD_WRITE_EEPROM_PAGE 0xC2 /* not used */ +#define CMD_WRITE_LOCK_1 0xAC +#define CMD_WRITE_LOCK_2 0xE0 +#define CMD_WRITE_FUSE_1 0xAC +#define CMD_WRITE_FUSE_2 0xA0 +#define CMD_WRITE_FUSE_H_1 0xAC /* not used */ +#define CMD_WRITE_FUSE_H_2 0xA8 /* not used */ +#define CMD_WRITE_FUSE_E_1 0xAC /* not used */ +#define CMD_WRITE_FUSE_E_2 0xA4 /* not used */ + +/* *********************************************************************** */ + +void spi_set_clk (uint8_t mode); +void spi_init (uint8_t enable); + +uint8_t isp_enter_progmode (void); +void isp_mem_write (uint8_t cmd, uint16_t addr, uint8_t val); +uint8_t isp_mem_read (uint8_t cmd, uint16_t addr); +void isp_mem_poll (const avr_device_t * p_device); +void isp_mem_pagewrite (void); +void isp_read_signature (uint8_t * p_signature); +uint8_t isp_cmd3 (uint8_t cmd1, uint8_t cmd2, + uint8_t cmd3); +uint8_t isp_cmd4 (uint8_t cmd1, uint8_t cmd2, + uint8_t cmd3, uint8_t cmd4); + +/* *********************************************************************** */ + +#endif /* SPI_ISP_H_ */ diff --git a/target.h b/target.h index 8297d38..2012402 100644 --- a/target.h +++ b/target.h @@ -19,14 +19,15 @@ #define ISP_SCK PORTB7 /* to target */ #define RESET_IN PORTD3 /* high active */ -#define ISP_INACTIVE() { /* ISP_SCK, ISP_MOSI and ISP_RESET are inputs */ \ - DDRB &= ~((1<