From 1418af3f31895a15bf2dfcbcae652b7583181a68 Mon Sep 17 00:00:00 2001 From: halfbakery Date: Tue, 15 Sep 2020 21:49:03 +0200 Subject: [PATCH] Fix C2 programmer, incorrect initialization could brick EFM8 MCUs --- lib/C2Programmer-1.0.0/src/c2.cpp | 22 +++++++++++++++++++++- lib/C2Programmer-1.0.0/src/c2.h | 9 ++++++++- tasmota/xdrv_06_snfbridge.ino | 4 ++-- 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/lib/C2Programmer-1.0.0/src/c2.cpp b/lib/C2Programmer-1.0.0/src/c2.cpp index 22bfbaedd..fd7e41af0 100644 --- a/lib/C2Programmer-1.0.0/src/c2.cpp +++ b/lib/C2Programmer-1.0.0/src/c2.cpp @@ -204,13 +204,33 @@ uint8_t c2_reset() { return C2_SUCCESS; } -uint8_t c2_programming_init() { +uint8_t c2_programming_init(uint8_t devid) { c2_reset(); c2_address_write(C2FPCTL); C2_DATA_WRITE_AND_CHECK(C2FPCTL_ENABLE0, 1); C2_DATA_WRITE_AND_CHECK(C2FPCTL_CORE_HALT, 1); C2_DATA_WRITE_AND_CHECK(C2FPCTL_ENABLE1, 1) 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; } diff --git a/lib/C2Programmer-1.0.0/src/c2.h b/lib/C2Programmer-1.0.0/src/c2.h index bc744d02f..0b80c95f3 100644 --- a/lib/C2Programmer-1.0.0/src/c2.h +++ b/lib/C2Programmer-1.0.0/src/c2.h @@ -103,6 +103,13 @@ inline void C2D_enable(bool oe) { #define C2_INBUSY 0x02 #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 void c2_address_write(uint8_t address); 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 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_read(uint32_t address, uint8_t *data, uint8_t len); uint8_t c2_eeprom_read(uint32_t address, uint8_t *data, uint8_t len); diff --git a/tasmota/xdrv_06_snfbridge.ino b/tasmota/xdrv_06_snfbridge.ino index af6f928bd..228564a45 100644 --- a/tasmota/xdrv_06_snfbridge.ino +++ b/tasmota/xdrv_06_snfbridge.ino @@ -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; do { - err = c2_programming_init(); + err = c2_programming_init(C2_DEVID_EFM8BB1); err = c2_block_write(address, h->data, h->len); } while (err != C2_SUCCESS && retries--); } else if (h->record_type == IHX_RT_END_OF_FILE) { @@ -179,7 +179,7 @@ uint8_t rf_erase_flash(void) uint8_t err; 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) { return 10; // Failed to init RF chip }