diff --git a/board/bootstub.c b/board/bootstub.c index e23e9a29..7f65c3c3 100644 --- a/board/bootstub.c +++ b/board/bootstub.c @@ -12,9 +12,6 @@ #include "libc.h" #include "gpio.h" - -void spi_cb_rx(uint8_t *data, int len) {}; - #include "drivers/drivers.h" #include "drivers/spi.h" diff --git a/board/config.h b/board/config.h index d663edac..98c13f08 100644 --- a/board/config.h +++ b/board/config.h @@ -3,6 +3,7 @@ //#define DEBUG //#define DEBUG_USB +//#define DEBUG_SPI #ifdef STM32F4 #define PANDA diff --git a/board/drivers/drivers.h b/board/drivers/drivers.h index 1b092fd6..876925ef 100644 --- a/board/drivers/drivers.h +++ b/board/drivers/drivers.h @@ -70,8 +70,7 @@ void timer_init(TIM_TypeDef *TIM, int psc); // IRQs: DMA2_Stream2, DMA2_Stream3, EXTI4 void spi_init(); -void spi_cb_rx(uint8_t *data, int len); -void spi_tx_dma(void *addr, int len); +int spi_cb_rx(uint8_t *data, int len, uint8_t *data_out); // ********************* CAN ********************* diff --git a/board/drivers/spi.h b/board/drivers/spi.h index 25e82f66..58037006 100644 --- a/board/drivers/spi.h +++ b/board/drivers/spi.h @@ -17,6 +17,10 @@ void spi_init() { NVIC_EnableIRQ(DMA2_Stream3_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) SYSCFG->EXTICR[2] = SYSCFG_EXTICR2_EXTI4_PA; EXTI->IMR = (1 << 4); @@ -39,6 +43,12 @@ void spi_tx_dma(void *addr, int len) { DMA2_Stream3->CR |= DMA_SxCR_TCIE; 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) { @@ -64,11 +74,22 @@ void spi_rx_dma(void *addr, int len) { // ***************************** SPI IRQs ***************************** +// can't go on the stack cause it's DMAed +uint8_t spi_tx_buf[0x44]; + // SPI RX void DMA2_Stream2_IRQHandler(void) { // ack 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 @@ -76,6 +97,10 @@ void DMA2_Stream3_IRQHandler(void) { // ack DMA2->LIFCR = DMA_LIFCR_CTCIF3; + #ifdef DEBUG_SPI + puts("SPI handshake\n"); + #endif + // reset handshake back to pull up GPIOB->MODER &= ~(GPIO_MODER_MODER0); GPIOB->PUPDR |= GPIO_PUPDR_PUPDR0_0; diff --git a/board/main.c b/board/main.c index 5373c277..59fe1263 100644 --- a/board/main.c +++ b/board/main.c @@ -358,25 +358,20 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, int hardwired) { } #ifdef PANDA - -// 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); +int spi_cb_rx(uint8_t *data, int len, uint8_t *data_out) { // data[0] = endpoint // data[2] = length // data[4:] = data - int *resp_len = (int*)spi_tx_buf; - *resp_len = 0; + + int resp_len = 0; switch (data[0]) { case 0: // 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; case 1: // 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; case 2: // 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); break; } - 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); + return resp_len; } #else -void spi_cb_rx(uint8_t *data, int len) {}; +int spi_cb_rx(uint8_t *data, int len) { return 0; }; #endif @@ -460,7 +449,7 @@ int main() { // set PWM fan_init(); - fan_set_speed(65535); + fan_set_speed(0); puts("**** INTERRUPTS ON ****\n"); diff --git a/board/spi_flasher.h b/board/spi_flasher.h index 58eb935b..9ad2e1b4 100644 --- a/board/spi_flasher.h +++ b/board/spi_flasher.h @@ -1,28 +1,84 @@ -/*void lock_bootloader() { - if (FLASH->OPTCR & FLASH_OPTCR_nWRP_0) { - FLASH->OPTKEYR = 0x08192A3B; - FLASH->OPTKEYR = 0x4C5D6E7F; +// can't go on the stack cause it's DMAed +uint8_t spi_tx_buf[0x44]; - // write protect the bootloader - FLASH->OPTCR &= ~FLASH_OPTCR_nWRP_0; +uint32_t *prog_ptr; +int unlocked = 0; - // OPT program - FLASH->OPTCR |= FLASH_OPTCR_OPTSTRT; - while (FLASH->SR & FLASH_SR_BSY); - - // relock it - FLASH->OPTCR |= FLASH_OPTCR_OPTLOCK; - - // reset - NVIC_SystemReset(); +int spi_cb_rx(uint8_t *data, int len, uint8_t *data_out) { + // get serial number even in bootstub mode + if (memcmp("\x00\x00\x00\x00\x40\xD0\x00\x00\x00\x00\x20\x00", data, 0xC) == 0) { + memcpy(data_out, (void *)0x1fff79e0, 0x20); + return 0x20; } -}*/ + + // 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() { - // green LED on for flashing - GPIOC->MODER |= GPIO_MODER_MODER6_0; - GPIOC->ODR &= ~(1 << 6); - + __disable_irq(); + RCC->AHB1ENR |= RCC_AHB1ENR_DMA2EN; 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) | GPIO_AF5_SPI1 << (6*4) | GPIO_AF5_SPI1 << (7*4); + // blue LED on for flashing + set_led(LED_BLUE, 1); + // flasher spi_init(); + __enable_irq(); - unsigned char spi_rx_buf[0x14]; - 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; - } - } + while (1) { } } + diff --git a/boardesp/proxy.c b/boardesp/proxy.c index 9d2c36b1..99231e0f 100644 --- a/boardesp/proxy.c +++ b/boardesp/proxy.c @@ -56,7 +56,9 @@ static int ICACHE_FLASH_ATTR __spi_comm(char *dat, int len, uint32_t *recvData, SPIMasterSendData(SpiNum_HSPI, &spiData); // 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 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); int length = recvData[0]; + if (length > 0x40) { + os_printf("SPI: BAD LENGTH RECEIVED\n"); + } + // got response, 0x40 works, 0x44 does not spiData.data = recvData+1; spiData.dataLen = recvDataLen; diff --git a/boardesp/webserver.c b/boardesp/webserver.c index 5f209027..84ea206c 100644 --- a/boardesp/webserver.c +++ b/boardesp/webserver.c @@ -35,43 +35,60 @@ LOCAL os_timer_t ota_reboot_timer; #define FIRMWARE_SIZE 503808 -void st_flash() { +void ICACHE_FLASH_ATTR st_flash() { int i; - // stupid watchdog test - //system_soft_wdt_stop(); + if (st_firmware != NULL) { + // stupid watchdog test + //system_soft_wdt_stop(); - // boot mode - st_set_boot_mode(1); + // boot mode + os_printf("st_flash: enter boot mode\n"); + st_set_boot_mode(1); - // unlock flash - st_cmd(0x10, 0, NULL); - st_cmd(0xf, 0, NULL); + // echo + os_printf("st_flash: wait for echo\n"); + 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 - st_cmd(0x11, 1, NULL); - st_cmd(0xf, 0, NULL); + // unlock flash + os_printf("st_flash: unlock flash\n"); + st_cmd(0x10, 0, NULL); - if (real_content_length >= 16384) { - // erase sector 2 - st_cmd(0x11, 2, NULL); - st_cmd(0xf, 0, NULL); + // erase sector 1 + os_printf("st_flash: erase sector 1\n"); + st_cmd(0x11, 1, 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 { @@ -87,7 +104,7 @@ typedef enum { web_state_t state = NOT_STARTED; 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; for (i=0;i