mirror of https://github.com/commaai/panda.git
refactor SPI and make flasher reliable
This commit is contained in:
parent
a2523f2d3a
commit
0a5a8ab5ec
|
@ -12,9 +12,6 @@
|
||||||
#include "libc.h"
|
#include "libc.h"
|
||||||
#include "gpio.h"
|
#include "gpio.h"
|
||||||
|
|
||||||
|
|
||||||
void spi_cb_rx(uint8_t *data, int len) {};
|
|
||||||
|
|
||||||
#include "drivers/drivers.h"
|
#include "drivers/drivers.h"
|
||||||
#include "drivers/spi.h"
|
#include "drivers/spi.h"
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
//#define DEBUG
|
//#define DEBUG
|
||||||
//#define DEBUG_USB
|
//#define DEBUG_USB
|
||||||
|
//#define DEBUG_SPI
|
||||||
|
|
||||||
#ifdef STM32F4
|
#ifdef STM32F4
|
||||||
#define PANDA
|
#define PANDA
|
||||||
|
|
|
@ -70,8 +70,7 @@ void timer_init(TIM_TypeDef *TIM, int psc);
|
||||||
// IRQs: DMA2_Stream2, DMA2_Stream3, EXTI4
|
// IRQs: DMA2_Stream2, DMA2_Stream3, EXTI4
|
||||||
|
|
||||||
void spi_init();
|
void spi_init();
|
||||||
void spi_cb_rx(uint8_t *data, int len);
|
int spi_cb_rx(uint8_t *data, int len, uint8_t *data_out);
|
||||||
void spi_tx_dma(void *addr, int len);
|
|
||||||
|
|
||||||
|
|
||||||
// ********************* CAN *********************
|
// ********************* CAN *********************
|
||||||
|
|
|
@ -17,6 +17,10 @@ void spi_init() {
|
||||||
NVIC_EnableIRQ(DMA2_Stream3_IRQn);
|
NVIC_EnableIRQ(DMA2_Stream3_IRQn);
|
||||||
//NVIC_EnableIRQ(SPI1_IRQn);
|
//NVIC_EnableIRQ(SPI1_IRQn);
|
||||||
|
|
||||||
|
// reset handshake back to pull up
|
||||||
|
GPIOB->MODER &= ~(GPIO_MODER_MODER0);
|
||||||
|
GPIOB->PUPDR |= GPIO_PUPDR_PUPDR0_0;
|
||||||
|
|
||||||
// setup interrupt on falling edge of SPI enable (on PA4)
|
// setup interrupt on falling edge of SPI enable (on PA4)
|
||||||
SYSCFG->EXTICR[2] = SYSCFG_EXTICR2_EXTI4_PA;
|
SYSCFG->EXTICR[2] = SYSCFG_EXTICR2_EXTI4_PA;
|
||||||
EXTI->IMR = (1 << 4);
|
EXTI->IMR = (1 << 4);
|
||||||
|
@ -39,6 +43,12 @@ void spi_tx_dma(void *addr, int len) {
|
||||||
DMA2_Stream3->CR |= DMA_SxCR_TCIE;
|
DMA2_Stream3->CR |= DMA_SxCR_TCIE;
|
||||||
|
|
||||||
SPI1->CR2 |= SPI_CR2_TXDMAEN;
|
SPI1->CR2 |= SPI_CR2_TXDMAEN;
|
||||||
|
|
||||||
|
// signal data is ready by driving low
|
||||||
|
// esp must be configured as input by this point
|
||||||
|
GPIOB->MODER &= ~(GPIO_MODER_MODER0);
|
||||||
|
GPIOB->MODER |= GPIO_MODER_MODER0_0;
|
||||||
|
GPIOB->ODR &= ~(GPIO_ODR_ODR_0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void spi_rx_dma(void *addr, int len) {
|
void spi_rx_dma(void *addr, int len) {
|
||||||
|
@ -64,11 +74,22 @@ void spi_rx_dma(void *addr, int len) {
|
||||||
|
|
||||||
// ***************************** SPI IRQs *****************************
|
// ***************************** SPI IRQs *****************************
|
||||||
|
|
||||||
|
// can't go on the stack cause it's DMAed
|
||||||
|
uint8_t spi_tx_buf[0x44];
|
||||||
|
|
||||||
// SPI RX
|
// SPI RX
|
||||||
void DMA2_Stream2_IRQHandler(void) {
|
void DMA2_Stream2_IRQHandler(void) {
|
||||||
// ack
|
// ack
|
||||||
DMA2->LIFCR = DMA_LIFCR_CTCIF2;
|
DMA2->LIFCR = DMA_LIFCR_CTCIF2;
|
||||||
spi_cb_rx(spi_buf, 0x13);
|
int *resp_len = (int*)spi_tx_buf;
|
||||||
|
memset(spi_tx_buf, 0xaa, 0x44);
|
||||||
|
*resp_len = spi_cb_rx(spi_buf, 0x13, spi_tx_buf+4);
|
||||||
|
#ifdef DEBUG_SPI
|
||||||
|
puts("SPI write: ");
|
||||||
|
puth(*resp_len);
|
||||||
|
puts("\n");
|
||||||
|
#endif
|
||||||
|
spi_tx_dma(spi_tx_buf, *resp_len + 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
// SPI TX
|
// SPI TX
|
||||||
|
@ -76,6 +97,10 @@ void DMA2_Stream3_IRQHandler(void) {
|
||||||
// ack
|
// ack
|
||||||
DMA2->LIFCR = DMA_LIFCR_CTCIF3;
|
DMA2->LIFCR = DMA_LIFCR_CTCIF3;
|
||||||
|
|
||||||
|
#ifdef DEBUG_SPI
|
||||||
|
puts("SPI handshake\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
// reset handshake back to pull up
|
// reset handshake back to pull up
|
||||||
GPIOB->MODER &= ~(GPIO_MODER_MODER0);
|
GPIOB->MODER &= ~(GPIO_MODER_MODER0);
|
||||||
GPIOB->PUPDR |= GPIO_PUPDR_PUPDR0_0;
|
GPIOB->PUPDR |= GPIO_PUPDR_PUPDR0_0;
|
||||||
|
|
27
board/main.c
27
board/main.c
|
@ -358,25 +358,20 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, int hardwired) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef PANDA
|
#ifdef PANDA
|
||||||
|
int spi_cb_rx(uint8_t *data, int len, uint8_t *data_out) {
|
||||||
// can't go on the stack cause it's DMAed
|
|
||||||
uint8_t spi_tx_buf[0x44];
|
|
||||||
|
|
||||||
void spi_cb_rx(uint8_t *data, int len) {
|
|
||||||
memset(spi_tx_buf, 0xaa, 0x44);
|
|
||||||
// data[0] = endpoint
|
// data[0] = endpoint
|
||||||
// data[2] = length
|
// data[2] = length
|
||||||
// data[4:] = data
|
// data[4:] = data
|
||||||
int *resp_len = (int*)spi_tx_buf;
|
|
||||||
*resp_len = 0;
|
int resp_len = 0;
|
||||||
switch (data[0]) {
|
switch (data[0]) {
|
||||||
case 0:
|
case 0:
|
||||||
// control transfer
|
// control transfer
|
||||||
*resp_len = usb_cb_control_msg((USB_Setup_TypeDef *)(data+4), spi_tx_buf+4, 0);
|
resp_len = usb_cb_control_msg((USB_Setup_TypeDef *)(data+4), data_out, 0);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
// ep 1, read
|
// ep 1, read
|
||||||
*resp_len = usb_cb_ep1_in(spi_tx_buf+4, 0x40, 0);
|
resp_len = usb_cb_ep1_in(data_out, 0x40, 0);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
// ep 2, send serial
|
// ep 2, send serial
|
||||||
|
@ -387,18 +382,12 @@ void spi_cb_rx(uint8_t *data, int len) {
|
||||||
usb_cb_ep3_out(data+4, data[2], 0);
|
usb_cb_ep3_out(data+4, data[2], 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
spi_tx_dma(spi_tx_buf, 0x44);
|
return resp_len;
|
||||||
|
|
||||||
// signal data is ready by driving low
|
|
||||||
// esp must be configured as input by this point
|
|
||||||
GPIOB->MODER &= ~(GPIO_MODER_MODER0);
|
|
||||||
GPIOB->MODER |= GPIO_MODER_MODER0_0;
|
|
||||||
GPIOB->ODR &= ~(GPIO_ODR_ODR_0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
void spi_cb_rx(uint8_t *data, int len) {};
|
int spi_cb_rx(uint8_t *data, int len) { return 0; };
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -460,7 +449,7 @@ int main() {
|
||||||
|
|
||||||
// set PWM
|
// set PWM
|
||||||
fan_init();
|
fan_init();
|
||||||
fan_set_speed(65535);
|
fan_set_speed(0);
|
||||||
|
|
||||||
puts("**** INTERRUPTS ON ****\n");
|
puts("**** INTERRUPTS ON ****\n");
|
||||||
|
|
||||||
|
|
|
@ -1,28 +1,84 @@
|
||||||
/*void lock_bootloader() {
|
// can't go on the stack cause it's DMAed
|
||||||
if (FLASH->OPTCR & FLASH_OPTCR_nWRP_0) {
|
uint8_t spi_tx_buf[0x44];
|
||||||
FLASH->OPTKEYR = 0x08192A3B;
|
|
||||||
FLASH->OPTKEYR = 0x4C5D6E7F;
|
|
||||||
|
|
||||||
// write protect the bootloader
|
uint32_t *prog_ptr;
|
||||||
FLASH->OPTCR &= ~FLASH_OPTCR_nWRP_0;
|
int unlocked = 0;
|
||||||
|
|
||||||
// OPT program
|
int spi_cb_rx(uint8_t *data, int len, uint8_t *data_out) {
|
||||||
FLASH->OPTCR |= FLASH_OPTCR_OPTSTRT;
|
// get serial number even in bootstub mode
|
||||||
while (FLASH->SR & FLASH_SR_BSY);
|
if (memcmp("\x00\x00\x00\x00\x40\xD0\x00\x00\x00\x00\x20\x00", data, 0xC) == 0) {
|
||||||
|
memcpy(data_out, (void *)0x1fff79e0, 0x20);
|
||||||
// relock it
|
return 0x20;
|
||||||
FLASH->OPTCR |= FLASH_OPTCR_OPTLOCK;
|
|
||||||
|
|
||||||
// reset
|
|
||||||
NVIC_SystemReset();
|
|
||||||
}
|
}
|
||||||
}*/
|
|
||||||
|
// flasher mode
|
||||||
|
if (data[0] == (0xff^data[1]) &&
|
||||||
|
data[2] == (0xff^data[3])) {
|
||||||
|
int sec;
|
||||||
|
memset(data_out, 0, 4);
|
||||||
|
memcpy(data_out+4, "\xde\xad\xd0\x0d", 4);
|
||||||
|
data_out[0] = 0xff;
|
||||||
|
data_out[2] = data[0];
|
||||||
|
data_out[3] = data[1];
|
||||||
|
switch (data[0]) {
|
||||||
|
case 0xf:
|
||||||
|
// echo
|
||||||
|
data_out[1] = 0xff;
|
||||||
|
break;
|
||||||
|
case 0x10:
|
||||||
|
// unlock flash
|
||||||
|
if (FLASH->CR & FLASH_CR_LOCK) {
|
||||||
|
FLASH->KEYR = 0x45670123;
|
||||||
|
FLASH->KEYR = 0xCDEF89AB;
|
||||||
|
data_out[1] = 0xff;
|
||||||
|
}
|
||||||
|
set_led(LED_GREEN, 1);
|
||||||
|
unlocked = 1;
|
||||||
|
prog_ptr = (uint32_t *)0x8004000;
|
||||||
|
break;
|
||||||
|
case 0x11:
|
||||||
|
// erase
|
||||||
|
sec = data[2] & 0xF;
|
||||||
|
// don't erase the bootloader
|
||||||
|
if (sec != 0 && sec < 12 && unlocked) {
|
||||||
|
FLASH->CR = (sec << 3) | FLASH_CR_SER;
|
||||||
|
FLASH->CR |= FLASH_CR_STRT;
|
||||||
|
while (FLASH->SR & FLASH_SR_BSY);
|
||||||
|
data_out[1] = 0xff;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x12:
|
||||||
|
if (data[2] <= 4 && unlocked) {
|
||||||
|
set_led(LED_RED, 0);
|
||||||
|
for (int i = 0; i < data[2]; i++) {
|
||||||
|
// program byte 1
|
||||||
|
FLASH->CR = FLASH_CR_PSIZE_1 | FLASH_CR_PG;
|
||||||
|
|
||||||
|
*prog_ptr = *(uint32_t*)(data+4+(i*4));
|
||||||
|
while (FLASH->SR & FLASH_SR_BSY);
|
||||||
|
|
||||||
|
//*(uint64_t*)(&spi_tx_buf[0x30+(i*4)]) = *prog_ptr;
|
||||||
|
prog_ptr++;
|
||||||
|
}
|
||||||
|
set_led(LED_RED, 1);
|
||||||
|
data_out[1] = 0xff;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x13:
|
||||||
|
// reset
|
||||||
|
NVIC_SystemReset();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 8;
|
||||||
|
}
|
||||||
|
|
||||||
void spi_flasher() {
|
void spi_flasher() {
|
||||||
// green LED on for flashing
|
__disable_irq();
|
||||||
GPIOC->MODER |= GPIO_MODER_MODER6_0;
|
|
||||||
GPIOC->ODR &= ~(1 << 6);
|
|
||||||
|
|
||||||
RCC->AHB1ENR |= RCC_AHB1ENR_DMA2EN;
|
RCC->AHB1ENR |= RCC_AHB1ENR_DMA2EN;
|
||||||
RCC->APB2ENR |= RCC_APB2ENR_SPI1EN;
|
RCC->APB2ENR |= RCC_APB2ENR_SPI1EN;
|
||||||
|
|
||||||
|
@ -32,112 +88,13 @@ void spi_flasher() {
|
||||||
GPIOA->AFR[0] = GPIO_AF5_SPI1 << (4*4) | GPIO_AF5_SPI1 << (5*4) |
|
GPIOA->AFR[0] = GPIO_AF5_SPI1 << (4*4) | GPIO_AF5_SPI1 << (5*4) |
|
||||||
GPIO_AF5_SPI1 << (6*4) | GPIO_AF5_SPI1 << (7*4);
|
GPIO_AF5_SPI1 << (6*4) | GPIO_AF5_SPI1 << (7*4);
|
||||||
|
|
||||||
|
// blue LED on for flashing
|
||||||
|
set_led(LED_BLUE, 1);
|
||||||
|
|
||||||
// flasher
|
// flasher
|
||||||
spi_init();
|
spi_init();
|
||||||
|
__enable_irq();
|
||||||
|
|
||||||
unsigned char spi_rx_buf[0x14];
|
while (1) { }
|
||||||
unsigned char spi_tx_buf[0x44];
|
|
||||||
|
|
||||||
int i;
|
|
||||||
int sec;
|
|
||||||
int rcv = 0;
|
|
||||||
int lastval = (GPIOA->IDR & (1 << 4));
|
|
||||||
uint32_t *prog_ptr = (uint32_t *)0x8004000;
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
int val = (GPIOA->IDR & (1 << 4));
|
|
||||||
if (!val && lastval) {
|
|
||||||
spi_rx_dma(spi_rx_buf, 0x14);
|
|
||||||
rcv = 1;
|
|
||||||
}
|
|
||||||
lastval = val;
|
|
||||||
|
|
||||||
if (rcv && (DMA2->LISR & DMA_LISR_TCIF2)) {
|
|
||||||
DMA2->LIFCR = DMA_LIFCR_CTCIF2;
|
|
||||||
|
|
||||||
rcv = 0;
|
|
||||||
memset(spi_tx_buf, 0, 0x44);
|
|
||||||
spi_tx_buf[0x40] = 0xde;
|
|
||||||
spi_tx_buf[0x41] = 0xad;
|
|
||||||
spi_tx_buf[0x42] = 0xd0;
|
|
||||||
spi_tx_buf[0x43] = 0x0d;
|
|
||||||
|
|
||||||
if (memcmp("\x00\x00\x00\x00\x40\xD0\x00\x00\x00\x00\x20\x00", spi_rx_buf, 0xC) == 0) {
|
|
||||||
*(uint32_t*)(&spi_tx_buf[0]) = 0x20;
|
|
||||||
memcpy(spi_tx_buf+4, (void *)0x1fff79e0, 0x20);
|
|
||||||
} else if (spi_rx_buf[0] == (0xff^spi_rx_buf[1]) &&
|
|
||||||
spi_rx_buf[2] == (0xff^spi_rx_buf[3])) {
|
|
||||||
spi_tx_buf[0] = 0xff;
|
|
||||||
*(uint32_t*)(&spi_tx_buf[4]) = FLASH->CR;
|
|
||||||
*(uint32_t*)(&spi_tx_buf[8]) = (uint32_t)prog_ptr;
|
|
||||||
// valid
|
|
||||||
switch (spi_rx_buf[0]) {
|
|
||||||
case 0x10:
|
|
||||||
// unlock flash
|
|
||||||
if (FLASH->CR & FLASH_CR_LOCK) {
|
|
||||||
FLASH->KEYR = 0x45670123;
|
|
||||||
FLASH->KEYR = 0xCDEF89AB;
|
|
||||||
spi_tx_buf[1] = 0xff;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 0x11:
|
|
||||||
// erase
|
|
||||||
sec = spi_rx_buf[2] & 0xF;
|
|
||||||
// don't erase the bootloader
|
|
||||||
if (sec != 0 && sec < 12) {
|
|
||||||
FLASH->CR = (sec << 3) | FLASH_CR_SER;
|
|
||||||
FLASH->CR |= FLASH_CR_STRT;
|
|
||||||
while (FLASH->SR & FLASH_SR_BSY);
|
|
||||||
spi_tx_buf[1] = 0xff;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 0x12:
|
|
||||||
if (spi_rx_buf[2] <= 4) {
|
|
||||||
set_led(LED_RED, 0);
|
|
||||||
for (i = 0; i < spi_rx_buf[2]; i++) {
|
|
||||||
// program byte 1
|
|
||||||
FLASH->CR = FLASH_CR_PSIZE_1 | FLASH_CR_PG;
|
|
||||||
|
|
||||||
*prog_ptr = *(uint32_t*)(spi_rx_buf+4+(i*4));
|
|
||||||
while (FLASH->SR & FLASH_SR_BSY);
|
|
||||||
|
|
||||||
*(uint64_t*)(&spi_tx_buf[0x30+(i*4)]) = *prog_ptr;
|
|
||||||
prog_ptr++;
|
|
||||||
}
|
|
||||||
set_led(LED_RED, 1);
|
|
||||||
spi_tx_buf[1] = 0xff;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 0x13:
|
|
||||||
// reset
|
|
||||||
NVIC_SystemReset();
|
|
||||||
break;
|
|
||||||
case 0x14:
|
|
||||||
// bootloader
|
|
||||||
/*enter_bootloader_mode = ENTER_BOOTLOADER_MAGIC;
|
|
||||||
NVIC_SystemReset();*/
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
memcpy(spi_tx_buf+0x10, spi_rx_buf, 0x14);
|
|
||||||
}
|
|
||||||
|
|
||||||
spi_tx_dma(spi_tx_buf, 0x44);
|
|
||||||
|
|
||||||
// signal data is ready by driving low
|
|
||||||
// esp must be configured as input by this point
|
|
||||||
GPIOB->MODER &= ~(GPIO_MODER_MODER0);
|
|
||||||
GPIOB->MODER |= GPIO_MODER_MODER0_0;
|
|
||||||
GPIOB->ODR &= ~(GPIO_ODR_ODR_0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DMA2->LISR & DMA_LISR_TCIF3) {
|
|
||||||
DMA2->LIFCR = DMA_LIFCR_CTCIF3;
|
|
||||||
|
|
||||||
// reset handshake back to pull up
|
|
||||||
GPIOB->MODER &= ~(GPIO_MODER_MODER0);
|
|
||||||
GPIOB->PUPDR |= GPIO_PUPDR_PUPDR0_0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -56,7 +56,9 @@ static int ICACHE_FLASH_ATTR __spi_comm(char *dat, int len, uint32_t *recvData,
|
||||||
SPIMasterSendData(SpiNum_HSPI, &spiData);
|
SPIMasterSendData(SpiNum_HSPI, &spiData);
|
||||||
|
|
||||||
// give the ST time to be ready, up to 1s
|
// give the ST time to be ready, up to 1s
|
||||||
for (int i = 0;(gpio_input_get() & (1 << 4)) && i < 100000; i++) os_delay_us(10);
|
for (int i = 0;(gpio_input_get() & (1 << 4)) && i < 100000; i++) {
|
||||||
|
os_delay_us(10);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: handle this better
|
// TODO: handle this better
|
||||||
if (gpio_input_get() & (1 << 4)) os_printf("ERROR: SPI receive failed\n");
|
if (gpio_input_get() & (1 << 4)) os_printf("ERROR: SPI receive failed\n");
|
||||||
|
@ -70,6 +72,10 @@ static int ICACHE_FLASH_ATTR __spi_comm(char *dat, int len, uint32_t *recvData,
|
||||||
SPIMasterRecvData(SpiNum_HSPI, &spiData);
|
SPIMasterRecvData(SpiNum_HSPI, &spiData);
|
||||||
int length = recvData[0];
|
int length = recvData[0];
|
||||||
|
|
||||||
|
if (length > 0x40) {
|
||||||
|
os_printf("SPI: BAD LENGTH RECEIVED\n");
|
||||||
|
}
|
||||||
|
|
||||||
// got response, 0x40 works, 0x44 does not
|
// got response, 0x40 works, 0x44 does not
|
||||||
spiData.data = recvData+1;
|
spiData.data = recvData+1;
|
||||||
spiData.dataLen = recvDataLen;
|
spiData.dataLen = recvDataLen;
|
||||||
|
|
|
@ -35,43 +35,60 @@ LOCAL os_timer_t ota_reboot_timer;
|
||||||
|
|
||||||
#define FIRMWARE_SIZE 503808
|
#define FIRMWARE_SIZE 503808
|
||||||
|
|
||||||
void st_flash() {
|
void ICACHE_FLASH_ATTR st_flash() {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
// stupid watchdog test
|
if (st_firmware != NULL) {
|
||||||
//system_soft_wdt_stop();
|
// stupid watchdog test
|
||||||
|
//system_soft_wdt_stop();
|
||||||
|
|
||||||
// boot mode
|
// boot mode
|
||||||
st_set_boot_mode(1);
|
os_printf("st_flash: enter boot mode\n");
|
||||||
|
st_set_boot_mode(1);
|
||||||
|
|
||||||
// unlock flash
|
// echo
|
||||||
st_cmd(0x10, 0, NULL);
|
os_printf("st_flash: wait for echo\n");
|
||||||
st_cmd(0xf, 0, NULL);
|
int i;
|
||||||
|
for (i = 0; i < 10; i++) {
|
||||||
|
if (st_cmd(0xf, 0, NULL) == 1) break;
|
||||||
|
os_printf(" miss: %d\n", i);
|
||||||
|
}
|
||||||
|
|
||||||
// erase sector 1
|
// unlock flash
|
||||||
st_cmd(0x11, 1, NULL);
|
os_printf("st_flash: unlock flash\n");
|
||||||
st_cmd(0xf, 0, NULL);
|
st_cmd(0x10, 0, NULL);
|
||||||
|
|
||||||
if (real_content_length >= 16384) {
|
// erase sector 1
|
||||||
// erase sector 2
|
os_printf("st_flash: erase sector 1\n");
|
||||||
st_cmd(0x11, 2, NULL);
|
st_cmd(0x11, 1, NULL);
|
||||||
st_cmd(0xf, 0, NULL);
|
|
||||||
|
if (real_content_length >= 16384) {
|
||||||
|
// erase sector 2
|
||||||
|
os_printf("st_flash: erase sector 2\n");
|
||||||
|
st_cmd(0x11, 2, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// real content length will always be 0x10 aligned
|
||||||
|
os_printf("st_flash: flashing\n");
|
||||||
|
for (i = 0; i < real_content_length; i += 0x10) {
|
||||||
|
if (!st_cmd(0x12, 4, &st_firmware[i])) {
|
||||||
|
os_printf("st_flash: FAILED, BAILING\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
system_soft_wdt_feed();
|
||||||
|
}
|
||||||
|
|
||||||
|
// reboot into normal mode
|
||||||
|
os_printf("st_flash: rebooting\n");
|
||||||
|
st_set_boot_mode(0);
|
||||||
|
|
||||||
|
// done with this
|
||||||
|
os_free(st_firmware);
|
||||||
|
st_firmware = NULL;
|
||||||
|
|
||||||
|
// watchdog done
|
||||||
|
//system_soft_wdt_restart();
|
||||||
}
|
}
|
||||||
|
|
||||||
// real content length will always be 0x10 aligned
|
|
||||||
for (i = 0; i < real_content_length; i += 0x10) {
|
|
||||||
st_cmd(0x12, 4, &st_firmware[i]);
|
|
||||||
system_soft_wdt_feed();
|
|
||||||
}
|
|
||||||
|
|
||||||
// reboot into normal mode
|
|
||||||
st_set_boot_mode(0);
|
|
||||||
|
|
||||||
// done with this
|
|
||||||
os_free(st_firmware);
|
|
||||||
|
|
||||||
// watchdog done
|
|
||||||
//system_soft_wdt_restart();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
@ -87,7 +104,7 @@ typedef enum {
|
||||||
web_state_t state = NOT_STARTED;
|
web_state_t state = NOT_STARTED;
|
||||||
int esp_address, esp_address_erase_limit, start_address;
|
int esp_address, esp_address_erase_limit, start_address;
|
||||||
|
|
||||||
void hexdump(char *data, int len) {
|
void ICACHE_FLASH_ATTR hexdump(char *data, int len) {
|
||||||
int i;
|
int i;
|
||||||
for (i=0;i<len;i++) {
|
for (i=0;i<len;i++) {
|
||||||
if (i!=0 && (i%0x10)==0) os_printf("\n");
|
if (i!=0 && (i%0x10)==0) os_printf("\n");
|
||||||
|
@ -96,7 +113,7 @@ void hexdump(char *data, int len) {
|
||||||
os_printf("\n");
|
os_printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void st_reset() {
|
void ICACHE_FLASH_ATTR st_reset() {
|
||||||
// reset the ST
|
// reset the ST
|
||||||
gpio16_output_conf();
|
gpio16_output_conf();
|
||||||
gpio16_output_set(0);
|
gpio16_output_set(0);
|
||||||
|
@ -105,7 +122,7 @@ void st_reset() {
|
||||||
os_delay_us(10000);
|
os_delay_us(10000);
|
||||||
}
|
}
|
||||||
|
|
||||||
void st_set_boot_mode(int boot_mode) {
|
void ICACHE_FLASH_ATTR st_set_boot_mode(int boot_mode) {
|
||||||
if (boot_mode) {
|
if (boot_mode) {
|
||||||
// boot mode (pull low)
|
// boot mode (pull low)
|
||||||
gpio_output_set(0, (1 << 4), (1 << 4), 0);
|
gpio_output_set(0, (1 << 4), (1 << 4), 0);
|
||||||
|
@ -115,9 +132,12 @@ void st_set_boot_mode(int boot_mode) {
|
||||||
gpio_output_set((1 << 4), 0, (1 << 4), 0);
|
gpio_output_set((1 << 4), 0, (1 << 4), 0);
|
||||||
st_reset();
|
st_reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// float boot pin
|
||||||
|
gpio_output_set(0, 0, 0, (1 << 4));
|
||||||
}
|
}
|
||||||
|
|
||||||
int st_cmd(int d1, int d2, char *data) {
|
int ICACHE_FLASH_ATTR st_cmd(int d1, int d2, char *data) {
|
||||||
uint32_t __dat[0x14];
|
uint32_t __dat[0x14];
|
||||||
char *dat = (char *)__dat;
|
char *dat = (char *)__dat;
|
||||||
memset(dat, 0, 0x14);
|
memset(dat, 0, 0x14);
|
||||||
|
@ -127,10 +147,31 @@ int st_cmd(int d1, int d2, char *data) {
|
||||||
dat[2] = d2;
|
dat[2] = d2;
|
||||||
dat[3] = 0xFF^d2;
|
dat[3] = 0xFF^d2;
|
||||||
if (data != NULL) memcpy(dat+4, data, 0x10);
|
if (data != NULL) memcpy(dat+4, data, 0x10);
|
||||||
hexdump(dat, 0x14);
|
//hexdump(dat, 0x14);
|
||||||
|
|
||||||
spi_comm(dat, 0x14, recv, 0x40);
|
spi_comm(dat, 0x14, recv, 0x40);
|
||||||
return memcmp(recv+0x10, "\xde\xad\xd0\x0d", 4)==0;
|
//hexdump(recv, 0x44);
|
||||||
|
int good = memcmp(recv+2, "\xde\xad\xd0\x0d", 4)==0;
|
||||||
|
|
||||||
|
if (!good) {
|
||||||
|
os_printf("ST command failed!\n");
|
||||||
|
hexdump(recv, 0x44);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((uint8_t*)recv)[6] != d1) {
|
||||||
|
os_printf("ST command WRONG\n");
|
||||||
|
hexdump(recv, 0x44);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((uint8_t*)recv)[5] != 0xFF) {
|
||||||
|
os_printf("ST command logical fail\n");
|
||||||
|
hexdump(recv, 0x44);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ICACHE_FLASH_ATTR web_rx_cb(void *arg, char *data, uint16_t len) {
|
static void ICACHE_FLASH_ATTR web_rx_cb(void *arg, char *data, uint16_t len) {
|
||||||
|
@ -182,7 +223,7 @@ static void ICACHE_FLASH_ATTR web_rx_cb(void *arg, char *data, uint16_t len) {
|
||||||
// 0x1000 = user1.bin
|
// 0x1000 = user1.bin
|
||||||
// 0x81000 = user2.bin
|
// 0x81000 = user2.bin
|
||||||
// 0x3FE000 = blank.bin
|
// 0x3FE000 = blank.bin
|
||||||
os_printf("init st firmware\n");
|
os_printf("init esp firmware\n");
|
||||||
char *cl = strstr(data, "Content-Length: ");
|
char *cl = strstr(data, "Content-Length: ");
|
||||||
if (cl != NULL) {
|
if (cl != NULL) {
|
||||||
// get content length
|
// get content length
|
||||||
|
|
Loading…
Reference in New Issue