Fix C2 programmer, incorrect initialization could brick EFM8 MCUs

This commit is contained in:
halfbakery 2020-09-15 21:49:03 +02:00
parent f7ae554394
commit 1418af3f31
3 changed files with 31 additions and 4 deletions

View File

@ -204,13 +204,33 @@ uint8_t c2_reset() {
return C2_SUCCESS; return C2_SUCCESS;
} }
uint8_t c2_programming_init() { uint8_t c2_programming_init(uint8_t devid) {
c2_reset(); c2_reset();
c2_address_write(C2FPCTL); c2_address_write(C2FPCTL);
C2_DATA_WRITE_AND_CHECK(C2FPCTL_ENABLE0, 1); C2_DATA_WRITE_AND_CHECK(C2FPCTL_ENABLE0, 1);
C2_DATA_WRITE_AND_CHECK(C2FPCTL_CORE_HALT, 1); C2_DATA_WRITE_AND_CHECK(C2FPCTL_CORE_HALT, 1);
C2_DATA_WRITE_AND_CHECK(C2FPCTL_ENABLE1, 1) C2_DATA_WRITE_AND_CHECK(C2FPCTL_ENABLE1, 1)
C2_DELAY_MS(21); C2_DELAY_MS(21);
// device specific initialization, see https://www.silabs.com/documents/public/application-notes/AN127.pdf
switch (devid) {
case C2_DEVID_UNKNOWN:
break;
case C2_DEVID_EFM8BB1:
case C2_DEVID_EFM8BB2:
case C2_DEVID_EFM8BB3: // C2_DEVID_EFM8LB1 is the same
c2_address_write(0xFF);
C2_DATA_WRITE_AND_CHECK(0x80, 1);
C2_DELAY_US(5);
c2_address_write(0xEF);
C2_DATA_WRITE_AND_CHECK(0x02, 1);
c2_address_write(0xA9);
C2_DATA_WRITE_AND_CHECK(0x00, 1);
break;
default:
return C2_BROKEN_LINK;
}
return C2_SUCCESS; return C2_SUCCESS;
} }

View File

@ -103,6 +103,13 @@ inline void C2D_enable(bool oe) {
#define C2_INBUSY 0x02 #define C2_INBUSY 0x02
#define C2_OUTREADY 0x01 #define C2_OUTREADY 0x01
// Device families (https://www.silabs.com/documents/public/application-notes/AN127.pdf)
#define C2_DEVID_UNKNOWN 0x00
#define C2_DEVID_EFM8BB1 0x30
#define C2_DEVID_EFM8BB2 0x32
#define C2_DEVID_EFM8BB3 0x34
#define C2_DEVID_EFM8LB1 0x34
// Layer 1: C2 Programmig Interface (PI) Register access // Layer 1: C2 Programmig Interface (PI) Register access
void c2_address_write(uint8_t address); void c2_address_write(uint8_t address);
uint8_t c2_address_read(); uint8_t c2_address_read();
@ -125,7 +132,7 @@ inline uint8_t c2_data_read(uint8_t &d, uint8_t bytes=1) {
// Layer 2: Operations // Layer 2: Operations
uint8_t c2_reset(); uint8_t c2_reset();
uint8_t c2_programming_init(); uint8_t c2_programming_init(uint8_t devid);
uint8_t c2_block_write(uint32_t address, uint8_t *data, uint8_t len); uint8_t c2_block_write(uint32_t address, uint8_t *data, uint8_t len);
uint8_t c2_block_read(uint32_t address, uint8_t *data, uint8_t len); uint8_t c2_block_read(uint32_t address, uint8_t *data, uint8_t len);
uint8_t c2_eeprom_read(uint32_t address, uint8_t *data, uint8_t len); uint8_t c2_eeprom_read(uint32_t address, uint8_t *data, uint8_t len);

View File

@ -127,7 +127,7 @@ ssize_t rf_decode_and_write(uint8_t *record, size_t size)
uint16_t address = h->address_high * 0x100 + h->address_low; uint16_t address = h->address_high * 0x100 + h->address_low;
do { do {
err = c2_programming_init(); err = c2_programming_init(C2_DEVID_EFM8BB1);
err = c2_block_write(address, h->data, h->len); err = c2_block_write(address, h->data, h->len);
} while (err != C2_SUCCESS && retries--); } while (err != C2_SUCCESS && retries--);
} else if (h->record_type == IHX_RT_END_OF_FILE) { } else if (h->record_type == IHX_RT_END_OF_FILE) {
@ -179,7 +179,7 @@ uint8_t rf_erase_flash(void)
uint8_t err; uint8_t err;
for (uint32_t i = 0; i < 4; i++) { // HACK: Try multiple times as the command sometimes fails (unclear why) for (uint32_t i = 0; i < 4; i++) { // HACK: Try multiple times as the command sometimes fails (unclear why)
err = c2_programming_init(); err = c2_programming_init(C2_DEVID_EFM8BB1);
if (err != C2_SUCCESS) { if (err != C2_SUCCESS) {
return 10; // Failed to init RF chip return 10; // Failed to init RF chip
} }