Add twiboot bridge
This commit is contained in:
parent
cfef6e9a72
commit
144016f65d
@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
#if (USE_DISPLAY)
|
#if (USE_DISPLAY)
|
||||||
static display_mode_t m_mode = DISPLAY_MODE_OFF;
|
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_length = 0;
|
||||||
static uint8_t m_buffer_pos = 0;
|
static uint8_t m_buffer_pos = 0;
|
||||||
|
|
||||||
|
322
ispprog.c
322
ispprog.c
@ -26,8 +26,11 @@
|
|||||||
#include "display.h"
|
#include "display.h"
|
||||||
#include "spi_isp.h"
|
#include "spi_isp.h"
|
||||||
#include "target.h"
|
#include "target.h"
|
||||||
|
#include "twi_master.h"
|
||||||
#include "uart.h"
|
#include "uart.h"
|
||||||
|
|
||||||
|
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
|
||||||
|
|
||||||
#define TIMER_IRQFREQ_MS 10
|
#define TIMER_IRQFREQ_MS 10
|
||||||
|
|
||||||
/* convert milliseconds to timer ticks */
|
/* convert milliseconds to timer ticks */
|
||||||
@ -41,12 +44,14 @@
|
|||||||
#define EV_TIMEOUT 0x08
|
#define EV_TIMEOUT 0x08
|
||||||
#define EV_PROG_ENTER 0x10
|
#define EV_PROG_ENTER 0x10
|
||||||
#define EV_PROG_LEAVE 0x20
|
#define EV_PROG_LEAVE 0x20
|
||||||
|
#define EV_PROG_ENTER_TWI 0x40
|
||||||
|
|
||||||
#define STATE_IDLE 0x00 /* nothing */
|
#define STATE_IDLE 0x00 /* nothing */
|
||||||
#define STATE_RESET_SYNC 0x01
|
#define STATE_RESET_SYNC 0x01
|
||||||
#define STATE_RESET_RETRY 0x02
|
#define STATE_RESET_RETRY 0x02
|
||||||
#define STATE_RESET_PROGMODE 0x03
|
#define STATE_RESET_PROGMODE 0x03
|
||||||
|
#define STATE_TWI_CHECK_BL 0x04
|
||||||
|
#define STATE_TWI_PROGMODE 0x05
|
||||||
|
|
||||||
#define LED_OFF 0x00
|
#define LED_OFF 0x00
|
||||||
#define LED_SLOW 0x20
|
#define LED_SLOW 0x20
|
||||||
@ -63,6 +68,11 @@ static uint8_t m_page_buf[256];
|
|||||||
static avr_device_t m_device;
|
static avr_device_t m_device;
|
||||||
static uint16_t m_address = 0x0000;
|
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)
|
static void reset_statemachine(uint8_t events)
|
||||||
{
|
{
|
||||||
@ -105,12 +115,20 @@ static void reset_statemachine(uint8_t events)
|
|||||||
timer = TIMER_MSEC2IRQCNT(0);
|
timer = TIMER_MSEC2IRQCNT(0);
|
||||||
|
|
||||||
spi_init(0);
|
spi_init(0);
|
||||||
|
#if (USE_TWI_SUPPORT)
|
||||||
|
twi_init(0);
|
||||||
|
#endif
|
||||||
/* put device in RUN mode */
|
/* put device in RUN mode */
|
||||||
RESET_INACTIVE();
|
RESET_INACTIVE();
|
||||||
m_led_mode = LED_OFF;
|
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;
|
reset_cause = events;
|
||||||
events &= ~(EV_BUTTON_PRESSED | EV_PROG_ENTER);
|
events &= ~(EV_BUTTON_PRESSED | EV_PROG_ENTER);
|
||||||
@ -122,6 +140,29 @@ static void reset_statemachine(uint8_t events)
|
|||||||
|
|
||||||
m_state = STATE_RESET_SYNC;
|
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;
|
break;
|
||||||
|
|
||||||
case STATE_RESET_SYNC:
|
case STATE_RESET_SYNC:
|
||||||
@ -204,6 +245,101 @@ static void reset_statemachine(uint8_t events)
|
|||||||
}
|
}
|
||||||
break;
|
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:
|
default:
|
||||||
m_state = STATE_IDLE;
|
m_state = STATE_IDLE;
|
||||||
break;
|
break;
|
||||||
@ -380,6 +516,7 @@ static void cmd_handler_isp(uint8_t cmd)
|
|||||||
size |= uart_recv();
|
size |= uart_recv();
|
||||||
type = uart_recv();
|
type = uart_recv();
|
||||||
|
|
||||||
|
size = MIN(size, sizeof(m_page_buf));
|
||||||
uart_recv_buf(m_page_buf, size);
|
uart_recv_buf(m_page_buf, size);
|
||||||
|
|
||||||
if (type == 'F')
|
if (type == 'F')
|
||||||
@ -487,6 +624,124 @@ static void cmd_handler_isp(uint8_t cmd)
|
|||||||
} /* cmd_handler_isp */
|
} /* 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) __attribute__ ((noreturn));
|
||||||
static void cmdloop(void)
|
static void cmdloop(void)
|
||||||
{
|
{
|
||||||
@ -596,12 +851,67 @@ static void cmdloop(void)
|
|||||||
uart_send(sizeof(m_page_buf) & 0xFF);
|
uart_send(sizeof(m_page_buf) & 0xFF);
|
||||||
break;
|
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 */
|
/* ESC */
|
||||||
case 0x1B:
|
case 0x1B:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
cmd_handler_isp(cmd);
|
#if (USE_TWI_SUPPORT)
|
||||||
|
if (m_twi_address != 0x00)
|
||||||
|
{
|
||||||
|
cmd_handler_twi(cmd);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif /* (USE_TWI_SUPPORT) */
|
||||||
|
{
|
||||||
|
cmd_handler_isp(cmd);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -683,6 +993,10 @@ int main(void)
|
|||||||
|
|
||||||
spi_init(0);
|
spi_init(0);
|
||||||
|
|
||||||
|
#if (USE_TWI_SUPPORT)
|
||||||
|
twi_init(0);
|
||||||
|
#endif
|
||||||
|
|
||||||
TIMER_INIT();
|
TIMER_INIT();
|
||||||
|
|
||||||
/* init statemachine */
|
/* init statemachine */
|
||||||
|
3
target.h
3
target.h
@ -34,6 +34,7 @@
|
|||||||
#define ISP_CHECK() (PIND & (1<<RESET_IN))
|
#define ISP_CHECK() (PIND & (1<<RESET_IN))
|
||||||
|
|
||||||
#define USE_DISPLAY 0
|
#define USE_DISPLAY 0
|
||||||
|
#define USE_TWI_SUPPORT 0
|
||||||
|
|
||||||
#define TIMER_DIVISOR 1024
|
#define TIMER_DIVISOR 1024
|
||||||
#define TIMER_INIT() { /* timer0, FCPU/1024, overflow interrupt */ \
|
#define TIMER_INIT() { /* timer0, FCPU/1024, overflow interrupt */ \
|
||||||
@ -95,6 +96,8 @@
|
|||||||
#define DISP_D5 PORTD6
|
#define DISP_D5 PORTD6
|
||||||
#define DISP_D6 PORTD7
|
#define DISP_D6 PORTD7
|
||||||
|
|
||||||
|
#define USE_TWI_SUPPORT 1
|
||||||
|
|
||||||
#define TIMER_DIVISOR 1024
|
#define TIMER_DIVISOR 1024
|
||||||
#define TIMER_INIT() { /* timer0, FCPU/1024, overflow interrupt */ \
|
#define TIMER_INIT() { /* timer0, FCPU/1024, overflow interrupt */ \
|
||||||
TCCR0B = (1<<CS02) | (1<<CS00); \
|
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_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
|
* uart_recv_buf
|
||||||
* *********************************************************************** */
|
* *********************************************************************** */
|
||||||
|
1
uart.h
1
uart.h
@ -9,6 +9,7 @@ void uart_send (uint8_t data);
|
|||||||
uint8_t uart_recv (void);
|
uint8_t uart_recv (void);
|
||||||
uint8_t uart_rx_ready (void);
|
uint8_t uart_rx_ready (void);
|
||||||
|
|
||||||
|
void uart_send_buf (const uint8_t * p_data, uint16_t data_length);
|
||||||
void uart_recv_buf (uint8_t * p_data, uint16_t data_length);
|
void uart_recv_buf (uint8_t * p_data, uint16_t data_length);
|
||||||
|
|
||||||
void uart_init (void);
|
void uart_init (void);
|
||||||
|
Loading…
Reference in New Issue
Block a user