working dual port flasher, direct usb only

This commit is contained in:
Jelmer
2023-03-18 01:50:39 +01:00
parent 29c0deb541
commit 9b4fba818f
14 changed files with 2002 additions and 105 deletions

3
esp32_fw/CMakeLists.txt Normal file
View File

@@ -0,0 +1,3 @@
cmake_minimum_required(VERSION 3.16.0)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(esp32_fw)

View File

@@ -0,0 +1,9 @@
dependencies:
idf:
component_hash: null
source:
type: idf
version: 4.4.4
manifest_hash: dcf4d39b94252de130019eadceb989d72b0dbc26b552cfdcbb50f6da531d2b92
target: esp32s3
version: 1.0.0

View File

@@ -10,6 +10,28 @@
// flasher options
#define CUSTOM_MAC_HDR 0x0000
#define FLASHER_AP_SS 4
#define FLASHER_AP_CLK 5
#define FLASHER_AP_MOSI 7
#define FLASHER_AP_MISO 6
#define FLASHER_AP_RESET 15
#define FLASHER_AP_POWER 0
#define FLASHER_AP_TXD 17
#define FLASHER_AP_RXD 18
#define FLASHER_AP_TEST 16
#define FLASHER_EXT_SS 40
#define FLASHER_EXT_CLK 41
#define FLASHER_EXT_MOSI 2
#define FLASHER_EXT_MISO 42
#define FLASHER_EXT_RESET 1
#define FLASHER_EXT_POWER 8
#define FLASHER_EXT_TXD 47
#define FLASHER_EXT_RXD 39
#define FLASHER_EXT_TEST 38
/* Lolin32 lite connections to AP tag
#define RXD1 16
#define TXD1 17

View File

@@ -0,0 +1,4 @@
#include <Arduino.h>
void usbFlasherTask(void* parameter);

View File

@@ -1,15 +1,16 @@
#pragma once
#include <stdint.h>
#include <stdio.h>
#include <stdint.h>
#include <SPI.h>
/* Autor: Aaron Christophel ATCnetz.de */
#include <Arduino.h>
void simplePowerOn();
class ZBS_interface {
public:
uint8_t begin();
class ZBS_interface
{
public:
uint8_t begin(uint8_t SS, uint8_t CLK, uint8_t MOSI, uint8_t MISO, uint8_t RESET, uint8_t POWER = -1, uint32_t spi_speed = 8000000);
void setSpeed(uint32_t speed);
void set_power(uint8_t state);
void enable_debug();
void reset();
@@ -27,8 +28,11 @@ class ZBS_interface {
uint8_t select_flash(uint8_t page);
void erase_flash();
void erase_infoblock();
~ZBS_interface();
private:
private:
SPIClass *spi = NULL;
SPISettings spiSettings;
uint8_t _SS_PIN = -1;
uint8_t _CLK_PIN = -1;
uint8_t _MOSI_PIN = -1;
@@ -36,8 +40,11 @@ class ZBS_interface {
uint8_t _RESET_PIN = -1;
uint8_t _POWER_PIN = -1;
int ZBS_spi_delay = 1;
uint8_t spi_ready = 0;
uint32_t after_byte_delay = 10;
typedef enum {
typedef enum
{
ZBS_CMD_W_RAM = 0x02,
ZBS_CMD_R_RAM = 0x03,
ZBS_CMD_W_FLASH = 0x08,
@@ -48,10 +55,9 @@ class ZBS_interface {
ZBS_CMD_ERASE_INFOBLOCK = 0x48,
} ZBS_CMD_LIST;
typedef enum {
typedef enum
{
ZBS_ON = 1,
ZBS_OFF = 0,
} ZBS_POWER_STATE;
};
extern ZBS_interface zbs;
};

View File

@@ -8,11 +8,15 @@
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html
[env:lolin32_lite]
platform = espressif32
board = esp32dev
; ----------------------------------------------------------------------------------------
; !!! this configuration expects the 16MB Flash / 8MB Ram version of the ESP32-S3-DevkitC1
; ----------------------------------------------------------------------------------------
[env:openepaperlink-flasher-ap]
platform = https://github.com/platformio/platform-espressif32.git
board = esp32-s3-devkitc-1
framework = arduino
board_build.partitions = no_ota.csv
board_build.partitions =default_16MB.csv
platform_packages =
monitor_filters = esp32_exception_decoder
monitor_speed = 115200
@@ -26,5 +30,20 @@ lib_deps =
https://github.com/Bodmer/TJpg_Decoder.git
https://github.com/garretlab/shoddyxml2
https://github.com/Bodmer/U8g2_for_TFT_eSPI
upload_port = COM12
monitor_port = COM12
upload_port = COM7
monitor_port = COM7
build_unflags =
-D ARDUINO_USB_MODE=1
build_flags =
-D ARDUINO_USB_MODE=0
-D CONFIG_ESP32S3_SPIRAM_SUPPORT=1
-D BOARD_HAS_PSRAM
-D CONFIG_SPIRAM_USE_MALLOC=y
board_build.flash_mode=qio
board_build.arduino.memory_type = qio_opi
board_build.psram_type=qspi_opi
board_upload.maximum_size = 16777216
board_upload.maximum_ram_size = 327680
board_upload.flash_size = 16MB

BIN
esp32_fw/readtest.bin2 Normal file

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,6 @@
# This file was automatically generated for projects
# without default 'CMakeLists.txt' file.
FILE(GLOB_RECURSE app_sources ${CMAKE_SOURCE_DIR}/src/*.*)
idf_component_register(SRCS ${app_sources})

View File

@@ -27,6 +27,9 @@ typedef enum {
uint8_t *infoblock = nullptr;
uint8_t *flashbuffer = nullptr;
static class ZBS_interface* zbs;
// look for the latest version of the firmware file... It's supposed to be something like zigbeebase0003.bin
String lookupFirmwareFile(uint16_t &version) {
String filename;
@@ -58,9 +61,9 @@ uint16_t getDeviceType() {
uint8_t type29[8] = {0x7d, 0x22, 0xff, 0x02, 0xa4, 0x58, 0xf0, 0x90};
uint8_t type154[8] = {0xa1, 0x23, 0x22, 0x02, 0xa4, 0xc3, 0xe4, 0xf0};
uint8_t buffer[8] = {0};
zbs.select_flash(0);
zbs->select_flash(0);
for (uint8_t c = 0; c < 8; c++) {
buffer[c] = zbs.read_flash(0x08 + c);
buffer[c] = zbs->read_flash(0x08 + c);
}
if (memcmp(buffer, type29, 8) == 0) {
return 0x3B10;
@@ -73,10 +76,10 @@ uint16_t getDeviceType() {
// extract original mac from firmware and make it 2 bytes longer based on info in settings.h
uint64_t getOriginalTagMac() {
zbs.select_flash(0);
zbs->select_flash(0);
uint8_t mac[8] = {0};
for (uint8_t c = 0; c < 6; c++) {
mac[c + 2] = zbs.read_flash(0xFC06 + c);
mac[c + 2] = zbs->read_flash(0xFC06 + c);
}
mac[0] = (uint8_t)(CUSTOM_MAC_HDR >> 8);
mac[1] = (uint8_t)CUSTOM_MAC_HDR;
@@ -96,10 +99,10 @@ uint64_t getOriginalTagMac() {
// extract custom firmware mac from Infoblock
uint64_t getInfoBlockMac() {
zbs.select_flash(1);
zbs->select_flash(1);
uint8_t mac[8] = {0};
for (uint8_t c = 0; c < 8; c++) {
mac[c] = zbs.read_flash(0x10 + c);
mac[c] = zbs->read_flash(0x10 + c);
}
return *((uint64_t *)(mac));
}
@@ -110,9 +113,9 @@ void readInfoBlock() {
// allocate room for infopage
infoblock = (uint8_t *)calloc(1024, 1);
}
zbs.select_flash(1); // select info page
zbs->select_flash(1); // select info page
for (uint16_t c = 0; c < 1024; c++) {
infoblock[c] = zbs.read_flash(c);
infoblock[c] = zbs->read_flash(c);
}
}
@@ -121,13 +124,13 @@ void writeInfoBlock() {
if (infoblock == nullptr) {
return;
}
zbs.select_flash(1);
zbs.erase_infoblock();
zbs.select_flash(1); // select info page
zbs->select_flash(1);
zbs->erase_infoblock();
zbs->select_flash(1); // select info page
for (uint16_t c = 0; c < 1024; c++) {
for (uint8_t i = 0; i < MAX_WRITE_ATTEMPTS; i++) {
zbs.write_flash(c, infoblock[c]);
if (zbs.read_flash(c) == infoblock[c]) {
zbs->write_flash(c, infoblock[c]);
if (zbs->read_flash(c) == infoblock[c]) {
break;
}
}
@@ -139,15 +142,15 @@ void writeFlashBlock(uint16_t size) {
if (flashbuffer == nullptr) {
return;
}
zbs.select_flash(0);
zbs.erase_flash();
zbs.select_flash(0);
zbs->select_flash(0);
zbs->erase_flash();
zbs->select_flash(0);
Serial.printf("Starting flash, size=%d\n", size);
uint8_t i = 0;
for (uint16_t c = 0; c < size; c++) {
for (i = 0; i < MAX_WRITE_ATTEMPTS; i++) {
zbs.write_flash(c, flashbuffer[c]);
if (zbs.read_flash(c) == flashbuffer[c]) {
zbs->write_flash(c, flashbuffer[c]);
if (zbs->read_flash(c) == flashbuffer[c]) {
break;
}
}
@@ -165,11 +168,11 @@ void writeFlashBlock(uint16_t size) {
void performDeviceFlash() {
uint8_t interfaceWorking = 0;
Serial.printf("Power cycling to get everything up and running...\n");
zbs.set_power(0);
zbs->set_power(0);
vTaskDelay(500 / portTICK_PERIOD_MS);
zbs.set_power(1);
zbs->set_power(1);
vTaskDelay(500 / portTICK_PERIOD_MS);
interfaceWorking = zbs.begin();
//interfaceWorking = zbs.begin();
if (!interfaceWorking) {
Serial.print("I wasn't able to connect to a ZBS tag, please check wiring and definitions in the settings.h file.\n");
return;
@@ -182,11 +185,11 @@ void performDeviceFlash() {
if (*((uint64_t *)(mac)) == 0xFFFFFFFFFFFFFFFF) {
// mac not set in infopage, get it from the original firmware
*((uint64_t *)(mac)) = getOriginalTagMac();
zbs.select_flash(1);
zbs->select_flash(1);
for (uint8_t c = 0; c < 8; c++) {
infoblock[0x17 - c] = mac[c];
// write mac directly to infoblock without erasing; the bytes should all be 0xFF anyway
zbs.write_flash(0x17 - c, mac[c]);
zbs->write_flash(0x17 - c, mac[c]);
}
}
@@ -219,6 +222,6 @@ void performDeviceFlash() {
infoblock = nullptr;
free(flashbuffer);
flashbuffer = nullptr;
zbs.reset();
zbs.set_power(1);
zbs->reset();
zbs->set_power(1);
}

View File

@@ -5,12 +5,13 @@
#include "contentmanager.h"
#include "flasher.h"
#include "hal/wdt_hal.h"
#include "makeimage.h"
#include "pendingdata.h"
#include "serial.h"
#include "settings.h"
#include "soc/rtc_wdt.h"
#include "tag_db.h"
#include "usbflasher.h"
#include "web.h"
void timeTask(void* parameter) {
@@ -35,9 +36,26 @@ void setup() {
Serial.begin(115200);
Serial.print(">\n");
psramInit();
Serial.println("\n\n##################################");
Serial.printf("Internal Total heap %d, internal Free Heap %d\n", ESP.getHeapSize(), ESP.getFreeHeap());
Serial.printf("SPIRam Total heap %d, SPIRam Free Heap %d\n", ESP.getPsramSize(), ESP.getFreePsram());
Serial.printf("ChipRevision %d, Cpu Freq %d, SDK Version %s\n", ESP.getChipRevision(), ESP.getCpuFreqMHz(), ESP.getSdkVersion());
Serial.printf("Flash Size %d, Flash Speed %d\n", ESP.getFlashChipSize(), ESP.getFlashChipSpeed());
Serial.println("##################################\n\n");
Serial.println(ESP.getFreeHeap());
Serial.printf("Total heap: %d", ESP.getHeapSize());
Serial.printf("Free heap: %d", ESP.getFreeHeap());
Serial.printf("Total PSRAM: %d", ESP.getPsramSize());
Serial.printf("Free PSRAM: %d", ESP.getFreePsram());
pinMode(ONBOARD_LED, OUTPUT);
digitalWrite(ONBOARD_LED, HIGH);
xTaskCreate(usbFlasherTask, "flasher", 10000, NULL, configMAX_PRIORITIES - 10, NULL);
configTzTime("CET-1CEST,M3.5.0,M10.5.0/3", "0.nl.pool.ntp.org", "europe.pool.ntp.org", "time.nist.gov");
// https://github.com/nayarsystems/posix_tz_db/blob/master/zones.csv
@@ -46,7 +64,7 @@ void setup() {
xTaskCreate(zbsRxTask, "zbsRX Process", 10000, NULL, 2, NULL);
xTaskCreate(garbageCollection, "pending-data cleanup", 5000, NULL, 1, NULL);
xTaskCreate(webSocketSendProcess, "ws", 5000, NULL,configMAX_PRIORITIES-10, NULL);
xTaskCreate(webSocketSendProcess, "ws", 5000, NULL, configMAX_PRIORITIES - 10, NULL);
xTaskCreate(timeTask, "timed tasks", 10000, NULL, 2, NULL);
}

View File

@@ -231,7 +231,7 @@ extern uint8_t* getDataForFile(File* file);
void zbsRxTask(void* parameter) {
Serial1.begin(230400, SERIAL_8N1, RXD1, TXD1);
simplePowerOn();
//simplePowerOn();
bool firstrun = true;
Serial1.print("VER?");
@@ -250,7 +250,7 @@ void zbsRxTask(void* parameter) {
//performDeviceFlash();
Serial.println("I wasn't able to connect to a ZBS tag, trying to reboot the tag.");
Serial.println("If this problem persists, please check wiring and definitions in the settings.h file, and presence of the right firmware");
simplePowerOn();
//simplePowerOn();
wsErr("The AP tag crashed. Restarting tag, regenerating all pending info.");
refreshAllPending();
}

348
esp32_fw/src/usbflasher.cpp Normal file
View File

@@ -0,0 +1,348 @@
#include <Arduino.h>
#include "USB.h"
#include "settings.h"
#include "zbs_interface.h"
USBCDC USBSerial;
QueueHandle_t flasherCmdQueue;
#define FLASHER_WAIT_A 0
#define FLASHER_WAIT_T 1
#define FLASHER_WAIT_CMD 2
#define FLASHER_WAIT_LEN 3
#define FLASHER_WAIT_DATA 4
#define FLASHER_WAIT_CRCH 5
#define FLASHER_WAIT_CRCL 6
struct flasherCommand {
uint8_t command = 0;
uint8_t len = 0;
uint8_t* data = nullptr;
};
void sendFlasherAnswer(uint8_t answer_cmd, uint8_t* ans_buff, uint8_t len) {
uint8_t* answer_buffer = (uint8_t*)calloc(2 + 2 + len + 2, 1);
if (answer_buffer == nullptr) return;
uint32_t CRC_value = 0xAB34;
answer_buffer[0] = 'A';
answer_buffer[1] = 'T';
answer_buffer[2] = answer_cmd;
CRC_value += answer_cmd;
answer_buffer[3] = len;
CRC_value += len;
for (int i = 0; i < len; i++) {
answer_buffer[4 + i] = ans_buff[i];
CRC_value += ans_buff[i];
}
answer_buffer[2 + 2 + len] = CRC_value >> 8;
answer_buffer[2 + 2 + len + 1] = CRC_value;
USBSerial.write(answer_buffer, 2 + 2 + len + 2);
free(answer_buffer);
}
void flasherUartHandler(uint8_t* data, uint8_t len) {
static struct flasherCommand* cmd;
static uint8_t flasherSerialState = FLASHER_WAIT_A;
static uint8_t flasherCmdDataIndex = 0;
static uint16_t flasherCRC = 0xAB34;
static uint32_t flasherLastCmd = 0;
if ((flasherSerialState != FLASHER_WAIT_A) && (millis() - flasherLastCmd >= 225)) {
flasherSerialState = FLASHER_WAIT_A;
}
while (len--) {
uint8_t usbbyte = *(data++);
switch (flasherSerialState) {
case FLASHER_WAIT_A:
if (usbbyte == 'A') {
flasherSerialState = FLASHER_WAIT_T;
flasherLastCmd = millis();
}
break;
case FLASHER_WAIT_T:
if (usbbyte == 'T') {
flasherSerialState = FLASHER_WAIT_CMD;
cmd = new flasherCommand;
flasherCRC = 0xAB34;
flasherCmdDataIndex = 0;
} else {
flasherSerialState = FLASHER_WAIT_A;
}
break;
case FLASHER_WAIT_CMD:
cmd->command = usbbyte;
flasherCRC += usbbyte;
flasherSerialState = FLASHER_WAIT_LEN;
break;
case FLASHER_WAIT_LEN:
flasherCRC += usbbyte;
if (usbbyte) {
cmd->len = usbbyte;
cmd->data = (uint8_t*)calloc(usbbyte, 1);
flasherSerialState = FLASHER_WAIT_DATA;
} else {
flasherSerialState = FLASHER_WAIT_CRCH;
}
break;
case FLASHER_WAIT_DATA:
flasherCRC += usbbyte;
cmd->data[flasherCmdDataIndex++] = usbbyte;
if (flasherCmdDataIndex == cmd->len) {
flasherSerialState = FLASHER_WAIT_CRCH;
}
break;
case FLASHER_WAIT_CRCH:
flasherCRC -= ((uint16_t)usbbyte << 8);
flasherSerialState = FLASHER_WAIT_CRCL;
break;
case FLASHER_WAIT_CRCL:
flasherCRC -= ((uint16_t)usbbyte);
if (flasherCRC) {
Serial.printf("CRC failed for flasher command :( %04X\n", flasherCRC);
cmd = nullptr;
} else {
BaseType_t queuestatus = xQueueSend(flasherCmdQueue, &cmd, 0);
if (queuestatus == pdFALSE) {
if (cmd->data != nullptr) free(cmd->data);
delete cmd;
}
cmd = nullptr;
}
flasherSerialState = FLASHER_WAIT_A;
break;
}
}
}
static void usbEventCallback(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) {
if (event_base == ARDUINO_USB_EVENTS) {
arduino_usb_event_data_t* data = (arduino_usb_event_data_t*)event_data;
switch (event_id) {
case ARDUINO_USB_STARTED_EVENT:
Serial.println("USB PLUGGED");
break;
case ARDUINO_USB_STOPPED_EVENT:
Serial.println("USB UNPLUGGED");
break;
case ARDUINO_USB_SUSPEND_EVENT:
Serial.printf("USB SUSPENDED: remote_wakeup_en: %u\n", data->suspend.remote_wakeup_en);
break;
case ARDUINO_USB_RESUME_EVENT:
Serial.println("USB RESUMED");
break;
default:
break;
}
} else if (event_base == ARDUINO_USB_CDC_EVENTS) {
arduino_usb_cdc_event_data_t* data = (arduino_usb_cdc_event_data_t*)event_data;
switch (event_id) {
case ARDUINO_USB_CDC_CONNECTED_EVENT:
Serial.println("CDC CONNECTED");
break;
case ARDUINO_USB_CDC_DISCONNECTED_EVENT:
Serial.println("CDC DISCONNECTED");
break;
case ARDUINO_USB_CDC_LINE_STATE_EVENT:
Serial.printf("CDC LINE STATE: dtr: %u, rts: %u\n", data->line_state.dtr, data->line_state.rts);
break;
case ARDUINO_USB_CDC_LINE_CODING_EVENT:
Serial.printf("CDC LINE CODING: bit_rate: %u, data_bits: %u, stop_bits: %u, parity: %u\n", data->line_coding.bit_rate, data->line_coding.data_bits, data->line_coding.stop_bits, data->line_coding.parity);
break;
case ARDUINO_USB_CDC_RX_EVENT:
// Serial.printf("CDC RX [%u]:", data->rx.len);
{
uint8_t buf[data->rx.len];
size_t len = USBSerial.read(buf, data->rx.len);
flasherUartHandler(buf, len);
}
break;
case ARDUINO_USB_CDC_RX_OVERFLOW_EVENT:
Serial.printf("CDC RX Overflow of %d bytes", data->rx_overflow.dropped_bytes);
break;
default:
break;
}
}
}
void flasherTaskBegin() {
flasherCmdQueue = xQueueCreate(10, sizeof(struct flasherCommand*));
#if ARDUINO_USB_MODE
#warning Wrong USB mode is in use, check settings in platformio.ini
#endif
USB.onEvent(usbEventCallback);
USBSerial.onEvent(usbEventCallback);
USBSerial.begin();
USB.begin();
}
typedef enum {
CMD_GET_VERSION = 1,
CMD_RESET_ESP = 2,
CMD_ZBS_BEGIN = 10,
CMD_RESET_ZBS = 11,
CMD_SELECT_PAGE = 12,
CMD_SET_POWER = 13,
CMD_READ_RAM = 20,
CMD_WRITE_RAM = 21,
CMD_READ_FLASH = 22,
CMD_WRITE_FLASH = 23,
CMD_READ_SFR = 24,
CMD_WRITE_SFR = 25,
CMD_ERASE_FLASH = 26,
CMD_ERASE_INFOBLOCK = 27,
CMD_SAVE_MAC_FROM_FW = 40,
CMD_PASS_THROUGH = 50,
} ZBS_UART_PROTO;
uint32_t FLASHER_VERSION = 0x0000002F;
static class ZBS_interface* zbs = nullptr;
void processFlasherCommand(struct flasherCommand* cmd) {
uint8_t* tempbuffer;
uint8_t temp_buff[16];
uint32_t spi_speed = 0;
static uint32_t curspeed = 0;
switch (cmd->command) {
case CMD_GET_VERSION:
temp_buff[0] = FLASHER_VERSION >> 24;
temp_buff[1] = FLASHER_VERSION >> 16;
temp_buff[2] = FLASHER_VERSION >> 8;
temp_buff[3] = FLASHER_VERSION;
sendFlasherAnswer(cmd->command, temp_buff, 4);
break;
case CMD_RESET_ESP:
sendFlasherAnswer(cmd->command, NULL, 0);
delay(100);
ESP.restart();
break;
case CMD_ZBS_BEGIN:
if (zbs != nullptr){
delete zbs;
}
zbs = new ZBS_interface;
if (cmd->data[0] & 1) {
spi_speed = 1000000;
} else {
spi_speed = 8000000;
}
curspeed = spi_speed;
if (cmd->data[0] & 2) {
temp_buff[0] = zbs->begin(FLASHER_AP_SS, FLASHER_AP_CLK, FLASHER_AP_MOSI, FLASHER_AP_MISO, FLASHER_AP_RESET, FLASHER_AP_POWER, spi_speed);
} else {
temp_buff[0] = zbs->begin(FLASHER_EXT_SS, FLASHER_EXT_CLK, FLASHER_EXT_MOSI, FLASHER_EXT_MISO, FLASHER_EXT_RESET, FLASHER_EXT_POWER, spi_speed);
}
sendFlasherAnswer(cmd->command, temp_buff, 1);
break;
case CMD_RESET_ZBS:
zbs->reset();
temp_buff[0] = 1;
sendFlasherAnswer(cmd->command, temp_buff, 1);
break;
case CMD_SELECT_PAGE:
temp_buff[0] = zbs->select_flash(cmd->data[0] ? 1 : 0);
sendFlasherAnswer(cmd->command, temp_buff, 1);
break;
case CMD_SET_POWER:
zbs->set_power(cmd->data[0] ? 1 : 0);
temp_buff[0] = 1;
sendFlasherAnswer(cmd->command, temp_buff, 1);
break;
case CMD_READ_RAM:
temp_buff[0] = zbs->read_ram(cmd->data[0]);
sendFlasherAnswer(cmd->command, temp_buff, 1);
break;
case CMD_WRITE_RAM:
zbs->write_ram(cmd->data[0], cmd->data[1]);
temp_buff[0] = 1;
sendFlasherAnswer(cmd->command, temp_buff, 1);
break;
case CMD_READ_FLASH:
tempbuffer = (uint8_t*)calloc(cmd->data[0], 1);
// cmd_buff[0] = len
// cmd_buff[1] << 8 | cmd_buff[2] = position
Serial.printf("Loading %d bytes from %04X \n", cmd->data[0], (cmd->data[1] << 8 | cmd->data[2]));
for (int i = 0; i < cmd->data[0]; i++) {
tempbuffer[i] = zbs->read_flash((cmd->data[1] << 8 | cmd->data[2]) + i);
}
sendFlasherAnswer(cmd->command, tempbuffer, cmd->data[0]);
free(tempbuffer);
break;
case CMD_WRITE_FLASH:
// cmd_buff[0] = len
// cmd_buff[1] << 8 | cmd_buff[2] = position
// cmd_buff[3+i] = data
if (cmd->data[0] >= (0xff - 3)) { // Len too high, only 0xFF - header len possible
temp_buff[0] = 0xEE;
sendFlasherAnswer(cmd->command, temp_buff, 1);
break;
}
Serial.printf("Writing %d bytes to %04X \n", cmd->data[0], (cmd->data[1] << 8 | cmd->data[2]));
for (int i = 0; i < cmd->data[0]; i++) {
if (cmd->data[3 + i] != 0xff) {
for (uint8_t attempts = 0; attempts < 10; attempts++) {
zbs->write_flash((cmd->data[1] << 8 | cmd->data[2]) + i, cmd->data[3 + i]);
if (zbs->read_flash((cmd->data[1] << 8 | cmd->data[2]) + i) == cmd->data[3 + i]) {
goto flash_pass;
}
curspeed -= 100000;
zbs->setSpeed(curspeed);
}
flash_fail:
temp_buff[0] = 0;
Serial.print("!");
sendFlasherAnswer(cmd->command, temp_buff, 1);
break;
flash_pass:
continue;
}
}
temp_buff[0] = 1;
sendFlasherAnswer(cmd->command, temp_buff, 1);
Serial.print("#");
break;
case CMD_READ_SFR:
temp_buff[0] = zbs->read_sfr(cmd->data[0]);
sendFlasherAnswer(cmd->command, temp_buff, 1);
break;
case CMD_WRITE_SFR:
zbs->write_sfr(cmd->data[0], cmd->data[1]);
temp_buff[0] = 1;
sendFlasherAnswer(cmd->command, temp_buff, 1);
break;
case CMD_ERASE_FLASH:
zbs->erase_flash();
temp_buff[0] = 1;
sendFlasherAnswer(cmd->command, temp_buff, 1);
break;
case CMD_ERASE_INFOBLOCK:
zbs->erase_infoblock();
temp_buff[0] = 1;
sendFlasherAnswer(cmd->command, temp_buff, 1);
break;
case CMD_SAVE_MAC_FROM_FW:
case CMD_PASS_THROUGH:
break;
}
}
void usbFlasherTask(void* parameter) {
flasherTaskBegin();
struct flasherCommand* cmd;
while (true) {
BaseType_t queuereceive = xQueueReceive(flasherCmdQueue, &cmd, portMAX_DELAY);
if (queuereceive == pdTRUE) {
processFlasherCommand(cmd);
if (cmd->data != nullptr) {
free(cmd->data);
}
delete cmd;
}
}
}

View File

@@ -1,55 +1,72 @@
/* Autor: Aaron Christophel ATCnetz.de */
#include "zbs_interface.h"
#include <Arduino.h>
#include <SPI.h>
#include <stdint.h>
#include <stdio.h>
#include "settings.h"
void simplePowerOn() {
pinMode(ZBS_SS, INPUT);
pinMode(ZBS_CLK, INPUT);
pinMode(ZBS_MoSi, INPUT);
pinMode(ZBS_MiSo, INPUT);
pinMode(ZBS_Reset, OUTPUT);
digitalWrite(ZBS_Reset, HIGH);
zbs.set_power(0);
delay(500);
zbs.set_power(1);
}
uint8_t ZBS_interface::begin() {
_SS_PIN = ZBS_SS;
_CLK_PIN = ZBS_CLK;
_MOSI_PIN = ZBS_MoSi;
_MISO_PIN = ZBS_MiSo;
_RESET_PIN = ZBS_Reset;
uint8_t ZBS_interface::begin(uint8_t SS, uint8_t CLK, uint8_t MOSI, uint8_t MISO, uint8_t RESET, uint8_t POWER, uint32_t spi_speed) {
_SS_PIN = SS;
_CLK_PIN = CLK;
_MOSI_PIN = MOSI;
_MISO_PIN = MISO;
_RESET_PIN = RESET;
_POWER_PIN = POWER;
pinMode(_SS_PIN, OUTPUT);
pinMode(_RESET_PIN, OUTPUT);
digitalWrite(_SS_PIN, HIGH);
digitalWrite(_RESET_PIN, HIGH);
set_power(ZBS_ON);
pinMode(_CLK_PIN, OUTPUT);
pinMode(_MOSI_PIN, OUTPUT);
pinMode(_MISO_PIN, INPUT);
pinMode(_RESET_PIN, OUTPUT);
digitalWrite(_SS_PIN, HIGH);
digitalWrite(_CLK_PIN, LOW);
digitalWrite(_MOSI_PIN, HIGH);
digitalWrite(_RESET_PIN, HIGH);
set_power(ZBS_ON);
if(!spi)spi = new SPIClass(HSPI);
spiSettings = SPISettings(spi_speed, MSBFIRST, SPI_MODE0);
spi_ready = 0;
if (spi_speed != 8000000) {
after_byte_delay = 10;
} else {
after_byte_delay = 10;
}
enable_debug();
return check_connection();
}
void ZBS_interface::setSpeed(uint32_t speed){
spiSettings = SPISettings(speed, MSBFIRST, SPI_MODE0);
}
ZBS_interface::~ZBS_interface(){
delete spi;
}
void ZBS_interface::set_power(uint8_t state) {
pinMode(ZBS_POWER1, INPUT);
pinMode(ZBS_POWER2, INPUT);
digitalWrite(ZBS_POWER1, state);
digitalWrite(ZBS_POWER2, state);
pinMode(ZBS_POWER1, OUTPUT);
pinMode(ZBS_POWER2, OUTPUT);
if (_POWER_PIN != -1) {
if (state) {
ledcSetup(0, 20000, 8);
ledcWrite(0, 255);
ledcAttachPin(_POWER_PIN, 0);
pinMode(_POWER_PIN, OUTPUT);
for (uint8_t c = 254; c != 0xFF; c--) {
ledcWrite(0, c);
vTaskDelay(1 / portTICK_PERIOD_MS);
}
digitalWrite(_POWER_PIN, LOW);
ledcDetachPin(_POWER_PIN);
digitalWrite(_POWER_PIN, LOW);
} else {
pinMode(_POWER_PIN, OUTPUT);
digitalWrite(_POWER_PIN, HIGH);
}
}
}
void ZBS_interface::enable_debug() {
@@ -81,6 +98,7 @@ void ZBS_interface::enable_debug() {
}
void ZBS_interface::reset() {
spi->end();
pinMode(_SS_PIN, INPUT);
pinMode(_CLK_PIN, INPUT);
pinMode(_MOSI_PIN, INPUT);
@@ -96,18 +114,14 @@ void ZBS_interface::reset() {
void ZBS_interface::send_byte(uint8_t data) {
digitalWrite(_SS_PIN, LOW);
delayMicroseconds(5);
for (int i = 0; i < 8; i++) {
if (data & 0x80) {
digitalWrite(_MOSI_PIN, HIGH);
} else {
digitalWrite(_MOSI_PIN, LOW);
}
delayMicroseconds(ZBS_spi_delay);
digitalWrite(_CLK_PIN, HIGH);
delayMicroseconds(ZBS_spi_delay);
digitalWrite(_CLK_PIN, LOW);
data <<= 1;
if (!spi_ready) {
spi_ready = 1;
spi->begin(_CLK_PIN, _MISO_PIN, _MOSI_PIN);
}
spi->beginTransaction(spiSettings);
spi->transfer(data);
spi->endTransaction();
delayMicroseconds(2);
digitalWrite(_SS_PIN, HIGH);
}
@@ -116,16 +130,13 @@ uint8_t ZBS_interface::read_byte() {
uint8_t data = 0x00;
digitalWrite(_SS_PIN, LOW);
delayMicroseconds(5);
for (int i = 0; i < 8; i++) {
data <<= 1;
if (digitalRead(_MISO_PIN)) {
data |= 1;
}
delayMicroseconds(ZBS_spi_delay);
digitalWrite(_CLK_PIN, HIGH);
delayMicroseconds(ZBS_spi_delay);
digitalWrite(_CLK_PIN, LOW);
if (!spi_ready) {
spi_ready = 1;
spi->begin(_CLK_PIN, _MISO_PIN, _MOSI_PIN);
}
spi->beginTransaction(spiSettings);
data = spi->transfer(0xff);
spi->endTransaction();
delayMicroseconds(2);
digitalWrite(_SS_PIN, HIGH);
return data;
@@ -135,7 +146,7 @@ void ZBS_interface::write_byte(uint8_t cmd, uint8_t addr, uint8_t data) {
send_byte(cmd);
send_byte(addr);
send_byte(data);
delay(1);
delayMicroseconds(after_byte_delay);
}
uint8_t ZBS_interface::read_byte(uint8_t cmd, uint8_t addr) {
@@ -143,7 +154,7 @@ uint8_t ZBS_interface::read_byte(uint8_t cmd, uint8_t addr) {
send_byte(cmd);
send_byte(addr);
data = read_byte();
delay(1);
delayMicroseconds(after_byte_delay);
return data;
}
@@ -152,7 +163,7 @@ void ZBS_interface::write_flash(uint16_t addr, uint8_t data) {
send_byte(addr >> 8);
send_byte(addr);
send_byte(data);
delay(1);
delayMicroseconds(after_byte_delay);
}
uint8_t ZBS_interface::read_flash(uint16_t addr) {
@@ -161,7 +172,7 @@ uint8_t ZBS_interface::read_flash(uint16_t addr) {
send_byte(addr >> 8);
send_byte(addr);
data = read_byte();
delay(1);
delayMicroseconds(after_byte_delay);
return data;
}
@@ -210,5 +221,3 @@ void ZBS_interface::erase_infoblock() {
send_byte(0x00);
delay(100);
}
ZBS_interface zbs;