diff --git a/ispprog.c b/ispprog.c index c7b2f42..57206ec 100644 --- a/ispprog.c +++ b/ispprog.c @@ -154,7 +154,7 @@ static void reset_statemachine(uint8_t events) twi_init(1); result = twi_switch_application(m_twi_address, BOOTTYPE_BOOTLOADER); - if (result == TWI_ERROR) + if (result == TWI_NACK_ADDR) { /* no response from target, do normal reset */ RESET_ACTIVE(); @@ -641,6 +641,7 @@ static void cmd_handler_twi(uint8_t cmd) uint16_t write_pos = 0; uint16_t size; uint8_t type; + uint8_t result = TWI_SUCCESS; m_led_mode = LED_FAST; @@ -653,14 +654,16 @@ static void cmd_handler_twi(uint8_t cmd) memset(m_page_buf + size, 0xFF, sizeof(m_page_buf) - size); - while (write_pos < size) + while ((write_pos < size) && + (result == TWI_SUCCESS) + ) { if (type == 'F') { - twi_write_memory(m_twi_address, MEMTYPE_FLASH, - (m_address << 1), - m_page_buf + write_pos, - m_twi_chipinfo.page_size); + result = twi_write_memory(m_twi_address, MEMTYPE_FLASH, + (m_address << 1), + m_page_buf + write_pos, + m_twi_chipinfo.page_size); /* when accessing flash, m_address is a word address */ m_address += (m_twi_chipinfo.page_size >> 1); @@ -670,12 +673,13 @@ static void cmd_handler_twi(uint8_t cmd) { uint8_t write_size; - write_size = MIN(size, m_twi_chipinfo.page_size); + /* one eeprom byte takes 3.5ms to programm */ + write_size = MIN(size, 4); - twi_write_memory(m_twi_address, MEMTYPE_EEPROM, - m_address, - m_page_buf + write_pos, - write_size); + result = twi_write_memory(m_twi_address, MEMTYPE_EEPROM, + m_address, + m_page_buf + write_pos, + write_size); /* when accessing eeprom, m_address is a byte address */ m_address += write_size; @@ -683,7 +687,7 @@ static void cmd_handler_twi(uint8_t cmd) } } - uart_send('\r'); + uart_send((result == TWI_SUCCESS) ? '\r' : '!'); break; } @@ -890,6 +894,7 @@ static void cmdloop(void) uart_send_buf(m_page_buf, read_size); uart_send((result == TWI_SUCCESS) ? '\r' : '!'); + break; } #endif /* (USE_TWI_SUPPORT) */ diff --git a/twi_master.c b/twi_master.c index 34c236f..e4ef02a 100644 --- a/twi_master.c +++ b/twi_master.c @@ -22,6 +22,8 @@ #include "target.h" #include "twi_master.h" +#include + #if (USE_TWI_SUPPORT) #define TWI_SLA_W(addr) (addr << 1) @@ -73,6 +75,13 @@ static uint8_t twi_master_tx(uint8_t value) case 0x40: /* SLA+R transmitted, ACK received */ return TWI_SUCCESS; + case 0x20: /* SLA+W transmitted, NACK received */ + case 0x48: /* SLA+R transmitted, NACK received */ + return TWI_NACK_ADDR; + + case 0x30: /* Data transmitted, NACK received */ + return TWI_NACK_DATA; + default: return TWI_ERROR; } @@ -105,17 +114,78 @@ static uint8_t twi_master_rx(uint8_t * p_value, uint8_t ack) * *********************************************************************** */ static uint8_t twi_master_start(uint8_t twi_addr) { - if (twi_start() == TWI_SUCCESS) + uint8_t result = TWI_NACK_ADDR; + uint8_t retry = 10; + + while ((result == TWI_NACK_ADDR) && (retry--)) { - if (twi_master_tx(twi_addr) == TWI_SUCCESS) + result = twi_start(); + if (result == TWI_SUCCESS) { - return TWI_SUCCESS; + result = twi_master_tx(twi_addr); + if (result == TWI_SUCCESS) + { + return result; + } + } + + twi_stop(); + _delay_ms(2); + } + + return result; +} /* twi_master_start */ + + +/* *********************************************************************** + * twi_master_tx_buf + * *********************************************************************** */ +static uint8_t twi_master_tx_buf(const uint8_t * p_data, uint16_t data_size) +{ + uint8_t result = TWI_ERROR; + + while (data_size--) + { + result = twi_master_tx(*p_data++); + if (result != TWI_SUCCESS) + { + /* NACK for the last transmitted byte is OK */ + if ((result == TWI_NACK_DATA) && (data_size == 0)) + { + result = TWI_SUCCESS; + } + else + { + break; + } } } - twi_stop(); - return TWI_ERROR; -} /* twi_master_start */ + return result; +} /* twi_master_tx_buf */ + + +/* *********************************************************************** + * twi_master_rx_buf + * *********************************************************************** */ +static uint8_t twi_master_rx_buf(uint8_t * p_data, uint16_t data_size) +{ + uint8_t result = TWI_ERROR; + + while (data_size--) + { + uint8_t ack; + + ack = (data_size > 0); + result = twi_master_rx(p_data++, ack); + if (result != TWI_SUCCESS) + { + break; + } + } + + return result; +} /* twi_master_rx_buf */ /* *********************************************************************** @@ -132,16 +202,7 @@ uint8_t twi_generic(uint8_t twi_addr, result = twi_master_start(TWI_SLA_W(twi_addr)); if (result == TWI_SUCCESS) { - uint16_t i; - - for (i = 0; i < write_size; i++) - { - result = twi_master_tx(*p_wr_data++); - if (result != TWI_SUCCESS) - { - break; - } - } + result = twi_master_tx_buf(p_wr_data, write_size); } } @@ -152,19 +213,7 @@ uint8_t twi_generic(uint8_t twi_addr, result = twi_master_start(TWI_SLA_R(twi_addr)); if (result == TWI_SUCCESS) { - uint16_t i; - - for (i = 0; i < read_size; i++) - { - uint8_t ack; - - ack = (i != (read_size -1)); - result = twi_master_rx(p_rd_data++, ack); - if (result != TWI_SUCCESS) - { - break; - } - } + result = twi_master_rx_buf(p_rd_data, read_size); } } @@ -237,30 +286,12 @@ uint8_t twi_write_memory(uint8_t twi_addr, uint8_t memory_type, uint16_t memory_ result = twi_master_start(TWI_SLA_W(twi_addr)); if (result == TWI_SUCCESS) { - uint16_t i; - - for (i = 0; i < sizeof(cmd); i++) - { - result = twi_master_tx(cmd[i]); - if (result != TWI_SUCCESS) - { - break; - } - } + result = twi_master_tx_buf(cmd, sizeof(cmd)); } if (result == TWI_SUCCESS) { - uint16_t i; - - for (i = 0; i < data_length; i++) - { - result = twi_master_tx(*p_data++); - if (result != TWI_SUCCESS) - { - break; - } - } + result = twi_master_tx_buf(p_data, data_length); } twi_stop(); diff --git a/twi_master.h b/twi_master.h index ca98acb..c52635d 100644 --- a/twi_master.h +++ b/twi_master.h @@ -25,6 +25,8 @@ #define TWI_SUCCESS 0x00 #define TWI_ERROR 0x01 +#define TWI_NACK_ADDR 0x02 +#define TWI_NACK_DATA 0x03 typedef struct twi_chipinfo_s {