// flasher state variables
uint32_t * prog_ptr = NULL ;
int unlocked = 0 ;
void debug_ring_callback ( uart_ring * ring ) { }
int usb_cb_control_msg ( USB_Setup_TypeDef * setup , uint8_t * resp , int hardwired ) {
int resp_len = 0 ;
// flasher machine
memset ( resp , 0 , 4 ) ;
memcpy ( resp + 4 , " \xde \xad \xd0 \x0d " , 4 ) ;
resp [ 0 ] = 0xff ;
resp [ 2 ] = setup - > b . bRequest ;
resp [ 3 ] = ~ setup - > b . bRequest ;
* ( ( uint32_t * * ) & resp [ 8 ] ) = prog_ptr ;
resp_len = 0xc ;
int sec ;
switch ( setup - > b . bRequest ) {
// **** 0xb0: flasher echo
case 0xb0 :
resp [ 1 ] = 0xff ;
break ;
// **** 0xb1: unlock flash
case 0xb1 :
if ( FLASH - > CR & FLASH_CR_LOCK ) {
FLASH - > KEYR = 0x45670123 ;
FLASH - > KEYR = 0xCDEF89AB ;
resp [ 1 ] = 0xff ;
}
set_led ( LED_GREEN , 1 ) ;
unlocked = 1 ;
prog_ptr = ( uint32_t * ) 0x8004000 ;
break ;
// **** 0xb2: erase sector
case 0xb2 :
sec = setup - > b . wValue . w ;
// 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 ) ;
resp [ 1 ] = 0xff ;
}
break ;
// **** 0xd0: fetch serial number
case 0xd0 :
# ifdef PANDA
// addresses are OTP
if ( setup - > b . wValue . w = = 1 ) {
memcpy ( resp , ( void * ) 0x1fff79c0 , 0x10 ) ;
resp_len = 0x10 ;
} else {
get_provision_chunk ( resp ) ;
resp_len = PROVISION_CHUNK_LEN ;
}
# endif
break ;
// **** 0xd1: enter bootloader mode
case 0xd1 :
// this allows reflashing of the bootstub
// so it's blocked over wifi
switch ( setup - > b . wValue . w ) {
case 0 :
if ( hardwired ) {
puts ( " -> entering bootloader \n " ) ;
enter_bootloader_mode = ENTER_BOOTLOADER_MAGIC ;
NVIC_SystemReset ( ) ;
}
break ;
case 1 :
puts ( " -> entering softloader \n " ) ;
enter_bootloader_mode = ENTER_SOFTLOADER_MAGIC ;
NVIC_SystemReset ( ) ;
break ;
}
break ;
// **** 0xd6: get version
case 0xd6 :
COMPILE_TIME_ASSERT ( sizeof ( gitversion ) < = MAX_RESP_LEN )
memcpy ( resp , gitversion , sizeof ( gitversion ) ) ;
resp_len = sizeof ( gitversion ) ;
break ;
// **** 0xd8: reset ST
case 0xd8 :
NVIC_SystemReset ( ) ;
break ;
}
return resp_len ;
}
int usb_cb_ep1_in ( uint8_t * usbdata , int len , int hardwired ) { return 0 ; }
void usb_cb_ep3_out ( uint8_t * usbdata , int len , int hardwired ) { }
int is_enumerated = 0 ;
void usb_cb_enumeration_complete ( ) {
puts ( " USB enumeration complete \n " ) ;
is_enumerated = 1 ;
}
void usb_cb_ep2_out ( uint8_t * usbdata , int len , int hardwired ) {
set_led ( LED_RED , 0 ) ;
for ( int i = 0 ; i < len / 4 ; i + + ) {
// program byte 1
FLASH - > CR = FLASH_CR_PSIZE_1 | FLASH_CR_PG ;
* prog_ptr = * ( uint32_t * ) ( usbdata + ( 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 ) ;
}
int spi_cb_rx ( uint8_t * data , int len , uint8_t * data_out ) {
int resp_len = 0 ;
switch ( data [ 0 ] ) {
case 0 :
// control transfer
resp_len = usb_cb_control_msg ( ( USB_Setup_TypeDef * ) ( data + 4 ) , data_out , 0 ) ;
break ;
case 2 :
// ep 2, flash!
usb_cb_ep2_out ( data + 4 , data [ 2 ] , 0 ) ;
break ;
}
return resp_len ;
}
# ifdef PEDAL
# define CAN CAN1
# define CAN_BL_INPUT 0x1
# define CAN_BL_OUTPUT 0x2
void CAN1_TX_IRQHandler ( ) {
// clear interrupt
CAN - > TSR | = CAN_TSR_RQCP0 ;
}
# define ISOTP_BUF_SIZE 0x110
uint8_t isotp_buf [ ISOTP_BUF_SIZE ] ;
uint8_t * isotp_buf_ptr = NULL ;
int isotp_buf_remain = 0 ;
uint8_t isotp_buf_out [ ISOTP_BUF_SIZE ] ;
uint8_t * isotp_buf_out_ptr = NULL ;
int isotp_buf_out_remain = 0 ;
int isotp_buf_out_idx = 0 ;
void bl_can_send ( uint8_t * odat ) {
// wait for send
while ( ! ( CAN - > TSR & CAN_TSR_TME0 ) ) ;
// send continue
CAN - > sTxMailBox [ 0 ] . TDLR = ( ( uint32_t * ) odat ) [ 0 ] ;
CAN - > sTxMailBox [ 0 ] . TDHR = ( ( uint32_t * ) odat ) [ 1 ] ;
CAN - > sTxMailBox [ 0 ] . TDTR = 8 ;
CAN - > sTxMailBox [ 0 ] . TIR = ( CAN_BL_OUTPUT < < 21 ) | 1 ;
}
void CAN1_RX0_IRQHandler ( ) {
while ( CAN - > RF0R & CAN_RF0R_FMP0 ) {
if ( ( CAN - > sFIFOMailBox [ 0 ] . RIR > > 21 ) = = CAN_BL_INPUT ) {
uint8_t dat [ 8 ] ;
( ( uint32_t * ) dat ) [ 0 ] = CAN - > sFIFOMailBox [ 0 ] . RDLR ;
( ( uint32_t * ) dat ) [ 1 ] = CAN - > sFIFOMailBox [ 0 ] . RDHR ;
uint8_t odat [ 8 ] ;
uint8_t type = dat [ 0 ] & 0xF0 ;
if ( type = = 0x30 ) {
// continue
while ( isotp_buf_out_remain > 0 ) {
// wait for send
while ( ! ( CAN - > TSR & CAN_TSR_TME0 ) ) ;
odat [ 0 ] = 0x20 | isotp_buf_out_idx ;
memcpy ( odat + 1 , isotp_buf_out_ptr , 7 ) ;
isotp_buf_out_remain - = 7 ;
isotp_buf_out_ptr + = 7 ;
isotp_buf_out_idx + + ;
bl_can_send ( odat ) ;
}
} else if ( type = = 0x20 ) {
if ( isotp_buf_remain > 0 ) {
memcpy ( isotp_buf_ptr , dat + 1 , 7 ) ;
isotp_buf_ptr + = 7 ;
isotp_buf_remain - = 7 ;
}
if ( isotp_buf_remain < = 0 ) {
int len = isotp_buf_ptr - isotp_buf + isotp_buf_remain ;
// call the function
memset ( isotp_buf_out , 0 , ISOTP_BUF_SIZE ) ;
isotp_buf_out_remain = spi_cb_rx ( isotp_buf , len , isotp_buf_out ) ;
isotp_buf_out_ptr = isotp_buf_out ;
isotp_buf_out_idx = 0 ;
// send initial
if ( isotp_buf_out_remain < = 7 ) {
odat [ 0 ] = isotp_buf_out_remain ;
memcpy ( odat + 1 , isotp_buf_out_ptr , isotp_buf_out_remain ) ;
} else {
odat [ 0 ] = 0x10 | ( isotp_buf_out_remain > > 8 ) ;
odat [ 1 ] = isotp_buf_out_remain & 0xFF ;
memcpy ( odat + 2 , isotp_buf_out_ptr , 6 ) ;
isotp_buf_out_remain - = 6 ;
isotp_buf_out_ptr + = 6 ;
isotp_buf_out_idx + + ;
}
bl_can_send ( odat ) ;
}
} else if ( type = = 0x10 ) {
int len = ( ( dat [ 0 ] & 0xF ) < < 8 ) | dat [ 1 ] ;
// setup buffer
isotp_buf_ptr = isotp_buf ;
memcpy ( isotp_buf_ptr , dat + 2 , 6 ) ;
if ( len < ( ISOTP_BUF_SIZE - 0x10 ) ) {
isotp_buf_ptr + = 6 ;
isotp_buf_remain = len - 6 ;
}
memset ( odat , 0 , 8 ) ;
odat [ 0 ] = 0x30 ;
bl_can_send ( odat ) ;
}
}
// next
CAN - > RF0R | = CAN_RF0R_RFOM0 ;
}
}
void CAN1_SCE_IRQHandler ( ) {
can_sce ( CAN ) ;
}
# endif
void soft_flasher_start ( ) {
puts ( " \n \n \n ************************ FLASHER START ************************ \n " ) ;
enter_bootloader_mode = 0 ;
RCC - > AHB1ENR | = RCC_AHB1ENR_DMA2EN ;
RCC - > APB2ENR | = RCC_APB2ENR_SPI1EN ;
RCC - > AHB2ENR | = RCC_AHB2ENR_OTGFSEN ;
RCC - > APB1ENR | = RCC_APB1ENR_USART2EN ;
// pedal has the canloader
# ifdef PEDAL
RCC - > APB1ENR | = RCC_APB1ENR_CAN1EN ;
// B8,B9: CAN 1
set_gpio_alternate ( GPIOB , 8 , GPIO_AF9_CAN1 ) ;
set_gpio_alternate ( GPIOB , 9 , GPIO_AF9_CAN1 ) ;
set_can_enable ( CAN1 , 1 ) ;
// init can
can_silent = ALL_CAN_LIVE ;
can_init ( 0 ) ;
# endif
// A4,A5,A6,A7: setup SPI
set_gpio_alternate ( GPIOA , 4 , GPIO_AF5_SPI1 ) ;
set_gpio_alternate ( GPIOA , 5 , GPIO_AF5_SPI1 ) ;
set_gpio_alternate ( GPIOA , 6 , GPIO_AF5_SPI1 ) ;
set_gpio_alternate ( GPIOA , 7 , GPIO_AF5_SPI1 ) ;
// A2,A3: USART 2 for debugging
set_gpio_alternate ( GPIOA , 2 , GPIO_AF7_USART2 ) ;
set_gpio_alternate ( GPIOA , 3 , GPIO_AF7_USART2 ) ;
// A11,A12: USB
set_gpio_alternate ( GPIOA , 11 , GPIO_AF10_OTG_FS ) ;
set_gpio_alternate ( GPIOA , 12 , GPIO_AF10_OTG_FS ) ;
GPIOA - > OSPEEDR = GPIO_OSPEEDER_OSPEEDR11 | GPIO_OSPEEDER_OSPEEDR12 ;
// flasher
spi_init ( ) ;
// enable USB
usb_init ( ) ;
// green LED on for flashing
set_led ( LED_GREEN , 1 ) ;
__enable_irq ( ) ;
uint64_t cnt = 0 ;
for ( cnt = 0 ; ; cnt + + ) {
if ( cnt = = 35 & & ! is_enumerated & & usb_power_mode = = USB_POWER_CLIENT ) {
// if you are connected through a hub to the phone
// you need power to be able to see the device
puts ( " USBP: didn't enumerate, switching to CDP mode \n " ) ;
set_usb_power_mode ( USB_POWER_CDP ) ;
set_led ( LED_BLUE , 1 ) ;
}
// blink the green LED fast
set_led ( LED_GREEN , 0 ) ;
delay ( 500000 ) ;
set_led ( LED_GREEN , 1 ) ;
delay ( 500000 ) ;
}
}