Browse Source

Differentiate twi bus errors and address/data NACKs

master
Olaf Rempel 5 months ago
parent
commit
2d9c71bb8b
3 changed files with 98 additions and 60 deletions
  1. +17
    -12
      ispprog.c
  2. +79
    -48
      twi_master.c
  3. +2
    -0
      twi_master.h

+ 17
- 12
ispprog.c View File

@@ -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) */



+ 79
- 48
twi_master.c View File

@@ -22,6 +22,8 @@
#include "target.h"
#include "twi_master.h"

#include <util/delay.h>

#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,20 +114,81 @@ 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);
}

twi_stop();
return TWI_ERROR;
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;
}
}
}

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 */


/* ***********************************************************************
* twi_generic
* *********************************************************************** */
uint8_t twi_generic(uint8_t twi_addr,
@@ -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();


+ 2
- 0
twi_master.h View File

@@ -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
{


Loading…
Cancel
Save