tests pass, not building recover
parent
d9fc3b372c
commit
5fd041e011
128
board/early.h
128
board/early.h
|
@ -1,128 +0,0 @@
|
|||
#define ENTER_BOOTLOADER_MAGIC 0xdeadbeef
|
||||
#define POST_BOOTLOADER_MAGIC 0xdeadb111
|
||||
#define PULL_EFFECTIVE_DELAY 10
|
||||
|
||||
#define PANDA_REV_AB 0
|
||||
#define PANDA_REV_C 1
|
||||
|
||||
extern uint32_t enter_bootloader_mode;
|
||||
extern void *_app_start[];
|
||||
extern void *g_pfnVectors;
|
||||
|
||||
#include "config.h"
|
||||
#include "llgpio.h"
|
||||
|
||||
int has_external_debug_serial = 0;
|
||||
int is_giant_panda = 0;
|
||||
int revision = PANDA_REV_AB;
|
||||
void *g_pfnVectors;
|
||||
|
||||
// must call again from main because BSS is zeroed
|
||||
void detect() {
|
||||
volatile int i;
|
||||
// detect has_external_debug_serial
|
||||
GPIOA->PUPDR |= GPIO_PUPDR_PUPDR3_1;
|
||||
for (i=0;i<PULL_EFFECTIVE_DELAY;i++);
|
||||
has_external_debug_serial = (GPIOA->IDR & (1 << 3)) == (1 << 3);
|
||||
|
||||
#ifdef PANDA
|
||||
// detect is_giant_panda
|
||||
set_gpio_pullup(GPIOB, 1, PULL_DOWN);
|
||||
for (i=0;i<PULL_EFFECTIVE_DELAY;i++);
|
||||
is_giant_panda = get_gpio_input(GPIOB, 1);
|
||||
|
||||
// detect panda REV C.
|
||||
// A13 floats in REV AB. In REV C, A13 is pulled up to 5V with a 10K
|
||||
// resistor and attached to the USB power control chip CTRL
|
||||
// line. Pulling A13 down with an internal 50k resistor in REV C
|
||||
// will produce a voltage divider that results in a high logic
|
||||
// level. Checking if this pin reads high with a pull down should
|
||||
// differentiate REV AB from C.
|
||||
set_gpio_mode(GPIOA, 13, MODE_INPUT);
|
||||
set_gpio_pullup(GPIOA, 13, PULL_DOWN);
|
||||
for (i=0;i<PULL_EFFECTIVE_DELAY;i++);
|
||||
if(get_gpio_input(GPIOA, 13))
|
||||
revision = PANDA_REV_C;
|
||||
|
||||
// RESET pull up/down
|
||||
set_gpio_pullup(GPIOA, 13, PULL_NONE);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void early() {
|
||||
// after it's been in the bootloader, things are initted differently, so we reset
|
||||
if (enter_bootloader_mode == POST_BOOTLOADER_MAGIC) {
|
||||
enter_bootloader_mode = 0;
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
|
||||
volatile int i;
|
||||
// if wrong chip, reboot
|
||||
volatile unsigned int id = DBGMCU->IDCODE;
|
||||
#ifdef STM32F4
|
||||
if ((id&0xFFF) != 0x463) enter_bootloader_mode = ENTER_BOOTLOADER_MAGIC;
|
||||
#else
|
||||
if ((id&0xFFF) != 0x411) enter_bootloader_mode = ENTER_BOOTLOADER_MAGIC;
|
||||
#endif
|
||||
|
||||
// setup interrupt table
|
||||
SCB->VTOR = (uint32_t)&g_pfnVectors;
|
||||
|
||||
// early GPIOs
|
||||
RCC->AHB1ENR = RCC_AHB1ENR_GPIOAEN | RCC_AHB1ENR_GPIOBEN | RCC_AHB1ENR_GPIOCEN;
|
||||
GPIOA->MODER = 0; GPIOB->MODER = 0; GPIOC->MODER = 0;
|
||||
GPIOA->ODR = 0; GPIOB->ODR = 0; GPIOC->ODR = 0;
|
||||
GPIOA->PUPDR = 0; GPIOB->PUPDR = 0; GPIOC->PUPDR = 0;
|
||||
|
||||
detect();
|
||||
|
||||
#ifdef PANDA
|
||||
// enable the ESP, disable ESP boot mode
|
||||
// unless we are on a giant panda, then there's no ESP
|
||||
if (!is_giant_panda) {
|
||||
GPIOC->ODR = (1 << 14) | (1 << 5);
|
||||
}
|
||||
|
||||
// these are outputs to control the ESP
|
||||
GPIOC->MODER = GPIO_MODER_MODER14_0 | GPIO_MODER_MODER5_0;
|
||||
|
||||
// check if the ESP is trying to put me in boot mode
|
||||
// enable pull up
|
||||
GPIOB->PUPDR |= GPIO_PUPDR_PUPDR0_0;
|
||||
for (i=0;i<PULL_EFFECTIVE_DELAY;i++);
|
||||
|
||||
#ifdef BOOTSTUB
|
||||
// if it's driven low, jump to spi flasher
|
||||
if (!(GPIOB->IDR & 1)) {
|
||||
spi_flasher();
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
if (enter_bootloader_mode == ENTER_BOOTLOADER_MAGIC) {
|
||||
// ESP OFF
|
||||
GPIOC->ODR &= ~((1 << 14) | (1 << 5));
|
||||
|
||||
// green LED on
|
||||
// sadly, on the NEO board the bootloader turns it off
|
||||
#ifdef PANDA
|
||||
GPIOC->MODER |= GPIO_MODER_MODER7_0;
|
||||
GPIOC->ODR &= ~(1 << (6 + 1));
|
||||
#else
|
||||
GPIOB->MODER |= GPIO_MODER_MODER11_0;
|
||||
GPIOB->ODR &= ~(1 << (10 + 1));
|
||||
#endif
|
||||
|
||||
// do enter bootloader
|
||||
enter_bootloader_mode = POST_BOOTLOADER_MAGIC;
|
||||
void (*bootloader)(void) = (void (*)(void)) (*((uint32_t *)0x1fff0004));
|
||||
|
||||
// jump to bootloader
|
||||
bootloader();
|
||||
|
||||
// LOOP
|
||||
while(1);
|
||||
}
|
||||
}
|
141
board/gpio.h
141
board/gpio.h
|
@ -6,6 +6,52 @@
|
|||
|
||||
#include "llgpio.h"
|
||||
|
||||
// ********************* dynamic configuration detection *********************
|
||||
|
||||
#define PANDA_REV_AB 0
|
||||
#define PANDA_REV_C 1
|
||||
|
||||
#define PULL_EFFECTIVE_DELAY 10
|
||||
|
||||
int has_external_debug_serial = 0;
|
||||
int is_giant_panda = 0;
|
||||
int is_entering_bootmode = 0;
|
||||
int revision = PANDA_REV_AB;
|
||||
|
||||
int detect_with_pull(GPIO_TypeDef *GPIO, int pin, int mode) {
|
||||
set_gpio_mode(GPIO, pin, MODE_INPUT);
|
||||
set_gpio_pullup(GPIO, pin, mode);
|
||||
for (volatile int i=0; i<PULL_EFFECTIVE_DELAY; i++);
|
||||
int ret = get_gpio_input(GPIO, pin);
|
||||
set_gpio_pullup(GPIOB, pin, PULL_NONE);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// must call again from main because BSS is zeroed
|
||||
void detect() {
|
||||
volatile int i;
|
||||
|
||||
// detect has_external_debug_serial
|
||||
has_external_debug_serial = detect_with_pull(GPIOA, 3, PULL_DOWN);
|
||||
|
||||
#ifdef PANDA
|
||||
// detect is_giant_panda
|
||||
is_giant_panda = detect_with_pull(GPIOB, 1, PULL_DOWN);
|
||||
|
||||
// detect panda REV C.
|
||||
// A13 floats in REV AB. In REV C, A13 is pulled up to 5V with a 10K
|
||||
// resistor and attached to the USB power control chip CTRL
|
||||
// line. Pulling A13 down with an internal 50k resistor in REV C
|
||||
// will produce a voltage divider that results in a high logic
|
||||
// level. Checking if this pin reads high with a pull down should
|
||||
// differentiate REV AB from C.
|
||||
revision = detect_with_pull(GPIOA, 13, PULL_DOWN) ? PANDA_REV_C : PANDA_REV_AB;
|
||||
|
||||
// check if the ESP is trying to put me in boot mode
|
||||
is_entering_bootmode = detect_with_pull(GPIOB, 0, PULL_UP);
|
||||
#endif
|
||||
}
|
||||
|
||||
// ********************* bringup *********************
|
||||
|
||||
void clock_init() {
|
||||
|
@ -187,6 +233,28 @@ void set_usb_power_mode(int mode) {
|
|||
}
|
||||
}
|
||||
|
||||
#define ESP_DISABLED 0
|
||||
#define ESP_ENABLED 1
|
||||
#define ESP_BOOTMODE 2
|
||||
|
||||
void set_esp_mode(int mode) {
|
||||
switch (mode) {
|
||||
case ESP_DISABLED:
|
||||
// ESP OFF
|
||||
set_gpio_output(GPIOC, 14, 0);
|
||||
set_gpio_output(GPIOC, 5, 0);
|
||||
break;
|
||||
case ESP_ENABLED:
|
||||
set_gpio_output(GPIOC, 14, 1);
|
||||
set_gpio_output(GPIOC, 5, 1);
|
||||
break;
|
||||
case ESP_BOOTMODE:
|
||||
set_gpio_output(GPIOC, 14, 1);
|
||||
set_gpio_output(GPIOC, 5, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// ********************* big init function *********************
|
||||
|
||||
// board specific
|
||||
|
@ -299,3 +367,76 @@ void gpio_init() {
|
|||
}
|
||||
}
|
||||
|
||||
// ********************* early bringup *********************
|
||||
|
||||
#define ENTER_BOOTLOADER_MAGIC 0xdeadbeef
|
||||
#define POST_BOOTLOADER_MAGIC 0xdeadb111
|
||||
|
||||
extern void *g_pfnVectors;
|
||||
extern uint32_t enter_bootloader_mode;
|
||||
|
||||
void jump_to_bootloader() {
|
||||
// do enter bootloader
|
||||
enter_bootloader_mode = POST_BOOTLOADER_MAGIC;
|
||||
void (*bootloader)(void) = (void (*)(void)) (*((uint32_t *)0x1fff0004));
|
||||
|
||||
// jump to bootloader
|
||||
bootloader();
|
||||
|
||||
// LOOP
|
||||
while(1);
|
||||
}
|
||||
|
||||
void early() {
|
||||
// after it's been in the bootloader, things are initted differently, so we reset
|
||||
if (enter_bootloader_mode == POST_BOOTLOADER_MAGIC) {
|
||||
enter_bootloader_mode = 0;
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
|
||||
|
||||
volatile int i;
|
||||
// if wrong chip, reboot
|
||||
volatile unsigned int id = DBGMCU->IDCODE;
|
||||
#ifdef STM32F4
|
||||
if ((id&0xFFF) != 0x463) enter_bootloader_mode = ENTER_BOOTLOADER_MAGIC;
|
||||
#else
|
||||
if ((id&0xFFF) != 0x411) enter_bootloader_mode = ENTER_BOOTLOADER_MAGIC;
|
||||
#endif
|
||||
|
||||
// setup interrupt table
|
||||
SCB->VTOR = (uint32_t)&g_pfnVectors;
|
||||
|
||||
// early GPIOs float everything
|
||||
RCC->AHB1ENR = RCC_AHB1ENR_GPIOAEN | RCC_AHB1ENR_GPIOBEN | RCC_AHB1ENR_GPIOCEN;
|
||||
GPIOA->MODER = 0; GPIOB->MODER = 0; GPIOC->MODER = 0;
|
||||
GPIOA->ODR = 0; GPIOB->ODR = 0; GPIOC->ODR = 0;
|
||||
GPIOA->PUPDR = 0; GPIOB->PUPDR = 0; GPIOC->PUPDR = 0;
|
||||
|
||||
#ifdef PANDA
|
||||
detect();
|
||||
|
||||
// enable the ESP, disable ESP boot mode
|
||||
// unless we are on a giant panda, then there's no ESP
|
||||
if (is_giant_panda) {
|
||||
set_esp_mode(ESP_DISABLED);
|
||||
} else {
|
||||
set_esp_mode(ESP_ENABLED);
|
||||
}
|
||||
|
||||
#ifdef BOOTSTUB
|
||||
if (is_entering_bootmode) {
|
||||
spi_flasher();
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
if (enter_bootloader_mode == ENTER_BOOTLOADER_MAGIC) {
|
||||
set_esp_mode(ESP_DISABLED);
|
||||
set_led(LED_GREEN, 1);
|
||||
|
||||
jump_to_bootloader();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
30
board/main.c
30
board/main.c
|
@ -1,5 +1,4 @@
|
|||
#include "config.h"
|
||||
#include "early.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
// *** end config ***
|
||||
|
@ -177,6 +176,8 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, int hardwired) {
|
|||
break;
|
||||
// **** 0xd1: enter bootloader mode
|
||||
case 0xd1:
|
||||
// this allows reflashing of the bootstub
|
||||
// so it's blocked over wifi
|
||||
if (hardwired) {
|
||||
enter_bootloader_mode = ENTER_BOOTLOADER_MAGIC;
|
||||
NVIC_SystemReset();
|
||||
|
@ -203,31 +204,22 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, int hardwired) {
|
|||
// **** 0xd9: set ESP power
|
||||
case 0xd9:
|
||||
if (setup->b.wValue.w == 1) {
|
||||
// on
|
||||
GPIOC->ODR |= (1 << 14);
|
||||
set_esp_mode(ESP_ENABLED);
|
||||
} else {
|
||||
// off
|
||||
GPIOC->ODR &= ~(1 << 14);
|
||||
set_esp_mode(ESP_DISABLED);
|
||||
}
|
||||
break;
|
||||
// **** 0xda: reset ESP, with optional boot mode
|
||||
case 0xda:
|
||||
// pull low for ESP boot mode
|
||||
if (setup->b.wValue.w == 1) {
|
||||
GPIOC->ODR &= ~(1 << 5);
|
||||
}
|
||||
|
||||
// do ESP reset
|
||||
GPIOC->ODR &= ~(1 << 14);
|
||||
set_esp_mode(ESP_DISABLED);
|
||||
delay(1000000);
|
||||
GPIOC->ODR |= (1 << 14);
|
||||
delay(1000000);
|
||||
|
||||
// reset done, no more boot mode
|
||||
// TODO: ESP doesn't seem to listen here
|
||||
if (setup->b.wValue.w == 1) {
|
||||
GPIOC->ODR |= (1 << 5);
|
||||
set_esp_mode(ESP_BOOTMODE);
|
||||
} else {
|
||||
set_esp_mode(ESP_ENABLED);
|
||||
}
|
||||
delay(1000000);
|
||||
set_esp_mode(ESP_ENABLED);
|
||||
break;
|
||||
// **** 0xdb: set GMLAN multiplexing mode
|
||||
case 0xdb:
|
||||
|
@ -247,6 +239,8 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, int hardwired) {
|
|||
break;
|
||||
// **** 0xdc: set safety mode
|
||||
case 0xdc:
|
||||
// this is the only way to leave silent mode
|
||||
// and it's blocked over WiFi
|
||||
if (hardwired) {
|
||||
safety_set_mode(setup->b.wValue.w);
|
||||
can_silent = (setup->b.wValue.w == SAFETY_NOOUTPUT);
|
||||
|
|
Loading…
Reference in New Issue