Add twiboot bridge
This commit is contained in:
parent
cfef6e9a72
commit
144016f65d
@ -23,7 +23,7 @@
|
||||
|
||||
#if (USE_DISPLAY)
|
||||
static display_mode_t m_mode = DISPLAY_MODE_OFF;
|
||||
static char m_buffer[24];
|
||||
static char m_buffer[32];
|
||||
static uint8_t m_buffer_length = 0;
|
||||
static uint8_t m_buffer_pos = 0;
|
||||
|
||||
|
320
ispprog.c
320
ispprog.c
@ -26,8 +26,11 @@
|
||||
#include "display.h"
|
||||
#include "spi_isp.h"
|
||||
#include "target.h"
|
||||
#include "twi_master.h"
|
||||
#include "uart.h"
|
||||
|
||||
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
|
||||
|
||||
#define TIMER_IRQFREQ_MS 10
|
||||
|
||||
/* convert milliseconds to timer ticks */
|
||||
@ -41,12 +44,14 @@
|
||||
#define EV_TIMEOUT 0x08
|
||||
#define EV_PROG_ENTER 0x10
|
||||
#define EV_PROG_LEAVE 0x20
|
||||
#define EV_PROG_ENTER_TWI 0x40
|
||||
|
||||
#define STATE_IDLE 0x00 /* nothing */
|
||||
#define STATE_RESET_SYNC 0x01
|
||||
#define STATE_RESET_RETRY 0x02
|
||||
#define STATE_RESET_PROGMODE 0x03
|
||||
|
||||
#define STATE_TWI_CHECK_BL 0x04
|
||||
#define STATE_TWI_PROGMODE 0x05
|
||||
|
||||
#define LED_OFF 0x00
|
||||
#define LED_SLOW 0x20
|
||||
@ -63,6 +68,11 @@ static uint8_t m_page_buf[256];
|
||||
static avr_device_t m_device;
|
||||
static uint16_t m_address = 0x0000;
|
||||
|
||||
#if (USE_TWI_SUPPORT)
|
||||
static twi_chipinfo_t m_twi_chipinfo;
|
||||
static uint8_t m_twi_address;
|
||||
#endif /* (USE_TWI_SUPPORT) */
|
||||
|
||||
|
||||
static void reset_statemachine(uint8_t events)
|
||||
{
|
||||
@ -105,12 +115,20 @@ static void reset_statemachine(uint8_t events)
|
||||
timer = TIMER_MSEC2IRQCNT(0);
|
||||
|
||||
spi_init(0);
|
||||
|
||||
#if (USE_TWI_SUPPORT)
|
||||
twi_init(0);
|
||||
#endif
|
||||
/* put device in RUN mode */
|
||||
RESET_INACTIVE();
|
||||
m_led_mode = LED_OFF;
|
||||
}
|
||||
else if (events & (EV_BUTTON_PRESSED | EV_PROG_ENTER))
|
||||
else if ((events & EV_PROG_ENTER) ||
|
||||
#if (USE_TWI_SUPPORT)
|
||||
((events & EV_BUTTON_PRESSED) && (m_twi_address == 0x00))
|
||||
#else
|
||||
(events & EV_BUTTON_PRESSED)
|
||||
#endif /* (USE_TWI_SUPPORT) */
|
||||
)
|
||||
{
|
||||
reset_cause = events;
|
||||
events &= ~(EV_BUTTON_PRESSED | EV_PROG_ENTER);
|
||||
@ -122,6 +140,29 @@ static void reset_statemachine(uint8_t events)
|
||||
|
||||
m_state = STATE_RESET_SYNC;
|
||||
}
|
||||
#if (USE_TWI_SUPPORT)
|
||||
else if ((events & EV_PROG_ENTER_TWI) ||
|
||||
((events & EV_BUTTON_PRESSED) && (m_twi_address != 0x00))
|
||||
)
|
||||
{
|
||||
uint8_t result;
|
||||
|
||||
reset_cause = events;
|
||||
events &= ~(EV_BUTTON_PRESSED | EV_PROG_ENTER_TWI);
|
||||
|
||||
reset_retries = 5;
|
||||
|
||||
twi_init(1);
|
||||
result = twi_switch_application(m_twi_address, BOOTTYPE_BOOTLOADER);
|
||||
if (result == TWI_ERROR)
|
||||
{
|
||||
/* no response from target, do normal reset */
|
||||
RESET_ACTIVE();
|
||||
}
|
||||
|
||||
m_state = STATE_TWI_CHECK_BL;
|
||||
}
|
||||
#endif /* (USE_TWI_SUPPORT) */
|
||||
break;
|
||||
|
||||
case STATE_RESET_SYNC:
|
||||
@ -204,6 +245,101 @@ static void reset_statemachine(uint8_t events)
|
||||
}
|
||||
break;
|
||||
|
||||
#if (USE_TWI_SUPPORT)
|
||||
case STATE_TWI_CHECK_BL:
|
||||
if (events & EV_STATE_ENTER)
|
||||
{
|
||||
events &= ~(EV_STATE_ENTER);
|
||||
|
||||
timer = TIMER_MSEC2IRQCNT(10);
|
||||
}
|
||||
else if (events & EV_TIMEOUT)
|
||||
{
|
||||
uint8_t result;
|
||||
|
||||
events &= ~(EV_TIMEOUT);
|
||||
|
||||
/* put target in RUN mode */
|
||||
RESET_INACTIVE();
|
||||
m_led_mode = LED_ON;
|
||||
|
||||
result = twi_read_chipinfo(m_twi_address, &m_twi_chipinfo);
|
||||
if (result == TWI_SUCCESS)
|
||||
{
|
||||
#if (USE_DISPLAY)
|
||||
char twi_version[16 +1];
|
||||
|
||||
twi_read_version(m_twi_address, twi_version,
|
||||
sizeof(twi_version) -1);
|
||||
twi_version[16] = '\0';
|
||||
|
||||
display_show_string(twi_version, 0);
|
||||
|
||||
avrdevice_get_by_signature(&m_device, m_twi_chipinfo.sig);
|
||||
if (m_device.name[0] != '\0')
|
||||
{
|
||||
display_show_string(" ", 1);
|
||||
display_show_string(m_device.name, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
display_show_string(" 0X", 1);
|
||||
display_show_hex(m_twi_chipinfo.sig[0], 1);
|
||||
display_show_hex(m_twi_chipinfo.sig[1], 1);
|
||||
display_show_hex(m_twi_chipinfo.sig[2], 1);
|
||||
}
|
||||
|
||||
display_set_mode(DISPLAY_MODE_SCROLL_ONCE);
|
||||
#endif /* (USE_DISPLAY) */
|
||||
|
||||
m_state = STATE_TWI_PROGMODE;
|
||||
}
|
||||
else
|
||||
{
|
||||
reset_retries--;
|
||||
if (reset_retries > 0)
|
||||
{
|
||||
timer = TIMER_MSEC2IRQCNT(10);
|
||||
}
|
||||
else
|
||||
{
|
||||
#if (USE_DISPLAY)
|
||||
display_show_string("0x", 0);
|
||||
display_show_hex(m_twi_address, 1);
|
||||
display_show_string(":NAK", 1);
|
||||
display_set_mode(DISPLAY_MODE_SCROLL_ONCE);
|
||||
#endif /* (USE_DISPLAY) */
|
||||
|
||||
m_state = STATE_IDLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_TWI_PROGMODE:
|
||||
if (events & EV_STATE_ENTER)
|
||||
{
|
||||
events &= ~(EV_STATE_ENTER);
|
||||
|
||||
if (reset_cause == EV_BUTTON_PRESSED)
|
||||
{
|
||||
m_state = STATE_IDLE;
|
||||
}
|
||||
}
|
||||
else if (events & EV_PROG_LEAVE)
|
||||
{
|
||||
events &= ~(EV_PROG_LEAVE);
|
||||
|
||||
m_state = STATE_IDLE;
|
||||
}
|
||||
|
||||
if (m_state == STATE_IDLE)
|
||||
{
|
||||
twi_switch_application(m_twi_address, BOOTTYPE_APPLICATION);
|
||||
}
|
||||
break;
|
||||
#endif /* (USE_TWI_SUPPORT) */
|
||||
|
||||
default:
|
||||
m_state = STATE_IDLE;
|
||||
break;
|
||||
@ -380,6 +516,7 @@ static void cmd_handler_isp(uint8_t cmd)
|
||||
size |= uart_recv();
|
||||
type = uart_recv();
|
||||
|
||||
size = MIN(size, sizeof(m_page_buf));
|
||||
uart_recv_buf(m_page_buf, size);
|
||||
|
||||
if (type == 'F')
|
||||
@ -487,6 +624,124 @@ static void cmd_handler_isp(uint8_t cmd)
|
||||
} /* cmd_handler_isp */
|
||||
|
||||
|
||||
#if (USE_TWI_SUPPORT)
|
||||
static void cmd_handler_twi(uint8_t cmd)
|
||||
{
|
||||
switch (cmd)
|
||||
{
|
||||
/* Enter programming mode */
|
||||
case 'P':
|
||||
reset_statemachine_wait(EV_PROG_ENTER_TWI);
|
||||
uart_send((m_state == STATE_TWI_PROGMODE) ? '\r' : '!');
|
||||
break;
|
||||
|
||||
/* Chip erase */
|
||||
case 'e':
|
||||
uart_send('\r');
|
||||
break;
|
||||
|
||||
/* Read signature bytes */
|
||||
case 's':
|
||||
uart_send(m_twi_chipinfo.sig[2]);
|
||||
uart_send(m_twi_chipinfo.sig[1]);
|
||||
uart_send(m_twi_chipinfo.sig[0]);
|
||||
break;
|
||||
|
||||
/* Block Write */
|
||||
case 'B':
|
||||
{
|
||||
uint16_t write_pos = 0;
|
||||
uint16_t size;
|
||||
uint8_t type;
|
||||
|
||||
m_led_mode = LED_FAST;
|
||||
|
||||
size = uart_recv() << 8;
|
||||
size |= uart_recv();
|
||||
type = uart_recv();
|
||||
|
||||
size = MIN(size, sizeof(m_page_buf));
|
||||
uart_recv_buf(m_page_buf, size);
|
||||
|
||||
memset(m_page_buf + size, 0xFF, sizeof(m_page_buf) - size);
|
||||
|
||||
while (write_pos < size)
|
||||
{
|
||||
if (type == 'F')
|
||||
{
|
||||
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);
|
||||
write_pos += m_twi_chipinfo.page_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t write_size;
|
||||
|
||||
write_size = MIN(size, m_twi_chipinfo.page_size);
|
||||
|
||||
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;
|
||||
write_pos += write_size;
|
||||
}
|
||||
}
|
||||
|
||||
uart_send('\r');
|
||||
break;
|
||||
}
|
||||
|
||||
/* Block Read */
|
||||
case 'g':
|
||||
{
|
||||
uint16_t size;
|
||||
uint8_t type;
|
||||
|
||||
m_led_mode = LED_SLOW;
|
||||
|
||||
size = uart_recv() << 8;
|
||||
size |= uart_recv();
|
||||
type = uart_recv();
|
||||
|
||||
size = MIN(size, sizeof(m_page_buf));
|
||||
|
||||
if (type == 'F')
|
||||
{
|
||||
twi_read_memory(m_twi_address, MEMTYPE_FLASH,
|
||||
(m_address << 1),
|
||||
m_page_buf, size);
|
||||
|
||||
m_address += (size >> 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
twi_read_memory(m_twi_address, MEMTYPE_EEPROM,
|
||||
m_address,
|
||||
m_page_buf, size);
|
||||
|
||||
m_address += size;
|
||||
}
|
||||
|
||||
uart_send_buf(m_page_buf, size);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
uart_send('?');
|
||||
break;
|
||||
}
|
||||
} /* cmd_handler_twi */
|
||||
#endif /* (USE_TWI_SUPPORT) */
|
||||
|
||||
|
||||
static void cmdloop(void) __attribute__ ((noreturn));
|
||||
static void cmdloop(void)
|
||||
{
|
||||
@ -596,12 +851,67 @@ static void cmdloop(void)
|
||||
uart_send(sizeof(m_page_buf) & 0xFF);
|
||||
break;
|
||||
|
||||
#if (USE_TWI_SUPPORT)
|
||||
case 'I':
|
||||
m_twi_address = uart_recv() & 0x7F;
|
||||
|
||||
if (m_twi_address != 0x00)
|
||||
{
|
||||
reset_statemachine_wait(EV_PROG_ENTER_TWI);
|
||||
if (m_state == STATE_TWI_PROGMODE)
|
||||
{
|
||||
uart_send('\r');
|
||||
}
|
||||
else
|
||||
{
|
||||
m_twi_address = 0x00;
|
||||
uart_send('!');
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uart_send('\r');
|
||||
}
|
||||
break;
|
||||
|
||||
case 'i':
|
||||
{
|
||||
uint8_t twi_addr;
|
||||
uint8_t write_size;
|
||||
uint8_t read_size;
|
||||
uint8_t result;
|
||||
|
||||
twi_addr = uart_recv();
|
||||
write_size = uart_recv();
|
||||
read_size = uart_recv();
|
||||
|
||||
uart_recv_buf(m_page_buf, write_size);
|
||||
|
||||
result = twi_generic(twi_addr,
|
||||
m_page_buf, write_size,
|
||||
m_page_buf, read_size);
|
||||
|
||||
uart_send_buf(m_page_buf, read_size);
|
||||
|
||||
uart_send((result == TWI_SUCCESS) ? '\r' : '!');
|
||||
}
|
||||
#endif /* (USE_TWI_SUPPORT) */
|
||||
|
||||
/* ESC */
|
||||
case 0x1B:
|
||||
break;
|
||||
|
||||
default:
|
||||
#if (USE_TWI_SUPPORT)
|
||||
if (m_twi_address != 0x00)
|
||||
{
|
||||
cmd_handler_twi(cmd);
|
||||
}
|
||||
else
|
||||
#endif /* (USE_TWI_SUPPORT) */
|
||||
{
|
||||
cmd_handler_isp(cmd);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -683,6 +993,10 @@ int main(void)
|
||||
|
||||
spi_init(0);
|
||||
|
||||
#if (USE_TWI_SUPPORT)
|
||||
twi_init(0);
|
||||
#endif
|
||||
|
||||
TIMER_INIT();
|
||||
|
||||
/* init statemachine */
|
||||
|
3
target.h
3
target.h
@ -34,6 +34,7 @@
|
||||
#define ISP_CHECK() (PIND & (1<<RESET_IN))
|
||||
|
||||
#define USE_DISPLAY 0
|
||||
#define USE_TWI_SUPPORT 0
|
||||
|
||||
#define TIMER_DIVISOR 1024
|
||||
#define TIMER_INIT() { /* timer0, FCPU/1024, overflow interrupt */ \
|
||||
@ -95,6 +96,8 @@
|
||||
#define DISP_D5 PORTD6
|
||||
#define DISP_D6 PORTD7
|
||||
|
||||
#define USE_TWI_SUPPORT 1
|
||||
|
||||
#define TIMER_DIVISOR 1024
|
||||
#define TIMER_INIT() { /* timer0, FCPU/1024, overflow interrupt */ \
|
||||
TCCR0B = (1<<CS02) | (1<<CS00); \
|
||||
|
286
twi_master.c
Normal file
286
twi_master.c
Normal file
@ -0,0 +1,286 @@
|
||||
/***************************************************************************
|
||||
* 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 <avr/io.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "target.h"
|
||||
#include "twi_master.h"
|
||||
|
||||
#if (USE_TWI_SUPPORT)
|
||||
|
||||
#define TWI_SLA_W(addr) (addr << 1)
|
||||
#define TWI_SLA_R(addr) ((addr << 1) | 0x01)
|
||||
|
||||
|
||||
/* ***********************************************************************
|
||||
* twi_start
|
||||
* *********************************************************************** */
|
||||
static uint8_t twi_start(void)
|
||||
{
|
||||
TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
|
||||
loop_until_bit_is_set(TWCR, TWINT);
|
||||
|
||||
switch (TWSR & 0xF8)
|
||||
{
|
||||
case 0x08: /* START transmitted */
|
||||
case 0x10: /* repeated START transmitted */
|
||||
return TWI_SUCCESS;
|
||||
|
||||
default:
|
||||
return TWI_ERROR;
|
||||
}
|
||||
} /* twi_start */
|
||||
|
||||
|
||||
/* ***********************************************************************
|
||||
* twi_stop
|
||||
* *********************************************************************** */
|
||||
static void twi_stop(void)
|
||||
{
|
||||
TWCR = (1<<TWINT) | (1<<TWSTO) | (1<<TWEN);
|
||||
} /* twi_stop */
|
||||
|
||||
|
||||
/* ***********************************************************************
|
||||
* twi_master_tx
|
||||
* *********************************************************************** */
|
||||
static uint8_t twi_master_tx(uint8_t value)
|
||||
{
|
||||
TWDR = value;
|
||||
TWCR = (1<<TWINT) | (1<<TWEN);
|
||||
loop_until_bit_is_set(TWCR, TWINT);
|
||||
|
||||
switch (TWSR & 0xF8)
|
||||
{
|
||||
case 0x18: /* SLA+W transmitted, ACK received */
|
||||
case 0x28: /* Data transmitted, ACK received */
|
||||
case 0x40: /* SLA+R transmitted, ACK received */
|
||||
return TWI_SUCCESS;
|
||||
|
||||
default:
|
||||
return TWI_ERROR;
|
||||
}
|
||||
} /* twi_master_tx */
|
||||
|
||||
|
||||
/* ***********************************************************************
|
||||
* twi_master_rx
|
||||
* *********************************************************************** */
|
||||
static uint8_t twi_master_rx(uint8_t * p_value, uint8_t ack)
|
||||
{
|
||||
TWCR = (1<<TWINT) | (1<<TWEN) | ((ack) ? (1<<TWEA) : 0x00);
|
||||
loop_until_bit_is_set(TWCR, TWINT);
|
||||
*p_value = TWDR;
|
||||
|
||||
switch (TWSR & 0xF8)
|
||||
{
|
||||
case 0x50: /* Data received, ACK returned */
|
||||
case 0x58: /* Data received, NAK returned */
|
||||
return TWI_SUCCESS;
|
||||
|
||||
default:
|
||||
return TWI_ERROR;
|
||||
}
|
||||
} /* twi_master_rx */
|
||||
|
||||
|
||||
/* ***********************************************************************
|
||||
* twi_master_start
|
||||
* *********************************************************************** */
|
||||
static uint8_t twi_master_start(uint8_t twi_addr)
|
||||
{
|
||||
if (twi_start() == TWI_SUCCESS)
|
||||
{
|
||||
if (twi_master_tx(twi_addr) == TWI_SUCCESS)
|
||||
{
|
||||
return TWI_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
twi_stop();
|
||||
return TWI_ERROR;
|
||||
} /* twi_master_start */
|
||||
|
||||
|
||||
/* ***********************************************************************
|
||||
* twi_generic
|
||||
* *********************************************************************** */
|
||||
uint8_t twi_generic(uint8_t twi_addr,
|
||||
const uint8_t * p_wr_data, uint16_t write_size,
|
||||
uint8_t * p_rd_data, uint16_t read_size)
|
||||
{
|
||||
uint8_t result = TWI_ERROR;
|
||||
|
||||
if (write_size > 0)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((read_size > 0) &&
|
||||
(result == TWI_SUCCESS)
|
||||
)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
twi_stop();
|
||||
return result;
|
||||
} /* twi_generic */
|
||||
|
||||
|
||||
/* ***********************************************************************
|
||||
* twi_switch_application
|
||||
* *********************************************************************** */
|
||||
uint8_t twi_switch_application(uint8_t twi_addr, uint8_t app)
|
||||
{
|
||||
uint8_t cmd[2] = { CMD_SWITCH_APPLICATION, app };
|
||||
|
||||
return twi_generic(twi_addr, cmd, sizeof(cmd), NULL, 0);
|
||||
} /* twi_switch_application */
|
||||
|
||||
|
||||
/* ***********************************************************************
|
||||
* twi_read_version
|
||||
* *********************************************************************** */
|
||||
uint8_t twi_read_version(uint8_t twi_addr, char * p_version,
|
||||
uint8_t version_length)
|
||||
{
|
||||
uint8_t cmd[1] = { CMD_READ_VERSION };
|
||||
|
||||
return twi_generic(twi_addr, cmd, sizeof(cmd),
|
||||
(uint8_t *)p_version, version_length);
|
||||
} /* twi_read_version */
|
||||
|
||||
|
||||
/* ***********************************************************************
|
||||
* twi_read_chipinfo
|
||||
* *********************************************************************** */
|
||||
uint8_t twi_read_chipinfo(uint8_t twi_addr, twi_chipinfo_t * p_chipinfo)
|
||||
{
|
||||
uint8_t cmd[4] = { CMD_READ_MEMORY, MEMTYPE_CHIPINFO, 0x00, 0x00 };
|
||||
|
||||
return twi_generic(twi_addr, cmd, sizeof(cmd),
|
||||
(uint8_t *)p_chipinfo, sizeof(twi_chipinfo_t));
|
||||
} /* twi_read_chipinfo */
|
||||
|
||||
|
||||
/* ***********************************************************************
|
||||
* twi_read_memory
|
||||
* *********************************************************************** */
|
||||
uint8_t twi_read_memory(uint8_t twi_addr, uint8_t memory_type, uint16_t memory_addr,
|
||||
uint8_t * p_data, uint16_t data_length)
|
||||
{
|
||||
uint8_t cmd[4] = { CMD_READ_MEMORY, memory_type,
|
||||
(memory_addr >> 8) & 0xFF,
|
||||
(memory_addr & 0xFF) };
|
||||
|
||||
return twi_generic(twi_addr, cmd, sizeof(cmd), p_data, data_length);
|
||||
} /* twi_read_memory */
|
||||
|
||||
|
||||
/* ***********************************************************************
|
||||
* twi_write_memory
|
||||
* *********************************************************************** */
|
||||
uint8_t twi_write_memory(uint8_t twi_addr, uint8_t memory_type, uint16_t memory_addr,
|
||||
const uint8_t * p_data, uint16_t data_length)
|
||||
{
|
||||
uint8_t cmd[4] = { CMD_WRITE_MEMORY, memory_type,
|
||||
(memory_addr >> 8) & 0xFF,
|
||||
(memory_addr & 0xFF) };
|
||||
uint8_t result;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
twi_stop();
|
||||
return result;
|
||||
} /* twi_read_memory */
|
||||
|
||||
|
||||
/* ***********************************************************************
|
||||
* twi_init
|
||||
* *********************************************************************** */
|
||||
void twi_init(uint8_t enable)
|
||||
{
|
||||
if (enable)
|
||||
{
|
||||
TWBR = ((F_CPU / 100000) -16) / 2;
|
||||
TWCR = (1<<TWSTO) | (1<<TWEN);
|
||||
}
|
||||
else
|
||||
{
|
||||
TWCR = 0x00;
|
||||
}
|
||||
} /* twi_init */
|
||||
#endif /* (USE_TWI_SUPPORT) */
|
62
twi_master.h
Normal file
62
twi_master.h
Normal file
@ -0,0 +1,62 @@
|
||||
#ifndef TWI_MASTER_H_
|
||||
#define TWI_MASTER_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* *********************************************************************** */
|
||||
|
||||
/* SLA+R */
|
||||
#define CMD_WAIT 0x00
|
||||
#define CMD_READ_VERSION 0x01
|
||||
#define CMD_READ_MEMORY 0x02
|
||||
|
||||
/* SLA+W */
|
||||
#define CMD_SWITCH_APPLICATION CMD_READ_VERSION
|
||||
#define CMD_WRITE_MEMORY CMD_READ_MEMORY
|
||||
|
||||
/* CMD_SWITCH_APPLICATION parameter */
|
||||
#define BOOTTYPE_BOOTLOADER 0x00
|
||||
#define BOOTTYPE_APPLICATION 0x80
|
||||
|
||||
/* CMD_{READ|WRITE}_* parameter */
|
||||
#define MEMTYPE_CHIPINFO 0x00
|
||||
#define MEMTYPE_FLASH 0x01
|
||||
#define MEMTYPE_EEPROM 0x02
|
||||
|
||||
#define TWI_SUCCESS 0x00
|
||||
#define TWI_ERROR 0x01
|
||||
|
||||
typedef struct twi_chipinfo_s
|
||||
{
|
||||
uint8_t sig[3];
|
||||
uint8_t page_size;
|
||||
uint16_t flash_size;
|
||||
uint16_t eeprom_size;
|
||||
} twi_chipinfo_t;
|
||||
|
||||
/* *********************************************************************** */
|
||||
|
||||
uint8_t twi_generic (uint8_t twi_addr,
|
||||
const uint8_t * p_wr_data, uint16_t write_size,
|
||||
uint8_t * p_rd_data, uint16_t read_size);
|
||||
|
||||
uint8_t twi_switch_application (uint8_t addr, uint8_t app);
|
||||
|
||||
uint8_t twi_read_version (uint8_t addr, char * p_version,
|
||||
uint8_t version_length);
|
||||
|
||||
uint8_t twi_read_chipinfo (uint8_t addr, twi_chipinfo_t * p_chipinfo);
|
||||
|
||||
uint8_t twi_read_memory (uint8_t twi_addr, uint8_t memory_type,
|
||||
uint16_t memory_addr,
|
||||
uint8_t * p_data, uint16_t data_length);
|
||||
|
||||
uint8_t twi_write_memory (uint8_t twi_addr, uint8_t memory_type,
|
||||
uint16_t memory_addr,
|
||||
const uint8_t * p_data, uint16_t data_length);
|
||||
|
||||
void twi_init (uint8_t enable);
|
||||
|
||||
/* *********************************************************************** */
|
||||
|
||||
#endif /* TWI_MASTER_H_ */
|
12
uart.c
12
uart.c
@ -66,6 +66,18 @@ uint8_t uart_rx_ready(void)
|
||||
} /* uart_rx_ready */
|
||||
|
||||
|
||||
/* ***********************************************************************
|
||||
* uart_send_buf
|
||||
* *********************************************************************** */
|
||||
void uart_send_buf(const uint8_t * p_data, uint16_t data_length)
|
||||
{
|
||||
while (data_length--)
|
||||
{
|
||||
uart_send(*p_data++);
|
||||
}
|
||||
} /* uart_send_buf */
|
||||
|
||||
|
||||
/* ***********************************************************************
|
||||
* uart_recv_buf
|
||||
* *********************************************************************** */
|
||||
|
Loading…
Reference in New Issue
Block a user