Do not rely on Clockstretching for writes
This commit is contained in:
parent
5bdbb430e7
commit
964c933bf3
24
README.md
24
README.md
@ -10,10 +10,10 @@ Currently the following AVR MCUs are supported:
|
|||||||
|
|
||||||
AVR MCU | Flash bytes used (.text + .data) | Bootloader region size
|
AVR MCU | Flash bytes used (.text + .data) | Bootloader region size
|
||||||
--- | --- | ---
|
--- | --- | ---
|
||||||
atmega8 | 718 (0x2CE) | 512 words
|
atmega8 | 802 (0x322) | 512 words
|
||||||
atmega88 | 740 (0x2E4) | 512 words
|
atmega88 | 826 (0x33A) | 512 words
|
||||||
atmega168 | 740 (0x2E4) | 512 words
|
atmega168 | 826 (0x33A) | 512 words
|
||||||
atmega328p | 740 (0x2E4) | 512 words
|
atmega328p | 826 (0x33A) | 512 words
|
||||||
|
|
||||||
(Compiled on Ubuntu 18.04 LTS (gcc 5.4.0 / avr-libc 2.0.0) with EEPROM and LED support)
|
(Compiled on Ubuntu 18.04 LTS (gcc 5.4.0 / avr-libc 2.0.0) with EEPROM and LED support)
|
||||||
|
|
||||||
@ -74,7 +74,7 @@ Read chip info | **SLA+W**, 0x02, 0x00, 0x00, 0x00, **SLA+R**, {8 bytes}, **STO*
|
|||||||
Read 1+ flash bytes | **SLA+W**, 0x02, 0x01, addrh, addrl, **SLA+R**, {* bytes}, **STO** |
|
Read 1+ flash bytes | **SLA+W**, 0x02, 0x01, addrh, addrl, **SLA+R**, {* bytes}, **STO** |
|
||||||
Read 1+ eeprom bytes | **SLA+W**, 0x02, 0x02, addrh, addrl, **SLA+R**, {* bytes}, **STO** |
|
Read 1+ eeprom bytes | **SLA+W**, 0x02, 0x02, addrh, addrl, **SLA+R**, {* bytes}, **STO** |
|
||||||
Write one flash page | **SLA+W**, 0x02, 0x01, addrh, addrl, {* bytes}, **STO** | page size as indicated in chip info
|
Write one flash page | **SLA+W**, 0x02, 0x01, addrh, addrl, {* bytes}, **STO** | page size as indicated in chip info
|
||||||
Write 1+ eeprom bytes | **SLA+W**, 0x02, 0x02, addrh, addrl, {* bytes}, **STO** |
|
Write 1+ eeprom bytes | **SLA+W**, 0x02, 0x02, addrh, addrl, {* bytes}, **STO** | write 0 < n < page size bytes at once
|
||||||
|
|
||||||
**SLA+R** means Start Condition, Slave Address, Read Access
|
**SLA+R** means Start Condition, Slave Address, Read Access
|
||||||
|
|
||||||
@ -82,16 +82,28 @@ Write 1+ eeprom bytes | **SLA+W**, 0x02, 0x02, addrh, addrl, {* bytes}, **STO**
|
|||||||
|
|
||||||
**STO** means Stop Condition
|
**STO** means Stop Condition
|
||||||
|
|
||||||
|
A flash page / eeprom write is only triggered after the Stop Condition.
|
||||||
|
During the write process twiboot will NOT acknowledge its slave address.
|
||||||
|
|
||||||
The multiboot_tool repository contains a simple linux application that uses
|
The multiboot_tool repository contains a simple linux application that uses
|
||||||
this protocol to access the bootloader over linux i2c device.
|
this protocol to access the bootloader over linux i2c device.
|
||||||
|
|
||||||
The ispprog programming adapter can also be used as a avr910/butterfly to twiboot protocol bridge.
|
The ispprog programming adapter can also be used as a avr910/butterfly to twiboot protocol bridge.
|
||||||
|
|
||||||
|
|
||||||
|
## TWI/I2C Clockstretching ##
|
||||||
|
While a write is in progress twiboot will not respond on the TWI/I2C bus and the
|
||||||
|
TWI/I2C master needs to retry/poll the slave address until the write has completed.
|
||||||
|
|
||||||
|
As a compile time option (USE_CLOCKSTRETCH) the previous behavior of twiboot can be restored:
|
||||||
|
TWI/I2C Clockstretching is then used to inform the master of the duration of the write.
|
||||||
|
Please note that there are some TWI/I2C masters that do not support clockstretching.
|
||||||
|
|
||||||
|
|
||||||
## Development ##
|
## Development ##
|
||||||
Issue reports, feature requests, patches or simply success stories are much appreciated.
|
Issue reports, feature requests, patches or simply success stories are much appreciated.
|
||||||
|
|
||||||
|
|
||||||
## Roadmap ##
|
## Roadmap ##
|
||||||
Some ideas that I want to investigate / implement in twiboot:
|
Some ideas that I want to investigate / implement in twiboot:
|
||||||
- find a way to not rely on TWI clock stretching during write access
|
|
||||||
- support AVR TINYs (USI peripheral, no bootloader fuse, no Read-While-Write flash)
|
- support AVR TINYs (USI peripheral, no bootloader fuse, no Read-While-Write flash)
|
||||||
|
70
main.c
70
main.c
@ -24,6 +24,7 @@
|
|||||||
#define VERSION_STRING "TWIBOOT v2.1"
|
#define VERSION_STRING "TWIBOOT v2.1"
|
||||||
#define EEPROM_SUPPORT 1
|
#define EEPROM_SUPPORT 1
|
||||||
#define LED_SUPPORT 1
|
#define LED_SUPPORT 1
|
||||||
|
#define USE_CLOCKSTRETCH 0
|
||||||
|
|
||||||
#define F_CPU 8000000ULL
|
#define F_CPU 8000000ULL
|
||||||
#define TIMER_DIVISOR 1024
|
#define TIMER_DIVISOR 1024
|
||||||
@ -63,6 +64,8 @@
|
|||||||
#define CMD_ACCESS_CHIPINFO (0x10 | CMD_ACCESS_MEMORY)
|
#define CMD_ACCESS_CHIPINFO (0x10 | CMD_ACCESS_MEMORY)
|
||||||
#define CMD_ACCESS_FLASH (0x20 | CMD_ACCESS_MEMORY)
|
#define CMD_ACCESS_FLASH (0x20 | CMD_ACCESS_MEMORY)
|
||||||
#define CMD_ACCESS_EEPROM (0x30 | CMD_ACCESS_MEMORY)
|
#define CMD_ACCESS_EEPROM (0x30 | CMD_ACCESS_MEMORY)
|
||||||
|
#define CMD_WRITE_FLASH_PAGE (0x40 | CMD_ACCESS_MEMORY)
|
||||||
|
#define CMD_WRITE_EEPROM_PAGE (0x50 | CMD_ACCESS_MEMORY)
|
||||||
|
|
||||||
/* SLA+W */
|
/* SLA+W */
|
||||||
#define CMD_SWITCH_APPLICATION CMD_READ_VERSION
|
#define CMD_SWITCH_APPLICATION CMD_READ_VERSION
|
||||||
@ -198,6 +201,22 @@ static void write_eeprom_byte(uint8_t val)
|
|||||||
|
|
||||||
eeprom_busy_wait();
|
eeprom_busy_wait();
|
||||||
} /* write_eeprom_byte */
|
} /* write_eeprom_byte */
|
||||||
|
|
||||||
|
|
||||||
|
#if (USE_CLOCKSTRETCH == 0)
|
||||||
|
/* *************************************************************************
|
||||||
|
* write_eeprom_buffer
|
||||||
|
* ************************************************************************* */
|
||||||
|
static void write_eeprom_buffer(uint8_t size)
|
||||||
|
{
|
||||||
|
uint8_t *p = buf;
|
||||||
|
|
||||||
|
while (size--)
|
||||||
|
{
|
||||||
|
write_eeprom_byte(*p++);
|
||||||
|
}
|
||||||
|
} /* write_eeprom_buffer */
|
||||||
|
#endif /* (USE_CLOCKSTRETCH == 0) */
|
||||||
#endif /* EEPROM_SUPPORT */
|
#endif /* EEPROM_SUPPORT */
|
||||||
|
|
||||||
|
|
||||||
@ -279,6 +298,19 @@ static uint8_t TWI_data_write(uint8_t bcnt, uint8_t data)
|
|||||||
default:
|
default:
|
||||||
switch (cmd)
|
switch (cmd)
|
||||||
{
|
{
|
||||||
|
#if (EEPROM_SUPPORT)
|
||||||
|
#if (USE_CLOCKSTRETCH)
|
||||||
|
case CMD_ACCESS_EEPROM:
|
||||||
|
write_eeprom_byte(data);
|
||||||
|
break;
|
||||||
|
#else
|
||||||
|
case CMD_ACCESS_EEPROM:
|
||||||
|
cmd = CMD_WRITE_EEPROM_PAGE;
|
||||||
|
/* fall through */
|
||||||
|
|
||||||
|
case CMD_WRITE_EEPROM_PAGE:
|
||||||
|
#endif /* (USE_CLOCKSTRETCH) */
|
||||||
|
#endif /* (EEPROM_SUPPORT) */
|
||||||
case CMD_ACCESS_FLASH:
|
case CMD_ACCESS_FLASH:
|
||||||
{
|
{
|
||||||
uint8_t pos = bcnt -4;
|
uint8_t pos = bcnt -4;
|
||||||
@ -289,19 +321,19 @@ static uint8_t TWI_data_write(uint8_t bcnt, uint8_t data)
|
|||||||
ack = 0x00;
|
ack = 0x00;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pos >= (sizeof(buf) -1))
|
if ((cmd == CMD_ACCESS_FLASH) &&
|
||||||
|
(pos >= (sizeof(buf) -1))
|
||||||
|
)
|
||||||
{
|
{
|
||||||
|
#if (USE_CLOCKSTRETCH)
|
||||||
write_flash_page();
|
write_flash_page();
|
||||||
|
#else
|
||||||
|
cmd = CMD_WRITE_FLASH_PAGE;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if (EEPROM_SUPPORT)
|
|
||||||
case CMD_ACCESS_EEPROM:
|
|
||||||
write_eeprom_byte(data);
|
|
||||||
break;
|
|
||||||
#endif /* (EEPROM_SUPPORT) */
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ack = 0x00;
|
ack = 0x00;
|
||||||
break;
|
break;
|
||||||
@ -392,6 +424,30 @@ static void TWI_vect(void)
|
|||||||
|
|
||||||
/* STOP or repeated START -> IDLE */
|
/* STOP or repeated START -> IDLE */
|
||||||
case 0xA0:
|
case 0xA0:
|
||||||
|
#if (USE_CLOCKSTRETCH == 0)
|
||||||
|
if ((cmd == CMD_WRITE_FLASH_PAGE)
|
||||||
|
#if (EEPROM_SUPPORT)
|
||||||
|
|| (cmd == CMD_WRITE_EEPROM_PAGE)
|
||||||
|
#endif
|
||||||
|
)
|
||||||
|
{
|
||||||
|
/* disable ACK for now, re-enable after page write */
|
||||||
|
control &= ~(1<<TWEA);
|
||||||
|
TWCR = (1<<TWINT) | control;
|
||||||
|
|
||||||
|
#if (EEPROM_SUPPORT)
|
||||||
|
if (cmd == CMD_WRITE_EEPROM_PAGE)
|
||||||
|
{
|
||||||
|
write_eeprom_buffer(bcnt -4);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif /* (EEPROM_SUPPORT) */
|
||||||
|
{
|
||||||
|
write_flash_page();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* (USE_CLOCKSTRETCH) */
|
||||||
|
|
||||||
bcnt = 0;
|
bcnt = 0;
|
||||||
/* fall through */
|
/* fall through */
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user