From 00d3e2b11cfe4989202793f55a5b239492ba53f4 Mon Sep 17 00:00:00 2001 From: Skip Hansen Date: Tue, 30 Jul 2024 09:54:21 -0700 Subject: [PATCH] Added cc_interface.* files missed in earlier commit. --- ESP32_AP-Flasher/include/cc_interface.h | 58 ++++ ESP32_AP-Flasher/src/cc_interface.cpp | 397 ++++++++++++++++++++++++ 2 files changed, 455 insertions(+) create mode 100755 ESP32_AP-Flasher/include/cc_interface.h create mode 100755 ESP32_AP-Flasher/src/cc_interface.cpp diff --git a/ESP32_AP-Flasher/include/cc_interface.h b/ESP32_AP-Flasher/include/cc_interface.h new file mode 100755 index 000000000..c4053800f --- /dev/null +++ b/ESP32_AP-Flasher/include/cc_interface.h @@ -0,0 +1,58 @@ +#pragma once +#include + +typedef void (*callbackPtr)(uint8_t percent); + +class CC_interface +{ + public: + uint16_t begin(uint8_t CC, uint8_t DD, uint8_t RESET); + void set_callback(callbackPtr callBack = nullptr); + uint8_t set_lock_byte(uint8_t lock_byte); + uint8_t erase_chip(); + void read_code_memory(uint16_t address, uint16_t len, uint8_t buffer[]); + void read_xdata_memory(uint16_t address, uint16_t len, uint8_t buffer[]); + void write_xdata_memory(uint16_t address, uint16_t len, uint8_t buffer[]); + void set_pc(uint16_t address); + uint8_t clock_init(); + uint8_t write_code_memory(uint16_t address, uint8_t buffer[], int len); + uint8_t verify_code_memory(uint16_t address, uint8_t buffer[], int len); + uint8_t opcode(uint8_t opCode); + uint8_t opcode(uint8_t opCode, uint8_t opCode1); + uint8_t opcode(uint8_t opCode, uint8_t opCode1, uint8_t opCode2); + uint8_t WR_CONFIG(uint8_t config); + uint8_t WD_CONFIG(); + /* Send one byte and return one byte as answer */ + uint8_t send_cc_cmdS(uint8_t cmd); + /* Send one byte and returns two bytes as answer */ + uint16_t send_cc_cmd(uint8_t cmd); + void cc_send_byte(uint8_t in_byte); + uint8_t cc_receive_byte(); + void enable_cc_debug(); + void reset_cc(); + + private: + boolean dd_direction = 0; // 0=OUT 1=IN + uint8_t _CC_PIN = -1; + uint8_t _DD_PIN = -1; + uint8_t _RESET_PIN = -1; + uint8_t flash_opcode[30] = { + 0x75, 0xAD, 0x00, // Set Flash Address HIGH + 0x75, 0xAC, 0x00, // Set Flash Address LOW + 0x90, 0xF0, 0x00, // Set RAM Address to 0xF000 + 0x75, 0xAE, 0x02, // Enable Flash Writing + 0x7D, 0x08, // Set Loop value to Half size as we write 2bytes at once 0x100 + 0xE0, // Put DPTR to A + 0xF5, 0xAF, // Put A to FWDATA + 0xA3, // Increase DPTR; + 0xE0, // Put DPTR to A + 0xF5, 0xAF, // Put A to FWDATA + 0xA3, // Increase DPTR + 0xE5, 0xAE, // Wait till writing is done + 0x20, 0xE6, 0xFB, + 0xDD, 0xF1, // Loop trough all bytes + 0xA5 // Breakpoint + }; + callbackPtr _callback = nullptr; +}; + diff --git a/ESP32_AP-Flasher/src/cc_interface.cpp b/ESP32_AP-Flasher/src/cc_interface.cpp new file mode 100755 index 000000000..7b78d63ae --- /dev/null +++ b/ESP32_AP-Flasher/src/cc_interface.cpp @@ -0,0 +1,397 @@ +#include +#include "cc_interface.h" + +uint16_t CC_interface::begin(uint8_t CC, uint8_t DD, uint8_t RESET) +{ + _CC_PIN = CC; + _DD_PIN = DD; + _RESET_PIN = RESET; + + pinMode(_CC_PIN, OUTPUT); + pinMode(_DD_PIN, OUTPUT); + pinMode(_RESET_PIN, OUTPUT); + digitalWrite(_CC_PIN, LOW); + digitalWrite(_DD_PIN, HIGH); + digitalWrite(_RESET_PIN, HIGH); + + enable_cc_debug(); + uint16_t device_id_answer = send_cc_cmd(0x68); + opcode(0x00); // NOP + clock_init(); // Even with failed clock init return the device id, because if the device is locked setting clock will fail + return device_id_answer; +} + +void CC_interface::set_callback(callbackPtr callBack) +{ + _callback = callBack; +} + +uint8_t CC_interface::set_lock_byte(uint8_t lock_byte) +{ + lock_byte = lock_byte & 0x1f; // Max lock byte value + WR_CONFIG(0x01); // Select flash info Page + opcode(0x00); // NOP + + opcode(0xE5, 0x92); + opcode(0x75, 0x92, 0x00); + opcode(0xE5, 0x83); + opcode(0xE5, 0x82); + opcode(0x90, 0xF0, 0x00); + opcode(0x74, 0xFF); + opcode(0xF0); + opcode(0xA3); // Increase Pointer + opcode(0x74, lock_byte); // Transmit the set lock byte + opcode(0xF0); + opcode(0xA3); // Increase Pointer + opcode(0x90, 0x00, 0x00); + opcode(0x75, 0x92, 0x00); + opcode(0x74, 0x00); + + opcode(0x00); // NOP + + opcode(0xE5, 0x92); + opcode(0x75, 0x92, 0x00); + opcode(0xE5, 0x83); + opcode(0xE5, 0x82); + opcode(0x90, 0xF8, 0x00); + opcode(0x74, 0xF0); + opcode(0xF0); + opcode(0xA3); // Increase Pointer + opcode(0x74, 0x00); + opcode(0xF0); + opcode(0xA3); // Increase Pointer + opcode(0x74, 0xDF); + opcode(0xF0); + opcode(0xA3); // Increase Pointer + opcode(0x74, 0xAF); + opcode(0xF0); + opcode(0xA3); // Increase Pointer + opcode(0x74, 0x00); + opcode(0xF0); + opcode(0xA3); // Increase Pointer + opcode(0x74, 0x02); + opcode(0xF0); + opcode(0xA3); // Increase Pointer + opcode(0x74, 0x12); + opcode(0xF0); + opcode(0xA3); // Increase Pointer + opcode(0x74, 0x4A); + opcode(0xF0); + opcode(0xA3); // Increase Pointer + opcode(0x90, 0x00, 0x00); + opcode(0x75, 0x92, 0x00); + opcode(0x74, 0x00); + + opcode(0x00); // NOP + + opcode(0xE5, 0xC6); + opcode(0x74, 0x00); + opcode(0x75, 0xAB, 0x23); + opcode(0x75, 0xD5, 0xF8); + opcode(0x75, 0xD4, 0x00); + opcode(0x75, 0xD6, 0x01); + opcode(0x75, 0xAD, 0x00); + opcode(0x75, 0xAC, 0x00); + opcode(0x75, 0xAE, 0x02); + + opcode(0x00); // NOP + + opcode(0xE5, 0xAE); + opcode(0x74, 0x00); + + return WR_CONFIG(0x00); // Select normal flash page +} + +uint8_t CC_interface::erase_chip() +{ + opcode(0x00); // NOP + send_cc_cmdS(0x14); + int timeout = millis() + 100; + while (!(send_cc_cmdS(0x34) & 0x80)) + { + if (millis() > timeout) + { + return 1; + } + } + return 0; +} + +void CC_interface::read_code_memory(uint16_t address, uint16_t len, uint8_t buffer[]) +{ + int last_callback = 0; + opcode(0x75, 0xc7, 0x01); + opcode(0x90, address >> 8, address); + for (int i = 0; i < len; i++) + { + opcode(0xe4); + buffer[i] = opcode(0x93); + opcode(0xa3); + if (i - last_callback > 100) + { + last_callback = i; + if (_callback != nullptr) + { + uint8_t percent = ((float)((float)i / (float)len) * 100.0); + if (percent < 0) + percent = 0; + if (percent > 100) + percent = 100; + _callback(percent); + } + } + } + if (_callback != nullptr) + _callback(100); +} + +void CC_interface::read_xdata_memory(uint16_t address, uint16_t len, uint8_t buffer[]) +{ + opcode(0x90, address >> 8, address); + for (int i = 0; i < len; i++) + { + buffer[i] = opcode(0xe0); + opcode(0xa3); + } +} + +void CC_interface::write_xdata_memory(uint16_t address, uint16_t len, uint8_t buffer[]) +{ + opcode(0x90, address >> 8, address); + for (int i = 0; i < len; i++) + { + opcode(0x74, buffer[i]); + opcode(0xf0); + opcode(0xa3); + } +} + +void CC_interface::set_pc(uint16_t address) +{ + opcode(0x02, address >> 8, address); +} + +uint8_t CC_interface::clock_init() +{ + opcode(0x75, 0xc6, 0x00); + int timeout = millis() + 100; + while (!(opcode(0xe5, 0xbe) & 0x40)) + { + if (millis() > timeout) + { + return 1; + } + } + return 0; +} + +uint8_t CC_interface::write_code_memory(uint16_t address, uint8_t buffer[], int len) +{ + int entry_len = len; + if (len % 2 != 0) + len++; + int position = 0; + int len_per_transfer = 64; + address = address / 2; + while (len) + { + flash_opcode[2] = (address >> 8) & 0xff; + flash_opcode[5] = address & 0xff; + flash_opcode[13] = (len > len_per_transfer) ? (len_per_transfer / 2) : (len / 2); + write_xdata_memory(0xf000, len_per_transfer, &buffer[position]); + write_xdata_memory(0xf100, sizeof(flash_opcode), flash_opcode); + opcode(0x75, 0xC7, 0x51); + set_pc(0xf100); + send_cc_cmdS(0x4c); + int timeout = millis() + 500; + while (!(send_cc_cmdS(0x34) & 0x08)) + { + if (millis() > timeout) + { + if (_callback != nullptr) + _callback(0); + return 1; + } + } + if (_callback != nullptr) + { + uint8_t percent = 100 - ((float)((float)len / (float)entry_len) * 100.0); + if (percent < 0) + percent = 0; + if (percent > 100) + percent = 100; + _callback(percent); + } + len -= flash_opcode[13] * 2; + position += flash_opcode[13] * 2; + address += flash_opcode[13]; + } + if (_callback != nullptr) + _callback(100); + return 0; +} + +uint8_t CC_interface::verify_code_memory(uint16_t address, uint8_t buffer[], int len) +{ + int last_callback = 0; + opcode(0x75, 0xc7, 0x01); + opcode(0x90, address >> 8, address); + for (int i = 0; i < len; i++) + { + opcode(0xe4); + if (buffer[i] != opcode(0x93)) + { + if (_callback != nullptr) + _callback(0); + return 1; + } + opcode(0xa3); + if (i - last_callback > 100) + { + last_callback = i; + if (_callback != nullptr) + { + uint8_t percent = ((float)((float)i / (float)len) * 100.0); + if (percent < 0) + percent = 0; + if (percent > 100) + percent = 100; + _callback(percent); + } + } + } + if (_callback != nullptr) + _callback(100); + return 0; +} + +uint8_t CC_interface::opcode(uint8_t opCode) +{ + cc_send_byte(0x55); + cc_send_byte(opCode); + return cc_receive_byte(); +} + +uint8_t CC_interface::opcode(uint8_t opCode, uint8_t opCode1) +{ + cc_send_byte(0x56); + cc_send_byte(opCode); + cc_send_byte(opCode1); + return cc_receive_byte(); +} + +uint8_t CC_interface::opcode(uint8_t opCode, uint8_t opCode1, uint8_t opCode2) +{ + cc_send_byte(0x57); + cc_send_byte(opCode); + cc_send_byte(opCode1); + cc_send_byte(opCode2); + return cc_receive_byte(); +} + +uint8_t CC_interface::WR_CONFIG(uint8_t config) +{ + cc_send_byte(0x1d); + cc_send_byte(config); + return cc_receive_byte(); +} + +uint8_t CC_interface::WD_CONFIG() +{ + cc_send_byte(0x24); + return cc_receive_byte(); +} + +uint8_t CC_interface::send_cc_cmdS(uint8_t cmd) +{ + cc_send_byte(cmd); + return cc_receive_byte(); +} + +uint16_t CC_interface::send_cc_cmd(uint8_t cmd) +{ + cc_send_byte(cmd); + return (cc_receive_byte() << 8) + cc_receive_byte(); +} + +void CC_interface::cc_send_byte(uint8_t in_byte) +{ + if (dd_direction == 1) + { + dd_direction = 0; + pinMode(_DD_PIN, OUTPUT); + digitalWrite(_DD_PIN, LOW); + } + for (int i = 8; i; i--) + { + if (in_byte & 0x80) + digitalWrite(_DD_PIN, HIGH); + else + digitalWrite(_DD_PIN, LOW); + + digitalWrite(_CC_PIN, HIGH); + in_byte <<= 1; + delayMicroseconds(5); + digitalWrite(_CC_PIN, LOW); + } +} + +uint8_t CC_interface::cc_receive_byte() +{ + uint8_t out_byte = 0x00; + if (dd_direction == 0) + { + dd_direction = 1; + pinMode(_DD_PIN, INPUT); + digitalWrite(_DD_PIN, LOW); + } + for (int i = 8; i; i--) + { + digitalWrite(_CC_PIN, HIGH); + delayMicroseconds(5); + out_byte <<= 1; + if (digitalRead(_DD_PIN)) + out_byte |= 0x01; + digitalWrite(_CC_PIN, LOW); + delayMicroseconds(5); + } + return out_byte; +} + +void CC_interface::enable_cc_debug() +{ + if (dd_direction == 0) + { + dd_direction = 1; + pinMode(_DD_PIN, INPUT); + digitalWrite(_DD_PIN, HIGH); + } + delay(5); + digitalWrite(_RESET_PIN, LOW); + delay(2); + digitalWrite(_CC_PIN, HIGH); + delayMicroseconds(5); + digitalWrite(_CC_PIN, LOW); + delayMicroseconds(5); + digitalWrite(_CC_PIN, HIGH); + delayMicroseconds(5); + digitalWrite(_CC_PIN, LOW); + delay(2); + digitalWrite(_RESET_PIN, HIGH); + delay(2); +} + +void CC_interface::reset_cc() +{ + if (dd_direction == 0) + { + dd_direction = 1; + pinMode(_DD_PIN, INPUT); + digitalWrite(_DD_PIN, HIGH); + } + delay(5); + digitalWrite(_RESET_PIN, LOW); + delay(5); + digitalWrite(_RESET_PIN, HIGH); + delay(2); +}