Differentiate twi bus errors and address/data NACKs

This commit is contained in:
Olaf Rempel 2020-01-26 00:24:20 +01:00
parent afd7b92c1f
commit 2d9c71bb8b
3 changed files with 99 additions and 61 deletions

View File

@ -154,7 +154,7 @@ static void reset_statemachine(uint8_t events)
twi_init(1); twi_init(1);
result = twi_switch_application(m_twi_address, BOOTTYPE_BOOTLOADER); 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 */ /* no response from target, do normal reset */
RESET_ACTIVE(); RESET_ACTIVE();
@ -641,6 +641,7 @@ static void cmd_handler_twi(uint8_t cmd)
uint16_t write_pos = 0; uint16_t write_pos = 0;
uint16_t size; uint16_t size;
uint8_t type; uint8_t type;
uint8_t result = TWI_SUCCESS;
m_led_mode = LED_FAST; 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); 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') if (type == 'F')
{ {
twi_write_memory(m_twi_address, MEMTYPE_FLASH, result = twi_write_memory(m_twi_address, MEMTYPE_FLASH,
(m_address << 1), (m_address << 1),
m_page_buf + write_pos, m_page_buf + write_pos,
m_twi_chipinfo.page_size); m_twi_chipinfo.page_size);
/* when accessing flash, m_address is a word address */ /* when accessing flash, m_address is a word address */
m_address += (m_twi_chipinfo.page_size >> 1); m_address += (m_twi_chipinfo.page_size >> 1);
@ -670,12 +673,13 @@ static void cmd_handler_twi(uint8_t cmd)
{ {
uint8_t write_size; 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, result = twi_write_memory(m_twi_address, MEMTYPE_EEPROM,
m_address, m_address,
m_page_buf + write_pos, m_page_buf + write_pos,
write_size); write_size);
/* when accessing eeprom, m_address is a byte address */ /* when accessing eeprom, m_address is a byte address */
m_address += write_size; 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; break;
} }
@ -890,6 +894,7 @@ static void cmdloop(void)
uart_send_buf(m_page_buf, read_size); uart_send_buf(m_page_buf, read_size);
uart_send((result == TWI_SUCCESS) ? '\r' : '!'); uart_send((result == TWI_SUCCESS) ? '\r' : '!');
break;
} }
#endif /* (USE_TWI_SUPPORT) */ #endif /* (USE_TWI_SUPPORT) */

View File

@ -22,6 +22,8 @@
#include "target.h" #include "target.h"
#include "twi_master.h" #include "twi_master.h"
#include <util/delay.h>
#if (USE_TWI_SUPPORT) #if (USE_TWI_SUPPORT)
#define TWI_SLA_W(addr) (addr << 1) #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 */ case 0x40: /* SLA+R transmitted, ACK received */
return TWI_SUCCESS; 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: default:
return TWI_ERROR; 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) 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 result;
return TWI_ERROR; } /* twi_master_tx_buf */
} /* twi_master_start */
/* ***********************************************************************
* 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)); result = twi_master_start(TWI_SLA_W(twi_addr));
if (result == TWI_SUCCESS) if (result == TWI_SUCCESS)
{ {
uint16_t i; result = twi_master_tx_buf(p_wr_data, write_size);
for (i = 0; i < write_size; i++)
{
result = twi_master_tx(*p_wr_data++);
if (result != TWI_SUCCESS)
{
break;
}
}
} }
} }
@ -152,19 +213,7 @@ uint8_t twi_generic(uint8_t twi_addr,
result = twi_master_start(TWI_SLA_R(twi_addr)); result = twi_master_start(TWI_SLA_R(twi_addr));
if (result == TWI_SUCCESS) if (result == TWI_SUCCESS)
{ {
uint16_t i; result = twi_master_rx_buf(p_rd_data, read_size);
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;
}
}
} }
} }
@ -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)); result = twi_master_start(TWI_SLA_W(twi_addr));
if (result == TWI_SUCCESS) if (result == TWI_SUCCESS)
{ {
uint16_t i; result = twi_master_tx_buf(cmd, sizeof(cmd));
for (i = 0; i < sizeof(cmd); i++)
{
result = twi_master_tx(cmd[i]);
if (result != TWI_SUCCESS)
{
break;
}
}
} }
if (result == TWI_SUCCESS) if (result == TWI_SUCCESS)
{ {
uint16_t i; result = twi_master_tx_buf(p_data, data_length);
for (i = 0; i < data_length; i++)
{
result = twi_master_tx(*p_data++);
if (result != TWI_SUCCESS)
{
break;
}
}
} }
twi_stop(); twi_stop();

View File

@ -25,6 +25,8 @@
#define TWI_SUCCESS 0x00 #define TWI_SUCCESS 0x00
#define TWI_ERROR 0x01 #define TWI_ERROR 0x01
#define TWI_NACK_ADDR 0x02
#define TWI_NACK_DATA 0x03
typedef struct twi_chipinfo_s typedef struct twi_chipinfo_s
{ {