Refactor Arduino Slave

This commit is contained in:
Theo Arends 2019-10-21 12:25:22 +02:00
parent 4d21a47edb
commit aaf6f90507
3 changed files with 92 additions and 77 deletions

View File

@ -542,9 +542,8 @@
//#define USE_A4988_STEPPER // Add support for A4988/DRV8825 stepper-motor-driver-circuit (+10k5 code) //#define USE_A4988_STEPPER // Add support for A4988/DRV8825 stepper-motor-driver-circuit (+10k5 code)
//#define USE_ARDUINO_SLAVE // Add support for Arduino Uno/Pro Mini via serial interface including flashing (+2k3 code, 44 mem) //#define USE_ARDUINO_SLAVE // Add support for Arduino Uno/Pro Mini via serial interface including flashing (+2k3 code, 44 mem)
// #define USE_ARDUINO_FLASH_SPEED 57600 // Usually 57600 for 3.3V variants and 115200 for 5V variants #define USE_ARDUINO_FLASH_SPEED 57600 // Usually 57600 for 3.3V variants and 115200 for 5V variants
// #define USE_ARDUINO_SERIAL_SPEED 57600 // Depends on the sketch that is running on the Uno/Pro Mini #define USE_ARDUINO_SERIAL_SPEED 57600 // Depends on the sketch that is running on the Uno/Pro Mini
// #define USE_ARDUINO_INVERT_RESET
// -- End of general directives ------------------- // -- End of general directives -------------------

View File

@ -210,7 +210,8 @@ enum UserSelectablePins {
GPIO_EXS_ENABLE, // EXS MCU Enable GPIO_EXS_ENABLE, // EXS MCU Enable
GPIO_ARDUINO_TXD, // Arduino Slave TX GPIO_ARDUINO_TXD, // Arduino Slave TX
GPIO_ARDUINO_RXD, // Arduino Slave RX GPIO_ARDUINO_RXD, // Arduino Slave RX
GPIO_ARDUINO_RESET, // Arduino Reset Pin GPIO_ARDUINO_RST, // Arduino Reset Pin
GPIO_ARDUINO_RST_INV, // Arduino Reset Pin inverted
GPIO_SENSOR_END }; GPIO_SENSOR_END };
// Programmer selectable GPIO functionality // Programmer selectable GPIO functionality
@ -289,7 +290,7 @@ const char kSensorNames[] PROGMEM =
D_SENSOR_DDSU666_TX "|" D_SENSOR_DDSU666_RX "|" D_SENSOR_DDSU666_TX "|" D_SENSOR_DDSU666_RX "|"
D_SENSOR_SM2135_CLK "|" D_SENSOR_SM2135_DAT "|" D_SENSOR_SM2135_CLK "|" D_SENSOR_SM2135_DAT "|"
D_SENSOR_DEEPSLEEP "|" D_SENSOR_EXS_ENABLE "|" D_SENSOR_DEEPSLEEP "|" D_SENSOR_EXS_ENABLE "|"
D_SENSOR_ARDUINO_TX "|" D_SENSOR_ARDUINO_RX "|" D_SENSOR_ARDUINO_RESET "|" D_SENSOR_ARDUINO_TX "|" D_SENSOR_ARDUINO_RX "|" D_SENSOR_ARDUINO_RESET "|" D_SENSOR_ARDUINO_RESET "i|"
; ;
const char kSensorNamesFixed[] PROGMEM = const char kSensorNamesFixed[] PROGMEM =
@ -705,7 +706,8 @@ const uint8_t kGpioNiceList[] PROGMEM = {
#ifdef USE_ARDUINO_SLAVE #ifdef USE_ARDUINO_SLAVE
GPIO_ARDUINO_TXD, // Arduino Slave TX GPIO_ARDUINO_TXD, // Arduino Slave TX
GPIO_ARDUINO_RXD, // Arduino Slave RX GPIO_ARDUINO_RXD, // Arduino Slave RX
GPIO_ARDUINO_RESET, // Arduino Reset Pin GPIO_ARDUINO_RST, // Arduino Reset Pin
GPIO_ARDUINO_RST_INV, // Arduino Reset Pin inverted
#endif #endif
#ifdef USE_RDM6300 #ifdef USE_RDM6300
GPIO_RDM6300_RX, GPIO_RDM6300_RX,

View File

@ -18,9 +18,11 @@
*/ */
#ifdef USE_ARDUINO_SLAVE #ifdef USE_ARDUINO_SLAVE
/*********************************************************************************************\
* Arduino slave
\*********************************************************************************************/
#include <TasmotaSerial.h> #define XDRV_31 31
#include <ArduinoHexParse.h>
#define CONST_STK_CRC_EOP 0x20 #define CONST_STK_CRC_EOP 0x20
@ -32,48 +34,47 @@
#define CMND_STK_LOAD_ADDRESS 0x55 #define CMND_STK_LOAD_ADDRESS 0x55
#define CMND_STK_PROG_PAGE 0x64 #define CMND_STK_PROG_PAGE 0x64
uint32_t as_spi_hex_size = 0; #include <TasmotaSerial.h>
uint8_t as_spi_sector_start = 0x96; #include <ArduinoHexParse.h>
uint8_t as_spi_sector_counter = 0x96;
uint8_t as_spi_sector_cursor = 0;
bool as_flashing = false;
uint8_t as_type = 0; struct ASLAVE {
uint32_t spi_hex_size = 0;
uint32_t spi_sector_counter = 0;
uint8_t spi_sector_cursor = 0;
uint8_t inverted = LOW;
bool type = false;
bool flashing = false;
} ASlave;
TasmotaSerial *ArduinoSlave_Serial; TasmotaSerial *ArduinoSlave_Serial;
#define XDRV_31 31 uint32_t ArduinoSlaveFlashStart(void)
{
return (ESP.getSketchSize() / SPI_FLASH_SEC_SIZE) + 2; // Stay on the safe side
}
uint8_t ArduinoSlave_UpdateInit(void) uint8_t ArduinoSlave_UpdateInit(void)
{ {
as_spi_hex_size = 0; ASlave.spi_hex_size = 0;
as_spi_sector_counter = as_spi_sector_start; // Reset the pre-defined write address where firmware will temporarily be stored ASlave.spi_sector_counter = ArduinoSlaveFlashStart(); // Reset the pre-defined write address where firmware will temporarily be stored
as_spi_sector_cursor = 0; ASlave.spi_sector_cursor = 0;
return 0; return 0;
} }
void ArduinoSlave_Reset(void) void ArduinoSlave_Reset(void)
{ {
if (as_type) { if (ASlave.type) {
#ifdef USE_ARDUINO_INVERT_RESET digitalWrite(pin[GPIO_ARDUINO_RST], !ASlave.inverted);
digitalWrite(pin[GPIO_ARDUINO_RESET], LOW);
delay(1); delay(1);
digitalWrite(pin[GPIO_ARDUINO_RESET], HIGH); digitalWrite(pin[GPIO_ARDUINO_RST], ASlave.inverted);
delay(1); delay(1);
digitalWrite(pin[GPIO_ARDUINO_RESET], LOW); digitalWrite(pin[GPIO_ARDUINO_RST], !ASlave.inverted);
delay(5); delay(5);
#else
digitalWrite(pin[GPIO_ARDUINO_RESET], HIGH);
delay(1);
digitalWrite(pin[GPIO_ARDUINO_RESET], LOW);
delay(1);
digitalWrite(pin[GPIO_ARDUINO_RESET], HIGH);
delay(5);
#endif
} }
} }
uint8_t ArduinoSlave_waitForSerialData(int dataCount, int timeout) { uint8_t ArduinoSlave_waitForSerialData(int dataCount, int timeout)
{
int timer = 0; int timer = 0;
while (timer < timeout) { while (timer < timeout) {
if (ArduinoSlave_Serial->available() >= dataCount) { if (ArduinoSlave_Serial->available() >= dataCount) {
@ -85,24 +86,27 @@ uint8_t ArduinoSlave_waitForSerialData(int dataCount, int timeout) {
return 0; return 0;
} }
byte ArduinoSlave_sendBytes(byte* bytes, int count) { uint8_t ArduinoSlave_sendBytes(uint8_t* bytes, int count)
{
ArduinoSlave_Serial->write(bytes, count); ArduinoSlave_Serial->write(bytes, count);
ArduinoSlave_waitForSerialData(2, 1000); ArduinoSlave_waitForSerialData(2, 1000);
byte sync = ArduinoSlave_Serial->read(); uint8_t sync = ArduinoSlave_Serial->read();
byte ok = ArduinoSlave_Serial->read(); uint8_t ok = ArduinoSlave_Serial->read();
if (sync == 0x14 && ok == 0x10) { if (sync == 0x14 && ok == 0x10) {
return 1; return 1;
} }
return 0; return 0;
} }
byte ArduinoSlave_execCmd(byte cmd) { uint8_t ArduinoSlave_execCmd(uint8_t cmd)
byte bytes[] = { cmd, CONST_STK_CRC_EOP }; {
uint8_t bytes[] = { cmd, CONST_STK_CRC_EOP };
return ArduinoSlave_sendBytes(bytes, 2); return ArduinoSlave_sendBytes(bytes, 2);
} }
byte ArduinoSlave_execParam(byte cmd, byte* params, int count) { uint8_t ArduinoSlave_execParam(uint8_t cmd, uint8_t* params, int count)
byte bytes[32]; {
uint8_t bytes[32];
bytes[0] = cmd; bytes[0] = cmd;
int i = 0; int i = 0;
while (i < count) { while (i < count) {
@ -120,10 +124,10 @@ uint8_t ArduinoSlave_exitProgMode(void)
void ArduinoSlave_SetupFlash(void) void ArduinoSlave_SetupFlash(void)
{ {
byte ProgParams[] = {0x86,0x00,0x00,0x01,0x01,0x01,0x01,0x03,0xff,0xff,0xff,0xff,0x00,0x80,0x04,0x00,0x00,0x00,0x80,0x00}; uint8_t ProgParams[] = {0x86,0x00,0x00,0x01,0x01,0x01,0x01,0x03,0xff,0xff,0xff,0xff,0x00,0x80,0x04,0x00,0x00,0x00,0x80,0x00};
byte ExtProgParams[] = {0x05,0x04,0xd7,0xc2,0x00}; uint8_t ExtProgParams[] = {0x05,0x04,0xd7,0xc2,0x00};
ArduinoSlave_Serial->begin(USE_ARDUINO_FLASH_SPEED); ArduinoSlave_Serial->begin(USE_ARDUINO_FLASH_SPEED);
if (ArduinoSlave_Serial->hardwareSerial()) { if (ArduinoSlave_Serial->hardwareSerial()) {
ClaimSerial(); ClaimSerial();
} }
ArduinoSlave_Reset(); ArduinoSlave_Reset();
@ -133,14 +137,15 @@ void ArduinoSlave_SetupFlash(void)
ArduinoSlave_execCmd(CMND_STK_ENTER_PROGMODE); // Enter programming mode ArduinoSlave_execCmd(CMND_STK_ENTER_PROGMODE); // Enter programming mode
} }
uint8_t ArduinoSlave_loadAddress(byte adrHi, byte adrLo) { uint8_t ArduinoSlave_loadAddress(uint8_t adrHi, uint8_t adrLo)
byte params[] = { adrHi, adrLo }; {
uint8_t params[] = { adrHi, adrLo };
return ArduinoSlave_execParam(CMND_STK_LOAD_ADDRESS, params, sizeof(params)); return ArduinoSlave_execParam(CMND_STK_LOAD_ADDRESS, params, sizeof(params));
} }
void ArduinoSlave_FlashPage(byte* address, byte* data) void ArduinoSlave_FlashPage(uint8_t* address, uint8_t* data)
{ {
byte Header[] = {CMND_STK_PROG_PAGE, 0x00, 0x80, 0x46}; uint8_t Header[] = {CMND_STK_PROG_PAGE, 0x00, 0x80, 0x46};
ArduinoSlave_loadAddress(address[1], address[0]); ArduinoSlave_loadAddress(address[1], address[0]);
ArduinoSlave_Serial->write(Header, 4); ArduinoSlave_Serial->write(Header, 4);
for (int i = 0; i < 128; i++) { for (int i = 0; i < 128; i++) {
@ -165,24 +170,25 @@ void ArduinoSlave_Flash(void)
ArduinoSlave_SetupFlash(); ArduinoSlave_SetupFlash();
flash_buffer = new char[SPI_FLASH_SEC_SIZE]; flash_buffer = new char[SPI_FLASH_SEC_SIZE];
uint32_t flash_start = ArduinoSlaveFlashStart() * SPI_FLASH_SEC_SIZE;
while (reading) { while (reading) {
ESP.flashRead(0x96000 + read, (uint32_t*)flash_buffer, FLASH_SECTOR_SIZE); ESP.flashRead(flash_start + read, (uint32_t*)flash_buffer, SPI_FLASH_SEC_SIZE);
read = read + FLASH_SECTOR_SIZE; read = read + SPI_FLASH_SEC_SIZE;
if (read >= as_spi_hex_size) { if (read >= ASlave.spi_hex_size) {
reading = false; reading = false;
} }
for (uint16_t ca=0; ca<FLASH_SECTOR_SIZE; ca++) { for (uint32_t ca = 0; ca < SPI_FLASH_SEC_SIZE; ca++) {
processed++; processed++;
if (processed <= as_spi_hex_size) { if (processed <= ASlave.spi_hex_size) {
if (':' == flash_buffer[ca]) { if (':' == flash_buffer[ca]) {
position = 0; position = 0;
} }
if (0x0D == flash_buffer[ca]) { if (0x0D == flash_buffer[ca]) {
thishexline[position] = 0; thishexline[position] = 0;
hexParse.ParseLine((byte*)thishexline); hexParse.ParseLine((uint8_t*)thishexline);
if (hexParse.IsFlashPageReady()) { if (hexParse.IsFlashPageReady()) {
byte* page = hexParse.GetFlashPage(); uint8_t* page = hexParse.GetFlashPage();
byte* address = hexParse.GetLoadAddress(); uint8_t* address = hexParse.GetLoadAddress();
ArduinoSlave_FlashPage(address, page); ArduinoSlave_FlashPage(address, page);
} }
} else { } else {
@ -194,48 +200,54 @@ void ArduinoSlave_Flash(void)
} }
} }
} }
as_flashing = false; ASlave.flashing = false;
ArduinoSlave_exitProgMode(); ArduinoSlave_exitProgMode();
restart_flag = 2; restart_flag = 2;
} }
void ArduinoSlave_SetFlagFlashing(bool value) void ArduinoSlave_SetFlagFlashing(bool value)
{ {
as_flashing = value; ASlave.flashing = value;
} }
bool ArduinoSlave_GetFlagFlashing(void) bool ArduinoSlave_GetFlagFlashing(void)
{ {
return as_flashing; return ASlave.flashing ;
} }
void ArduinoSlave_WriteBuffer(uint8_t *buf, size_t size) void ArduinoSlave_WriteBuffer(uint8_t *buf, size_t size)
{ {
if (0 == as_spi_sector_cursor) { // Starting a new sector write so we need to erase it first if (0 == ASlave.spi_sector_cursor) { // Starting a new sector write so we need to erase it first
ESP.flashEraseSector(as_spi_sector_counter); ESP.flashEraseSector(ASlave.spi_sector_counter);
} }
as_spi_sector_cursor++; ASlave.spi_sector_cursor++;
ESP.flashWrite((as_spi_sector_counter * 0x1000)+((as_spi_sector_cursor-1)*2048), (uint32_t*)buf, size); ESP.flashWrite((ASlave.spi_sector_counter * SPI_FLASH_SEC_SIZE) + ((ASlave.spi_sector_cursor-1)*2048), (uint32_t*)buf, size);
as_spi_hex_size = as_spi_hex_size + size; ASlave.spi_hex_size = ASlave.spi_hex_size + size;
if (2 == as_spi_sector_cursor) { // The web upload sends 2048 bytes at a time so keep track of the cursor position to reset it for the next flash sector erase if (2 == ASlave.spi_sector_cursor) { // The web upload sends 2048 bytes at a time so keep track of the cursor position to reset it for the next flash sector erase
as_spi_sector_cursor = 0; ASlave.spi_sector_cursor = 0;
as_spi_sector_counter++; ASlave.spi_sector_counter++;
} }
} }
void ArduinoSlave_Init(void) void ArduinoSlave_Init(void)
{ {
if (as_type) { if (ASlave.type) {
return; return;
} }
if ((pin[GPIO_ARDUINO_RXD] < 99) && (pin[GPIO_ARDUINO_TXD] < 99) && (pin[GPIO_ARDUINO_RESET] < 99)) { if ((pin[GPIO_ARDUINO_RXD] < 99) && (pin[GPIO_ARDUINO_TXD] < 99) &&
((pin[GPIO_ARDUINO_RST] < 99) || (pin[GPIO_ARDUINO_RST_INV] < 99))) {
ArduinoSlave_Serial = new TasmotaSerial(pin[GPIO_ARDUINO_RXD], pin[GPIO_ARDUINO_TXD], 1, 0, 200); ArduinoSlave_Serial = new TasmotaSerial(pin[GPIO_ARDUINO_RXD], pin[GPIO_ARDUINO_TXD], 1, 0, 200);
if (ArduinoSlave_Serial->begin(USE_ARDUINO_SERIAL_SPEED)) { if (ArduinoSlave_Serial->begin(USE_ARDUINO_SERIAL_SPEED)) {
if (ArduinoSlave_Serial->hardwareSerial()) { if (ArduinoSlave_Serial->hardwareSerial()) {
ClaimSerial(); ClaimSerial();
} }
pinMode(pin[GPIO_ARDUINO_RESET], OUTPUT); if (pin[GPIO_ARDUINO_RST_INV] < 99) {
as_type = 1; pin[GPIO_ARDUINO_RST] = pin[GPIO_ARDUINO_RST_INV];
pin[GPIO_ARDUINO_RST_INV] = 99;
ASlave.inverted = HIGH;
}
pinMode(pin[GPIO_ARDUINO_RST], OUTPUT);
ASlave.type = true;
ArduinoSlave_Reset(); ArduinoSlave_Reset();
AddLog_P2(LOG_LEVEL_INFO, PSTR("Arduino Slave Enabled")); AddLog_P2(LOG_LEVEL_INFO, PSTR("Arduino Slave Enabled"));
} }
@ -244,11 +256,11 @@ void ArduinoSlave_Init(void)
void ArduinoSlave_Show(bool json) void ArduinoSlave_Show(bool json)
{ {
if (as_type) { if (ASlave.type) {
char buffer[100];
ArduinoSlave_Serial->flush(); ArduinoSlave_Serial->flush();
ArduinoSlave_Serial->print("JSON"); ArduinoSlave_Serial->print("JSON");
ArduinoSlave_Serial->find(char(0xFE)); ArduinoSlave_Serial->find(char(0xFE));
char buffer[100];
uint16_t haveread = ArduinoSlave_Serial->readBytesUntil(char(0xFF), buffer, sizeof(buffer)-1); uint16_t haveread = ArduinoSlave_Serial->readBytesUntil(char(0xFF), buffer, sizeof(buffer)-1);
buffer[haveread] = '\0'; buffer[haveread] = '\0';
if (json) { if (json) {
@ -257,9 +269,14 @@ void ArduinoSlave_Show(bool json)
} }
} }
/*********************************************************************************************\
* Interface
\*********************************************************************************************/
bool Xdrv31(uint8_t function) bool Xdrv31(uint8_t function)
{ {
bool result = false; bool result = false;
switch (function) { switch (function) {
case FUNC_EVERY_SECOND: case FUNC_EVERY_SECOND:
ArduinoSlave_Init(); ArduinoSlave_Init();
@ -267,11 +284,8 @@ bool Xdrv31(uint8_t function)
case FUNC_JSON_APPEND: case FUNC_JSON_APPEND:
ArduinoSlave_Show(1); ArduinoSlave_Show(1);
break; break;
case FUNC_COMMAND_DRIVER:
break;
default:
break;
} }
return result;
} }
#endif // USE_ARDUINO_SLAVE #endif // USE_ARDUINO_SLAVE