Large reorganization of code and early integration of can bitrate setting.

master
Jessy Diamond Exum 2017-06-30 13:51:56 -07:00
parent baac060e3e
commit a1ed7b62ee
15 changed files with 875 additions and 672 deletions

View File

@ -76,13 +76,13 @@ obj/%.$(PROJ_NAME).o: ../crypto/%.c
obj/$(STARTUP_FILE).o: $(STARTUP_FILE).s
$(CC) $(CFLAGS) -o $@ -c $<
obj/$(PROJ_NAME).bin: obj/$(STARTUP_FILE).o obj/main.$(PROJ_NAME).o obj/early.$(PROJ_NAME).o obj/llgpio.$(PROJ_NAME).o
obj/$(PROJ_NAME).bin: obj/$(STARTUP_FILE).o obj/main.$(PROJ_NAME).o obj/early.$(PROJ_NAME).o obj/llgpio.$(PROJ_NAME).o obj/can.$(PROJ_NAME).o obj/uart.$(PROJ_NAME).o obj/gpio.$(PROJ_NAME).o obj/libc.$(PROJ_NAME).o
# hack
$(CC) -Wl,--section-start,.isr_vector=0x8004000 $(CFLAGS) -o obj/$(PROJ_NAME).elf $^
$(OBJCOPY) -v -O binary obj/$(PROJ_NAME).elf obj/code.bin
SETLEN=1 ../crypto/sign.py obj/code.bin $@ $(CERT)
obj/bootstub.$(PROJ_NAME).bin: obj/$(STARTUP_FILE).o obj/bootstub.$(PROJ_NAME).o obj/sha.$(PROJ_NAME).o obj/rsa.$(PROJ_NAME).o obj/early.$(PROJ_NAME).o obj/llgpio.$(PROJ_NAME).o
obj/bootstub.$(PROJ_NAME).bin: obj/$(STARTUP_FILE).o obj/bootstub.$(PROJ_NAME).o obj/sha.$(PROJ_NAME).o obj/rsa.$(PROJ_NAME).o obj/early.$(PROJ_NAME).o obj/llgpio.$(PROJ_NAME).o obj/libc.$(PROJ_NAME).o
$(CC) $(CFLAGS) -o obj/bootstub.$(PROJ_NAME).elf $^
$(OBJCOPY) -v -O binary obj/bootstub.$(PROJ_NAME).elf $@

186
board/can.c 100644
View File

@ -0,0 +1,186 @@
#include <stdint.h>
#include "config.h"
#include "can.h"
#include "uart.h"
#include "gpio.h"
#include "libc.h"
// assign CAN numbering
// old: CAN1 = 1 CAN2 = 0
// panda: CAN1 = 0 CAN2 = 1 CAN3 = 2
#ifdef PANDA
CAN_TypeDef *can_numbering[] = {CAN1, CAN2, CAN3};
int8_t can_forwarding[] = {-1, -1, -1};
uint32_t can_bitrate[] = {CAN_DEFAULT_BITRATE,
CAN_DEFAULT_BITRATE,
CAN_DEFAULT_BITRATE};
#else
CAN_TypeDef *can_numbering[] = {CAN2, CAN1};
int8_t can_forwarding[] = {-1,-1};
uint32_t can_bitrate[] = {CAN_DEFAULT_BITRATE,
CAN_DEFAULT_BITRATE};
#endif
int controls_allowed = 0;
int pop(can_ring *q, CAN_FIFOMailBox_TypeDef *elem) {
if (q->w_ptr != q->r_ptr) {
*elem = q->elems[q->r_ptr];
if ((q->r_ptr + 1) == q->fifo_size) q->r_ptr = 0;
else q->r_ptr += 1;
return 1;
}
return 0;
}
int push(can_ring *q, CAN_FIFOMailBox_TypeDef *elem) {
uint32_t next_w_ptr;
if ((q->w_ptr + 1) == q->fifo_size) next_w_ptr = 0;
else next_w_ptr = q->w_ptr + 1;
if (next_w_ptr != q->r_ptr) {
q->elems[q->w_ptr] = *elem;
q->w_ptr = next_w_ptr;
return 1;
}
puts("push failed!\n");
return 0;
}
// ********************* CAN Functions *********************
void can_init(uint8_t canid) {
uint32_t bitrate = can_bitrate[canid];
CAN_TypeDef *CAN = can_numbering[canid];
uint8_t quanta;
uint16_t prescaler;
uint8_t seq1, seq2;
puts("Configuring Can Interface index ");
puth(canid);
puts("\n");
//MAX 1 Megabaud
if(bitrate > 1000000)
bitrate = 1000000;
puts("Can Speed request to ");
puth(bitrate);
puts("\n");
//TODO: Try doing both and find the more accurate values.
if(min((FREQ / 2) / bitrate, 16) == 16){
quanta = 16;
seq1 = 13;//roundf(quanta * 0.875f) - 1;
seq2 = 2;//roundf(quanta * 0.125f);
}else{
quanta = 8;
seq1 = 6;//roundf(quanta * 0.875f) - 1;
seq2 = 1;//roundf(quanta * 0.125f);
}
// TODO: Look into better accuracy with rounding.
prescaler = FREQ / quanta / bitrate;
//Check the prescaler is not larger than max
if(prescaler > 0x3FF)
prescaler = 0x3FF;
can_bitrate[canid] = FREQ/quanta/prescaler;
puts("Can Speed set to ");
puth(can_bitrate[canid]);
puts("\n");
set_can_enable(CAN, 1);
// Move CAN to initialization mode and sync.
CAN->MCR = CAN_MCR_TTCM | CAN_MCR_INRQ;
while((CAN->MSR & CAN_MSR_INAK) != CAN_MSR_INAK);
// seg 1: 13 time quanta, seg 2: 2 time quanta
CAN->BTR = (CAN_BTR_TS1_0 * (seq1 - 1)) |
(CAN_BTR_TS2_0 * (seq2 - 1)) |
(prescaler - 1);
// silent loopback mode for debugging
#ifdef CAN_LOOPBACK_MODE
CAN->BTR |= CAN_BTR_SILM | CAN_BTR_LBKM;
#endif
if (!controls_allowed) {
CAN->BTR |= CAN_BTR_SILM;
}
// reset
CAN->MCR = CAN_MCR_TTCM;
int tmp = 0;
while((CAN->MSR & CAN_MSR_INAK) == CAN_MSR_INAK && tmp < CAN_TIMEOUT) tmp++;
if (tmp == CAN_TIMEOUT) {
set_led(LED_BLUE, 1);
puts("CAN init FAILED!!!!!\n");
} else {
puts("CAN init done\n");
}
// accept all filter
CAN->FMR |= CAN_FMR_FINIT;
// no mask
CAN->sFilterRegister[0].FR1 = 0;
CAN->sFilterRegister[0].FR2 = 0;
CAN->sFilterRegister[14].FR1 = 0;
CAN->sFilterRegister[14].FR2 = 0;
CAN->FA1R |= 1 | (1 << 14);
CAN->FMR &= ~(CAN_FMR_FINIT);
// enable all CAN interrupts
CAN->IER = 0xFFFFFFFF;
//CAN->IER = CAN_IER_TMEIE | CAN_IER_FMPIE0 | CAN_IER_FMPIE1;
}
// CAN error
void can_sce(CAN_TypeDef *CAN) {
#ifdef DEBUG
if (CAN==CAN1) puts("CAN1: ");
if (CAN==CAN2) puts("CAN2: ");
#ifdef CAN3
if (CAN==CAN3) puts("CAN3: ");
#endif
puts("MSR:");
puth(CAN->MSR);
puts(" TSR:");
puth(CAN->TSR);
puts(" RF0R:");
puth(CAN->RF0R);
puts(" RF1R:");
puth(CAN->RF1R);
puts(" ESR:");
puth(CAN->ESR);
puts("\n");
#endif
// clear
//CAN->sTxMailBox[0].TIR &= ~(CAN_TI0R_TXRQ);
CAN->TSR |= CAN_TSR_ABRQ0;
//CAN->ESR |= CAN_ESR_LEC;
//CAN->MSR &= ~(CAN_MSR_ERRI);
CAN->MSR = CAN->MSR;
}
int can_cksum(uint8_t *dat, int len, int addr, int idx) {
int i;
int s = 0;
for (i = 0; i < len; i++) {
s += (dat[i] >> 4);
s += dat[i] & 0xF;
}
s += (addr>>0)&0xF;
s += (addr>>4)&0xF;
s += (addr>>8)&0xF;
s += idx;
s = 8-s;
return s&0xF;
}

View File

@ -1,101 +1,46 @@
void can_init(CAN_TypeDef *CAN, int silent) {
set_can_enable(CAN, 1);
#ifndef PANDA_CAN_H
#define PANDA_CAN_H
CAN->MCR = CAN_MCR_TTCM | CAN_MCR_INRQ;
while((CAN->MSR & CAN_MSR_INAK) != CAN_MSR_INAK);
#define CAN_TIMEOUT 1000000
// http://www.bittiming.can-wiki.info/
// PCLK = 24 MHz
uint32_t pclk = 24000;
uint32_t num_time_quanta = 16;
extern CAN_TypeDef *can_numbering[];
extern int8_t can_forwarding[];
extern uint32_t can_bitrate[];
// 500 kbps
uint32_t prescaler = pclk / num_time_quanta / 500;
#ifdef PANDA
#define CAN_MAX 3
#else
#define CAN_MAX 2
#endif
// seg 1: 13 time quanta, seg 2: 2 time quanta
CAN->BTR = (CAN_BTR_TS1_0 * 12) |
CAN_BTR_TS2_0 | (prescaler - 1);
// ********************* queues types *********************
// silent loopback mode for debugging
#ifdef CAN_LOOPBACK_MODE
CAN->BTR |= CAN_BTR_SILM | CAN_BTR_LBKM;
#endif
typedef struct {
uint32_t w_ptr;
uint32_t r_ptr;
uint32_t fifo_size;
CAN_FIFOMailBox_TypeDef *elems;
} can_ring;
if (silent) {
CAN->BTR |= CAN_BTR_SILM;
}
#define can_buffer(x, size) \
CAN_FIFOMailBox_TypeDef elems_##x[size]; \
can_ring can_##x = { .w_ptr = 0, .r_ptr = 0, .fifo_size = size, .elems = (CAN_FIFOMailBox_TypeDef *)&elems_##x };
// reset
CAN->MCR = CAN_MCR_TTCM;
// ********************* interrupt safe queue *********************
#define CAN_TIMEOUT 1000000
int tmp = 0;
while((CAN->MSR & CAN_MSR_INAK) == CAN_MSR_INAK && tmp < CAN_TIMEOUT) tmp++;
int pop(can_ring *q, CAN_FIFOMailBox_TypeDef *elem);
if (tmp == CAN_TIMEOUT) {
set_led(LED_BLUE, 1);
puts("CAN init FAILED!!!!!\n");
} else {
puts("CAN init done\n");
}
int push(can_ring *q, CAN_FIFOMailBox_TypeDef *elem);
// accept all filter
CAN->FMR |= CAN_FMR_FINIT;
// ********************* CAN Functions *********************
// no mask
CAN->sFilterRegister[0].FR1 = 0;
CAN->sFilterRegister[0].FR2 = 0;
CAN->sFilterRegister[14].FR1 = 0;
CAN->sFilterRegister[14].FR2 = 0;
CAN->FA1R |= 1 | (1 << 14);
CAN->FMR &= ~(CAN_FMR_FINIT);
// enable all CAN interrupts
CAN->IER = 0xFFFFFFFF;
//CAN->IER = CAN_IER_TMEIE | CAN_IER_FMPIE0 | CAN_IER_FMPIE1;
}
void can_init(uint8_t canid);
// CAN error
void can_sce(CAN_TypeDef *CAN) {
#ifdef DEBUG
if (CAN==CAN1) puts("CAN1: ");
if (CAN==CAN2) puts("CAN2: ");
#ifdef CAN3
if (CAN==CAN3) puts("CAN3: ");
#endif
puts("MSR:");
puth(CAN->MSR);
puts(" TSR:");
puth(CAN->TSR);
puts(" RF0R:");
puth(CAN->RF0R);
puts(" RF1R:");
puth(CAN->RF1R);
puts(" ESR:");
puth(CAN->ESR);
puts("\n");
#endif
void can_sce(CAN_TypeDef *CAN);
// clear
//CAN->sTxMailBox[0].TIR &= ~(CAN_TI0R_TXRQ);
CAN->TSR |= CAN_TSR_ABRQ0;
//CAN->ESR |= CAN_ESR_LEC;
//CAN->MSR &= ~(CAN_MSR_ERRI);
CAN->MSR = CAN->MSR;
}
int can_cksum(uint8_t *dat, int len, int addr, int idx);
int can_cksum(uint8_t *dat, int len, int addr, int idx) {
int i;
int s = 0;
for (i = 0; i < len; i++) {
s += (dat[i] >> 4);
s += dat[i] & 0xF;
}
s += (addr>>0)&0xF;
s += (addr>>4)&0xF;
s += (addr>>8)&0xF;
s += idx;
s = 8-s;
return s&0xF;
}
extern int controls_allowed;
#endif

View File

@ -17,7 +17,29 @@
#define ENABLE_SPI
#endif
#ifdef PANDA
#define LED_RED 9
#define LED_GREEN 7
#define LED_BLUE 6
#else
#define LED_RED 10
#define LED_GREEN 11
#define LED_BLUE -1
#endif
#define USB_VID 0xbbaa
#define USB_PID 0xddcc
#define FREQ 24000000
// 500 khz
#define CAN_DEFAULT_BITRATE 500000
#define FIFO_SIZE 0x100
#define NULL ((void*)0)
#define PANDA_REV_AB 0
#define PANDA_REV_C 1
#endif

View File

@ -1,6 +1,7 @@
#include "config.h"
#include "early.h"
#include "llgpio.h"
#include "uart.h"
int has_external_debug_serial = 0;
int is_giant_panda = 0;

View File

@ -2,9 +2,6 @@
#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;

270
board/gpio.c 100644
View File

@ -0,0 +1,270 @@
#ifdef STM32F4
#include "stm32f4xx_hal_gpio_ex.h"
#else
#include "stm32f2xx_hal_gpio_ex.h"
#endif
#include "config.h"
#include "gpio.h"
#include "llgpio.h"
#include "early.h"
#include "can.h"
void set_can_enable(CAN_TypeDef *CAN, int enabled) {
// enable CAN busses
if (CAN == CAN1) {
#ifdef PANDA
// CAN1_EN
set_gpio_output(GPIOC, 1, !enabled);
#else
// CAN1_EN
set_gpio_output(GPIOB, 3, enabled);
#endif
} else if (CAN == CAN2) {
#ifdef PANDA
// CAN2_EN
set_gpio_output(GPIOC, 13, !enabled);
#else
// CAN2_EN
set_gpio_output(GPIOB, 4, enabled);
#endif
#ifdef CAN3
} else if (CAN == CAN3) {
// CAN3_EN
set_gpio_output(GPIOA, 0, !enabled);
#endif
}
}
void set_led(int led_num, int on) {
if (led_num == -1) return;
#ifdef PANDA
set_gpio_output(GPIOC, led_num, !on);
#else
set_gpio_output(GPIOB, led_num, !on);
#endif
}
// TODO: does this belong here?
void periph_init() {
// enable GPIOB, UART2, CAN, USB clock
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN;
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN;
RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN;
RCC->AHB1ENR |= RCC_AHB1ENR_DMA2EN;
RCC->APB1ENR |= RCC_APB1ENR_USART2EN;
RCC->APB1ENR |= RCC_APB1ENR_USART3EN;
#ifdef PANDA
RCC->APB1ENR |= RCC_APB1ENR_UART5EN;
#endif
RCC->APB1ENR |= RCC_APB1ENR_CAN1EN;
RCC->APB1ENR |= RCC_APB1ENR_CAN2EN;
#ifdef CAN3
RCC->APB1ENR |= RCC_APB1ENR_CAN3EN;
#endif
RCC->APB1ENR |= RCC_APB1ENR_DACEN;
RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;
//RCC->APB1ENR |= RCC_APB1ENR_TIM4EN;
RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
RCC->AHB2ENR |= RCC_AHB2ENR_OTGFSEN;
RCC->APB2ENR |= RCC_APB2ENR_TIM1EN;
RCC->APB2ENR |= RCC_APB2ENR_ADC1EN;
RCC->APB2ENR |= RCC_APB2ENR_SPI1EN;
// needed?
RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN;
}
void set_can_mode(int can, int use_gmlan) {
// http://www.bittiming.can-wiki.info/#bxCAN
// 24 MHz, sample point at 87.5%
uint32_t pclk = 24000;
uint32_t num_time_quanta = 16;
uint32_t prescaler;
CAN_TypeDef *CAN;
if(can >= CAN_MAX) return;
CAN = can_numbering[can];
// connects to CAN2 xcvr or GMLAN xcvr
if (use_gmlan) {
if (can == 1) {
// B5,B6: disable normal mode
set_gpio_mode(GPIOB, 5, MODE_INPUT);
set_gpio_mode(GPIOB, 6, MODE_INPUT);
// B12,B13: gmlan mode
set_gpio_alternate(GPIOB, 12, GPIO_AF9_CAN2);
set_gpio_alternate(GPIOB, 13, GPIO_AF9_CAN2);
/* GMLAN mode pins:
M0(B15) M1(B14) mode
=======================
0 0 sleep
1 0 100kbit
0 1 high voltage wakeup
1 1 33kbit (normal)
*/
} else if (revision == PANDA_REV_C && can == 2) {
// A8,A15: disable normal mode
set_gpio_mode(GPIOA, 8, MODE_INPUT);
set_gpio_mode(GPIOA, 15, MODE_INPUT);
// B3,B4: enable gmlan mode
set_gpio_alternate(GPIOB, 3, GPIO_AF11_CAN3);
set_gpio_alternate(GPIOB, 4, GPIO_AF11_CAN3);
}
// put gmlan transceiver in normal mode
set_gpio_output(GPIOB, 14, 1);
set_gpio_output(GPIOB, 15, 1);
// 83.3 kbps
// prescaler = pclk / num_time_quanta * 10 / 833;
// 33.3 kbps
prescaler = pclk / num_time_quanta * 10 / 333;
} else {
if (can == 1) {
// B12,B13: disable gmlan mode
set_gpio_mode(GPIOB, 12, MODE_INPUT);
set_gpio_mode(GPIOB, 13, MODE_INPUT);
// B5,B6: normal mode
set_gpio_alternate(GPIOB, 5, GPIO_AF9_CAN2);
set_gpio_alternate(GPIOB, 6, GPIO_AF9_CAN2);
} else if (can == 2) {
if(revision == PANDA_REV_C){
// B3,B4: disable gmlan mode
set_gpio_mode(GPIOB, 3, MODE_INPUT);
set_gpio_mode(GPIOB, 4, MODE_INPUT);
}
// A8,A15: normal mode
set_gpio_alternate(GPIOA, 8, GPIO_AF11_CAN3);
set_gpio_alternate(GPIOA, 15, GPIO_AF11_CAN3);
}
// 500 kbps
prescaler = pclk / num_time_quanta / 500;
}
// init
CAN->MCR = CAN_MCR_TTCM | CAN_MCR_INRQ;
while((CAN->MSR & CAN_MSR_INAK) != CAN_MSR_INAK);
// set speed
// seg 1: 13 time quanta, seg 2: 2 time quanta
CAN->BTR = (CAN_BTR_TS1_0 * 12) |
CAN_BTR_TS2_0 | (prescaler - 1);
// running
CAN->MCR = CAN_MCR_TTCM;
while((CAN->MSR & CAN_MSR_INAK) == CAN_MSR_INAK);
}
// board specific
void gpio_init() {
// pull low to hold ESP in reset??
// enable OTG out tied to ground
GPIOA->ODR = 0;
GPIOB->ODR = 0;
GPIOA->PUPDR = 0;
//GPIOC->ODR = 0;
GPIOB->AFR[0] = 0;
GPIOB->AFR[1] = 0;
// C2,C3: analog mode, voltage and current sense
set_gpio_mode(GPIOC, 2, MODE_ANALOG);
set_gpio_mode(GPIOC, 3, MODE_ANALOG);
// C8: FAN aka TIM3_CH4
set_gpio_alternate(GPIOC, 8, GPIO_AF2_TIM3);
// turn off LEDs and set mode
set_led(LED_RED, 0);
set_led(LED_GREEN, 0);
set_led(LED_BLUE, 0);
// 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;
#ifdef PANDA
// enable started_alt on the panda
set_gpio_pullup(GPIOA, 1, PULL_UP);
// A2,A3: USART 2 for debugging
set_gpio_alternate(GPIOA, 2, GPIO_AF7_USART2);
set_gpio_alternate(GPIOA, 3, GPIO_AF7_USART2);
// A9,A10: USART 1 for talking to the ESP
set_gpio_alternate(GPIOA, 9, GPIO_AF7_USART1);
set_gpio_alternate(GPIOA, 10, GPIO_AF7_USART1);
// B12: GMLAN, ignition sense, pull up
set_gpio_pullup(GPIOB, 12, PULL_UP);
// 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);
#endif
// B8,B9: CAN 1
set_can_enable(CAN1, 0);
#ifdef STM32F4
set_gpio_alternate(GPIOB, 8, GPIO_AF8_CAN1);
set_gpio_alternate(GPIOB, 9, GPIO_AF8_CAN1);
#else
set_gpio_alternate(GPIOB, 8, GPIO_AF9_CAN1);
set_gpio_alternate(GPIOB, 9, GPIO_AF9_CAN1);
#endif
// B5,B6: CAN 2
set_can_enable(CAN2, 0);
set_can_mode(2, 0);
// A8,A15: CAN3
#ifdef CAN3
set_can_enable(CAN3, 0);
set_can_mode(3, 0);
#endif
#ifdef PANDA
// K-line enable moved from B4->B7 to make room for GMLAN on CAN3
if(revision == PANDA_REV_C)
set_gpio_output(GPIOB, 7, 1); // REV C
else
set_gpio_output(GPIOB, 4, 1); // REV AB
// C12,D2: K-Line setup on UART 5
set_gpio_alternate(GPIOC, 12, GPIO_AF8_UART5);
set_gpio_alternate(GPIOD, 2, GPIO_AF8_UART5);
set_gpio_pullup(GPIOD, 2, PULL_UP);
// L-line enable
set_gpio_output(GPIOA, 14, 1);
// C10,C11: L-Line setup on USART 3
set_gpio_alternate(GPIOC, 10, GPIO_AF7_USART3);
set_gpio_alternate(GPIOC, 11, GPIO_AF7_USART3);
set_gpio_pullup(GPIOC, 11, PULL_UP);
#endif
if(revision == PANDA_REV_C) {
// B2,A13: set DCP mode on the charger (breaks USB!)
//set_gpio_output(GPIOB, 2, 0);
//set_gpio_output(GPIOA, 13, 0);
//set_gpio_output(GPIOA, 13, 1); //CTRL 1
//set_gpio_output(GPIOB, 2, 0); //CTRL 2
}
}

View File

@ -1,278 +1,11 @@
#ifdef STM32F4
#include "stm32f4xx_hal_gpio_ex.h"
#else
#include "stm32f2xx_hal_gpio_ex.h"
#endif
#include "llgpio.h"
void set_can_enable(CAN_TypeDef *CAN, int enabled) {
// enable CAN busses
if (CAN == CAN1) {
#ifdef PANDA
// CAN1_EN
set_gpio_output(GPIOC, 1, !enabled);
#else
// CAN1_EN
set_gpio_output(GPIOB, 3, enabled);
#endif
} else if (CAN == CAN2) {
#ifdef PANDA
// CAN2_EN
set_gpio_output(GPIOC, 13, !enabled);
#else
// CAN2_EN
set_gpio_output(GPIOB, 4, enabled);
#endif
#ifdef CAN3
} else if (CAN == CAN3) {
// CAN3_EN
set_gpio_output(GPIOA, 0, !enabled);
#endif
}
}
#ifdef PANDA
#define LED_RED 9
#define LED_GREEN 7
#define LED_BLUE 6
#else
#define LED_RED 10
#define LED_GREEN 11
#define LED_BLUE -1
#endif
void set_led(int led_num, int on) {
if (led_num == -1) return;
#ifdef PANDA
set_gpio_output(GPIOC, led_num, !on);
#else
set_gpio_output(GPIOB, led_num, !on);
#endif
}
void set_can_enable(CAN_TypeDef *CAN, int enabled);
void set_led(int led_num, int on);
// TODO: does this belong here?
void periph_init() {
// enable GPIOB, UART2, CAN, USB clock
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN;
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN;
RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN;
void periph_init();
RCC->AHB1ENR |= RCC_AHB1ENR_DMA2EN;
RCC->APB1ENR |= RCC_APB1ENR_USART2EN;
RCC->APB1ENR |= RCC_APB1ENR_USART3EN;
#ifdef PANDA
RCC->APB1ENR |= RCC_APB1ENR_UART5EN;
#endif
RCC->APB1ENR |= RCC_APB1ENR_CAN1EN;
RCC->APB1ENR |= RCC_APB1ENR_CAN2EN;
#ifdef CAN3
RCC->APB1ENR |= RCC_APB1ENR_CAN3EN;
#endif
RCC->APB1ENR |= RCC_APB1ENR_DACEN;
RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;
//RCC->APB1ENR |= RCC_APB1ENR_TIM4EN;
RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
RCC->AHB2ENR |= RCC_AHB2ENR_OTGFSEN;
RCC->APB2ENR |= RCC_APB2ENR_TIM1EN;
RCC->APB2ENR |= RCC_APB2ENR_ADC1EN;
RCC->APB2ENR |= RCC_APB2ENR_SPI1EN;
// needed?
RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN;
}
void set_can_mode(int can, int use_gmlan) {
// http://www.bittiming.can-wiki.info/#bxCAN
// 24 MHz, sample point at 87.5%
uint32_t pclk = 24000;
uint32_t num_time_quanta = 16;
uint32_t prescaler;
CAN_TypeDef *CAN = NULL;
if (can == 2) CAN = CAN2;
#ifdef CAN3
else if (can == 3) CAN = CAN3;
#endif
if (CAN == NULL) return;
// connects to CAN2 xcvr or GMLAN xcvr
if (use_gmlan) {
if (can == 2) {
// B5,B6: disable normal mode
set_gpio_mode(GPIOB, 5, MODE_INPUT);
set_gpio_mode(GPIOB, 6, MODE_INPUT);
// B12,B13: gmlan mode
set_gpio_alternate(GPIOB, 12, GPIO_AF9_CAN2);
set_gpio_alternate(GPIOB, 13, GPIO_AF9_CAN2);
/* GMLAN mode pins:
M0(B15) M1(B14) mode
=======================
0 0 sleep
1 0 100kbit
0 1 high voltage wakeup
1 1 33kbit (normal)
*/
} else if (revision == PANDA_REV_C && can == 3) {
// A8,A15: disable normal mode
set_gpio_mode(GPIOA, 8, MODE_INPUT);
set_gpio_mode(GPIOA, 15, MODE_INPUT);
// B3,B4: enable gmlan mode
set_gpio_alternate(GPIOB, 3, GPIO_AF11_CAN3);
set_gpio_alternate(GPIOB, 4, GPIO_AF11_CAN3);
}
// put gmlan transceiver in normal mode
set_gpio_output(GPIOB, 14, 1);
set_gpio_output(GPIOB, 15, 1);
// 83.3 kbps
// prescaler = pclk / num_time_quanta * 10 / 833;
// 33.3 kbps
prescaler = pclk / num_time_quanta * 10 / 333;
} else {
if (can == 2) {
// B12,B13: disable gmlan mode
set_gpio_mode(GPIOB, 12, MODE_INPUT);
set_gpio_mode(GPIOB, 13, MODE_INPUT);
// B5,B6: normal mode
set_gpio_alternate(GPIOB, 5, GPIO_AF9_CAN2);
set_gpio_alternate(GPIOB, 6, GPIO_AF9_CAN2);
} else if (can == 3) {
if(revision == PANDA_REV_C){
// B3,B4: disable gmlan mode
set_gpio_mode(GPIOB, 3, MODE_INPUT);
set_gpio_mode(GPIOB, 4, MODE_INPUT);
}
// A8,A15: normal mode
set_gpio_alternate(GPIOA, 8, GPIO_AF11_CAN3);
set_gpio_alternate(GPIOA, 15, GPIO_AF11_CAN3);
}
// 500 kbps
prescaler = pclk / num_time_quanta / 500;
}
// init
CAN->MCR = CAN_MCR_TTCM | CAN_MCR_INRQ;
while((CAN->MSR & CAN_MSR_INAK) != CAN_MSR_INAK);
// set speed
// seg 1: 13 time quanta, seg 2: 2 time quanta
CAN->BTR = (CAN_BTR_TS1_0 * 12) |
CAN_BTR_TS2_0 | (prescaler - 1);
// running
CAN->MCR = CAN_MCR_TTCM;
while((CAN->MSR & CAN_MSR_INAK) == CAN_MSR_INAK);
}
void set_can_mode(int can, int use_gmlan);
// board specific
void gpio_init() {
// pull low to hold ESP in reset??
// enable OTG out tied to ground
GPIOA->ODR = 0;
GPIOB->ODR = 0;
GPIOA->PUPDR = 0;
//GPIOC->ODR = 0;
GPIOB->AFR[0] = 0;
GPIOB->AFR[1] = 0;
// C2,C3: analog mode, voltage and current sense
set_gpio_mode(GPIOC, 2, MODE_ANALOG);
set_gpio_mode(GPIOC, 3, MODE_ANALOG);
// C8: FAN aka TIM3_CH4
set_gpio_alternate(GPIOC, 8, GPIO_AF2_TIM3);
// turn off LEDs and set mode
set_led(LED_RED, 0);
set_led(LED_GREEN, 0);
set_led(LED_BLUE, 0);
// 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;
#ifdef PANDA
// enable started_alt on the panda
set_gpio_pullup(GPIOA, 1, PULL_UP);
// A2,A3: USART 2 for debugging
set_gpio_alternate(GPIOA, 2, GPIO_AF7_USART2);
set_gpio_alternate(GPIOA, 3, GPIO_AF7_USART2);
// A9,A10: USART 1 for talking to the ESP
set_gpio_alternate(GPIOA, 9, GPIO_AF7_USART1);
set_gpio_alternate(GPIOA, 10, GPIO_AF7_USART1);
// B12: GMLAN, ignition sense, pull up
set_gpio_pullup(GPIOB, 12, PULL_UP);
// 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);
#endif
// B8,B9: CAN 1
set_can_enable(CAN1, 0);
#ifdef STM32F4
set_gpio_alternate(GPIOB, 8, GPIO_AF8_CAN1);
set_gpio_alternate(GPIOB, 9, GPIO_AF8_CAN1);
#else
set_gpio_alternate(GPIOB, 8, GPIO_AF9_CAN1);
set_gpio_alternate(GPIOB, 9, GPIO_AF9_CAN1);
#endif
// B5,B6: CAN 2
set_can_enable(CAN2, 0);
set_can_mode(2, 0);
// A8,A15: CAN3
#ifdef CAN3
set_can_enable(CAN3, 0);
set_can_mode(3, 0);
#endif
#ifdef PANDA
// K-line enable moved from B4->B7 to make room for GMLAN on CAN3
if(revision == PANDA_REV_C)
set_gpio_output(GPIOB, 7, 1); // REV C
else
set_gpio_output(GPIOB, 4, 1); // REV AB
// C12,D2: K-Line setup on UART 5
set_gpio_alternate(GPIOC, 12, GPIO_AF8_UART5);
set_gpio_alternate(GPIOD, 2, GPIO_AF8_UART5);
set_gpio_pullup(GPIOD, 2, PULL_UP);
// L-line enable
set_gpio_output(GPIOA, 14, 1);
// C10,C11: L-Line setup on USART 3
set_gpio_alternate(GPIOC, 10, GPIO_AF7_USART3);
set_gpio_alternate(GPIOC, 11, GPIO_AF7_USART3);
set_gpio_pullup(GPIOC, 11, PULL_UP);
#endif
if(revision == PANDA_REV_C) {
// B2,A13: set DCP mode on the charger (breaks USB!)
//set_gpio_output(GPIOB, 2, 0);
//set_gpio_output(GPIOA, 13, 0);
//set_gpio_output(GPIOA, 13, 1); //CTRL 1
//set_gpio_output(GPIOB, 2, 0); //CTRL 2
}
}
void gpio_init();

66
board/libc.c 100644
View File

@ -0,0 +1,66 @@
#include <stdint.h>
#include "config.h"
#include "libc.h"
void clock_init() {
// enable external oscillator
RCC->CR |= RCC_CR_HSEON;
while ((RCC->CR & RCC_CR_HSERDY) == 0);
// divide shit
RCC->CFGR = RCC_CFGR_HPRE_DIV1 | RCC_CFGR_PPRE2_DIV2 | RCC_CFGR_PPRE1_DIV4;
#ifdef PANDA
RCC->PLLCFGR = RCC_PLLCFGR_PLLQ_2 | RCC_PLLCFGR_PLLM_3 |
RCC_PLLCFGR_PLLN_6 | RCC_PLLCFGR_PLLN_5 | RCC_PLLCFGR_PLLSRC_HSE;
#else
RCC->PLLCFGR = RCC_PLLCFGR_PLLQ_2 | RCC_PLLCFGR_PLLM_3 |
RCC_PLLCFGR_PLLN_7 | RCC_PLLCFGR_PLLN_6 | RCC_PLLCFGR_PLLSRC_HSE;
#endif
// start PLL
RCC->CR |= RCC_CR_PLLON;
while ((RCC->CR & RCC_CR_PLLRDY) == 0);
// Configure Flash prefetch, Instruction cache, Data cache and wait state
// *** without this, it breaks ***
FLASH->ACR = FLASH_ACR_ICEN | FLASH_ACR_DCEN | FLASH_ACR_LATENCY_5WS;
// switch to PLL
RCC->CFGR |= RCC_CFGR_SW_PLL;
while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL);
// *** running on PLL ***
}
void delay(int a) {
volatile int i;
for (i=0;i<a;i++);
}
void *memset(void *str, int c, unsigned int n) {
int i;
for (i = 0; i < n; i++) {
*((uint8_t*)str) = c;
++str;
}
return str;
}
void *memcpy(void *dest, const void *src, unsigned int n) {
int i;
// TODO: make not slow
for (i = 0; i < n; i++) {
((uint8_t*)dest)[i] = *(uint8_t*)src;
++src;
}
return dest;
}
int memcmp(const void * ptr1, const void * ptr2, unsigned int num) {
int i;
for (i = 0; i < num; i++) {
if ( ((uint8_t*)ptr1)[i] != ((uint8_t*)ptr2)[i] ) return -1;
}
return 0;
}

View File

@ -1,3 +1,5 @@
#ifndef PANDA_LIBC_H
#define PANDA_LIBC_H
#define min(a,b) \
({ __typeof__ (a) _a = (a); \
@ -11,65 +13,14 @@
// **** shitty libc ****
void clock_init() {
// enable external oscillator
RCC->CR |= RCC_CR_HSEON;
while ((RCC->CR & RCC_CR_HSERDY) == 0);
void clock_init();
// divide shit
RCC->CFGR = RCC_CFGR_HPRE_DIV1 | RCC_CFGR_PPRE2_DIV2 | RCC_CFGR_PPRE1_DIV4;
#ifdef PANDA
RCC->PLLCFGR = RCC_PLLCFGR_PLLQ_2 | RCC_PLLCFGR_PLLM_3 |
RCC_PLLCFGR_PLLN_6 | RCC_PLLCFGR_PLLN_5 | RCC_PLLCFGR_PLLSRC_HSE;
#else
RCC->PLLCFGR = RCC_PLLCFGR_PLLQ_2 | RCC_PLLCFGR_PLLM_3 |
RCC_PLLCFGR_PLLN_7 | RCC_PLLCFGR_PLLN_6 | RCC_PLLCFGR_PLLSRC_HSE;
#endif
void delay(int a);
// start PLL
RCC->CR |= RCC_CR_PLLON;
while ((RCC->CR & RCC_CR_PLLRDY) == 0);
void *memset(void *str, int c, unsigned int n);
// Configure Flash prefetch, Instruction cache, Data cache and wait state
// *** without this, it breaks ***
FLASH->ACR = FLASH_ACR_ICEN | FLASH_ACR_DCEN | FLASH_ACR_LATENCY_5WS;
void *memcpy(void *dest, const void *src, unsigned int n);
// switch to PLL
RCC->CFGR |= RCC_CFGR_SW_PLL;
while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL);
int memcmp(const void * ptr1, const void * ptr2, unsigned int num);
// *** running on PLL ***
}
void delay(int a) {
volatile int i;
for (i=0;i<a;i++);
}
void *memset(void *str, int c, unsigned int n) {
int i;
for (i = 0; i < n; i++) {
*((uint8_t*)str) = c;
++str;
}
return str;
}
void *memcpy(void *dest, const void *src, unsigned int n) {
int i;
// TODO: make not slow
for (i = 0; i < n; i++) {
((uint8_t*)dest)[i] = *(uint8_t*)src;
++src;
}
return dest;
}
int memcmp(const void * ptr1, const void * ptr2, unsigned int num) {
int i;
for (i = 0; i < num; i++) {
if ( ((uint8_t*)ptr1)[i] != ((uint8_t*)ptr2)[i] ) return -1;
}
return 0;
}
#endif

View File

@ -1,28 +1,8 @@
#include "config.h"
#include "early.h"
#define NULL ((void*)0)
// assign CAN numbering
// old: CAN1 = 1 CAN2 = 0
// panda: CAN1 = 0 CAN2 = 1 CAN3 = 4
#ifdef PANDA
int can_numbering[] = {0,1,4};
#else
int can_numbering[] = {1,0,-1};
#endif
// can forwards FROM -> TO
#define CAN_MAX 3
int can_forwarding[] = {-1,-1,-1};
// *** end config ***
#include "obj/gitversion.h"
// debug safety check: is controls allowed?
int controls_allowed = 0;
int started = 0;
int can_live = 0, pending_can_live = 0;
@ -34,70 +14,19 @@ int started_signal_detected = 0;
// TODO: check for UART high
int did_usb_enumerate = 0;
// Declare puts to supress warning
int puts ( const char * str );
// ********************* instantiate queues *********************
#include "uart.h"
#include "can.h"
typedef struct {
uint32_t w_ptr;
uint32_t r_ptr;
uint32_t fifo_size;
CAN_FIFOMailBox_TypeDef *elems;
} can_ring;
#define can_buffer(x, size) \
CAN_FIFOMailBox_TypeDef elems_##x[size]; \
can_ring can_##x = { .w_ptr = 0, .r_ptr = 0, .fifo_size = size, .elems = (CAN_FIFOMailBox_TypeDef *)&elems_##x };
// ********************* instantiate can queues *********************
can_buffer(rx_q, 0x1000)
can_buffer(tx1_q, 0x100)
can_buffer(tx2_q, 0x100)
can_buffer(tx3_q, 0x100)
// ********************* interrupt safe queue *********************
int pop(can_ring *q, CAN_FIFOMailBox_TypeDef *elem) {
if (q->w_ptr != q->r_ptr) {
*elem = q->elems[q->r_ptr];
if ((q->r_ptr + 1) == q->fifo_size) q->r_ptr = 0;
else q->r_ptr += 1;
return 1;
}
return 0;
}
int push(can_ring *q, CAN_FIFOMailBox_TypeDef *elem) {
uint32_t next_w_ptr;
if ((q->w_ptr + 1) == q->fifo_size) next_w_ptr = 0;
else next_w_ptr = q->w_ptr + 1;
if (next_w_ptr != q->r_ptr) {
q->elems[q->w_ptr] = *elem;
q->w_ptr = next_w_ptr;
return 1;
}
puts("push failed!\n");
return 0;
}
// ***************************** serial port queues *****************************
#define FIFO_SIZE 0x100
typedef struct uart_ring {
uint8_t w_ptr_tx;
uint8_t r_ptr_tx;
uint8_t elems_tx[FIFO_SIZE];
uint8_t w_ptr_rx;
uint8_t r_ptr_rx;
uint8_t elems_rx[FIFO_SIZE];
USART_TypeDef *uart;
void (*callback)(struct uart_ring*);
} uart_ring;
int getc(uart_ring *q, char *elem);
int putc(uart_ring *q, char elem);
// esp = USART1
uart_ring esp_ring = { .w_ptr_tx = 0, .r_ptr_tx = 0,
.w_ptr_rx = 0, .r_ptr_rx = 0,
@ -113,12 +42,6 @@ uart_ring lin2_ring = { .w_ptr_tx = 0, .r_ptr_tx = 0,
.uart = USART3 };
// debug = USART2
void debug_ring_callback(uart_ring *ring);
uart_ring debug_ring = { .w_ptr_tx = 0, .r_ptr_tx = 0,
.w_ptr_rx = 0, .r_ptr_rx = 0,
.uart = USART2,
.callback = debug_ring_callback};
uart_ring *get_ring_by_number(int a) {
switch(a) {
@ -213,36 +136,6 @@ void debug_ring_callback(uart_ring *ring) {
}
}
// ***************************** serial port *****************************
void uart_ring_process(uart_ring *q) {
// TODO: check if external serial is connected
int sr = q->uart->SR;
if (q->w_ptr_tx != q->r_ptr_tx) {
if (sr & USART_SR_TXE) {
q->uart->DR = q->elems_tx[q->r_ptr_tx];
q->r_ptr_tx += 1;
} else {
// push on interrupt later
q->uart->CR1 |= USART_CR1_TXEIE;
}
} else {
// nothing to send
q->uart->CR1 &= ~USART_CR1_TXEIE;
}
if (sr & USART_SR_RXNE) {
uint8_t c = q->uart->DR; // TODO: can drop packets
uint8_t next_w_ptr = q->w_ptr_rx + 1;
if (next_w_ptr != q->r_ptr_rx) {
q->elems_rx[q->w_ptr_rx] = c;
q->w_ptr_rx = next_w_ptr;
if (q->callback) q->callback(q);
}
}
}
// interrupt boilerplate
void USART1_IRQHandler(void) {
@ -269,47 +162,12 @@ void UART5_IRQHandler(void) {
NVIC_EnableIRQ(UART5_IRQn);
}
int getc(uart_ring *q, char *elem) {
if (q->w_ptr_rx != q->r_ptr_rx) {
*elem = q->elems_rx[q->r_ptr_rx];
q->r_ptr_rx += 1;
return 1;
}
return 0;
}
int injectc(uart_ring *q, char elem) {
uint8_t next_w_ptr = q->w_ptr_rx + 1;
int ret = 0;
if (next_w_ptr != q->r_ptr_rx) {
q->elems_rx[q->w_ptr_rx] = elem;
q->w_ptr_rx = next_w_ptr;
ret = 1;
}
return ret;
}
int putc(uart_ring *q, char elem) {
uint8_t next_w_ptr = q->w_ptr_tx + 1;
int ret = 0;
if (next_w_ptr != q->r_ptr_tx) {
q->elems_tx[q->w_ptr_tx] = elem;
q->w_ptr_tx = next_w_ptr;
ret = 1;
}
uart_ring_process(q);
return ret;
}
// ********************* includes *********************
#include "libc.h"
#include "gpio.h"
#include "uart.h"
#include "adc.h"
#include "timer.h"
#include "usb.h"
#include "can.h"
#include "spi.h"
void safety_rx_hook(CAN_FIFOMailBox_TypeDef *to_push);
@ -322,6 +180,8 @@ int safety_tx_lin_hook(int lin_num, uint8_t *data, int len, int hardwired);
#include "honda_safety.h"
#endif
#define PANDA_CANB_RETURN_FLAG 0x80
// ***************************** CAN *****************************
void process_can(CAN_TypeDef *CAN, can_ring *can_q, int can_number) {
@ -333,7 +193,11 @@ void process_can(CAN_TypeDef *CAN, can_ring *can_q, int can_number) {
if ((CAN->TSR & CAN_TSR_TXOK0) == CAN_TSR_TXOK0) {
CAN_FIFOMailBox_TypeDef to_push;
to_push.RIR = CAN->sTxMailBox[0].TIR;
to_push.RDTR = (CAN->sTxMailBox[0].TDTR & 0xFFFF000F) | ((can_number+2) << 4);
to_push.RDTR = (CAN->sTxMailBox[0].TDTR & 0xFFFF000F) |
((PANDA_CANB_RETURN_FLAG | (can_number & 0x7F)) << 4);
puts("RDTR: ");
puth(to_push.RDTR);
puts("\n");
to_push.RDLR = CAN->sTxMailBox[0].TDLR;
to_push.RDHR = CAN->sTxMailBox[0].TDHR;
push(&can_rx_q, &to_push);
@ -359,16 +223,16 @@ void process_can(CAN_TypeDef *CAN, can_ring *can_q, int can_number) {
void CAN1_TX_IRQHandler() {
process_can(CAN1, &can_tx1_q, can_numbering[0]);
process_can(can_numbering[0], &can_tx1_q, 0);
}
void CAN2_TX_IRQHandler() {
process_can(CAN2, &can_tx2_q, can_numbering[1]);
process_can(can_numbering[1], &can_tx2_q, 1);
}
#ifdef CAN3
#ifdef PANDA
void CAN3_TX_IRQHandler() {
process_can(CAN3, &can_tx3_q, can_numbering[2]);
process_can(can_numbering[2], &can_tx3_q, 2);
}
#endif
@ -377,7 +241,7 @@ void send_can(CAN_FIFOMailBox_TypeDef *to_push, int flags);
// CAN receive handlers
// blink blue when we are receiving CAN messages
void can_rx(CAN_TypeDef *CAN, int can_index) {
int can_number = can_numbering[can_index];
//int can_number = can_numbering[can_index];
while (CAN->RF0R & CAN_RF0R_FMP0) {
// can is live
pending_can_live = 1;
@ -391,18 +255,18 @@ void can_rx(CAN_TypeDef *CAN, int can_index) {
// forwarding (panda only)
#ifdef PANDA
if (can_forwarding[can_index] != -1 && can_numbering[can_forwarding[can_index]] != -1) {
if (can_forwarding[can_index] != -1 && can_forwarding[can_index] != -1) {
CAN_FIFOMailBox_TypeDef to_send;
to_send.RIR = to_push.RIR | 1; // TXRQ
to_send.RDTR = to_push.RDTR;
to_send.RDLR = to_push.RDLR;
to_send.RDHR = to_push.RDHR;
send_can(&to_send, can_numbering[can_forwarding[can_index]]);
send_can(&to_send, can_forwarding[can_index]);
}
#endif
// modify RDTR for our API
to_push.RDTR = (to_push.RDTR & 0xFFFF000F) | (can_number << 4);
to_push.RDTR = (to_push.RDTR & 0xFFFF000F) | (can_index << 4);
safety_rx_hook(&to_push);
@ -491,6 +355,17 @@ void set_fan_speed(int fan_speed) {
TIM3->CCR3 = fan_speed;
}
void usb_cb_ep0_out(uint8_t *usbdata, int len, int hardwired) {
if(setup.b.bRequest == 0xde){
puts("Setting baud rate from usb\n");
uint32_t bitrate = *(int*)usbdata;
uint16_t canb_id = setup.b.wValue.w;
can_bitrate[canb_id] = bitrate;
can_init(canb_id);
}
}
int usb_cb_ep1_in(uint8_t *usbdata, int len, int hardwired) {
CAN_FIFOMailBox_TypeDef *reply = (CAN_FIFOMailBox_TypeDef *)usbdata;;
@ -513,27 +388,30 @@ void usb_cb_ep2_out(uint8_t *usbdata, int len, int hardwired) {
void send_can(CAN_FIFOMailBox_TypeDef *to_push, int flags) {
int i;
CAN_TypeDef *CAN;
can_ring *can_q;
if (flags == can_numbering[0]) {
CAN = CAN1;
uart_ring *lin_ring;
CAN_TypeDef *CAN = can_numbering[flags];
switch(flags){
case 0:
can_q = &can_tx1_q;
} else if (flags == can_numbering[1]) {
CAN = CAN2;
break;
case 1:
can_q = &can_tx2_q;
break;
#ifdef CAN3
} else if (flags == can_numbering[2]) {
CAN = CAN3;
case 2:
can_q = &can_tx3_q;
break;
#endif
} else if (flags == 8 || flags == 9) {
case 8:
case 9:
// fake LIN as CAN
uart_ring *lin_ring = (flags == 8) ? &lin1_ring : &lin2_ring;
lin_ring = (flags == 8) ? &lin1_ring : &lin2_ring;
for (i = 0; i < min(8, to_push->RDTR & 0xF); i++) {
putc(lin_ring, ((uint8_t*)&to_push->RDLR)[i]);
}
return;
} else {
default:
// no crash
return;
}
@ -549,6 +427,7 @@ void send_can(CAN_FIFOMailBox_TypeDef *to_push, int flags) {
// send on CAN
void usb_cb_ep3_out(uint8_t *usbdata, int len, int hardwired) {
puts("usb_cb_ep3_out called\n");
int dpkt = 0;
for (dpkt = 0; dpkt < len; dpkt += 0x10) {
uint32_t *tf = (uint32_t*)(&usbdata[dpkt]);
@ -652,10 +531,10 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, int hardwired) {
case 0xdc: // set controls allowed
controls_allowed = setup->b.wValue.w == 0x1337;
// take CAN out of SILM, careful with speed!
can_init(CAN1, 0);
can_init(CAN2, 0);
can_init(0);
can_init(1);
#ifdef CAN3
can_init(CAN3, 0);
can_init(2);
#endif
break;
case 0xdd: // enable can forwarding
@ -666,6 +545,27 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, int hardwired) {
}
}
break;
case 0xde: // Set Can bitrate
puts("Set can bitrate\n");
if (!(setup->b.wValue.w < CAN_MAX && setup->b.wLength.w == 4)) {
return -1;
}
break;
case 0xdf: // Set Can bitrate
puts("Get can bitrate\n");
if (setup->b.wValue.w < CAN_MAX) {
//TODO: Make fail if asking for can3 and no can3
puts("Canid: ");
puth(setup->b.wValue.w);
puts(" bitrate: ");
puth(can_bitrate[setup->b.wValue.w]);
puts("\n");
memcpy(resp, (void *)&can_bitrate[setup->b.wValue.w], 4);
resp_len = 4;
}else{
return -1;
}
break;
case 0xe0: // uart read
ur = get_ring_by_number(setup->b.wValue.w);
if (!ur) break;
@ -751,7 +651,7 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, int hardwired) {
puts("NO HANDLER ");
puth(setup->b.bRequest);
puts("\n");
break;
return -1;
}
return resp_len;
}
@ -867,27 +767,24 @@ int main() {
uart_init(USART3, 10400);
USART3->CR2 |= USART_CR2_LINEN;
/*puts("EXTERNAL");
puth(has_external_debug_serial);
puts("\n");*/
// enable USB
usb_init();
// default to silent mode to prevent issues with Ford
#ifdef PANDA_SAFETY
can_init(CAN1, 1);
can_init(CAN2, 1);
#ifdef CAN3
can_init(CAN3, 1);
#endif
controls_allowed = 0;
#else
can_init(CAN1, 0);
can_init(CAN2, 0);
#ifdef CAN3
can_init(CAN3, 0);
#endif
controls_allowed = 1;
#endif
puts("Can0 default bitrate ");
puth(can_bitrate[0]);
puts("\n");
can_init(0);
can_init(1);
#ifdef CAN3
can_init(2);
#endif
adc_init();

View File

@ -1,3 +1,5 @@
#include "libc.h"
/*void lock_bootloader() {
if (FLASH->OPTCR & FLASH_OPTCR_nWRP_0) {
FLASH->OPTKEYR = 0x08192A3B;

135
board/uart.c 100644
View File

@ -0,0 +1,135 @@
#include <stdint.h>
#include "config.h"
#include "uart.h"
#include "early.h"
uart_ring debug_ring = { .w_ptr_tx = 0, .r_ptr_tx = 0,
.w_ptr_rx = 0, .r_ptr_rx = 0,
.uart = USART2,
.callback = debug_ring_callback};
void uart_set_baud(USART_TypeDef *u, int baud) {
if (u == USART1) {
// USART1 is on APB2
u->BRR = __USART_BRR(48000000, baud);
} else {
u->BRR = __USART_BRR(24000000, baud);
}
}
void uart_init(USART_TypeDef *u, int baud) {
// enable uart and tx+rx mode
u->CR1 = USART_CR1_UE;
uart_set_baud(u, baud);
u->CR1 |= USART_CR1_TE | USART_CR1_RE;
//u->CR2 = USART_CR2_STOP_0 | USART_CR2_STOP_1;
//u->CR2 = USART_CR2_STOP_0;
// ** UART is ready to work **
// enable interrupts
u->CR1 |= USART_CR1_RXNEIE;
}
void putch(const char a) {
if (has_external_debug_serial) {
putc(&debug_ring, a);
} else {
injectc(&debug_ring, a);
}
}
int puts(const char *a) {
for (;*a;a++) {
if (*a == '\n') putch('\r');
putch(*a);
}
return 0;
}
void puth(unsigned int i) {
int pos;
char c[] = "0123456789abcdef";
for (pos = 28; pos != -4; pos -= 4) {
putch(c[(i >> pos) & 0xF]);
}
}
void puth2(unsigned int i) {
int pos;
char c[] = "0123456789abcdef";
for (pos = 4; pos != -4; pos -= 4) {
putch(c[(i >> pos) & 0xF]);
}
}
void hexdump(void *a, int l) {
int i;
for (i=0;i<l;i++) {
if (i != 0 && (i&0xf) == 0) puts("\n");
puth2(((unsigned char*)a)[i]);
puts(" ");
}
puts("\n");
}
int getc(uart_ring *q, char *elem) {
if (q->w_ptr_rx != q->r_ptr_rx) {
*elem = q->elems_rx[q->r_ptr_rx];
q->r_ptr_rx += 1;
return 1;
}
return 0;
}
int putc(uart_ring *q, char elem) {
uint8_t next_w_ptr = q->w_ptr_tx + 1;
int ret = 0;
if (next_w_ptr != q->r_ptr_tx) {
q->elems_tx[q->w_ptr_tx] = elem;
q->w_ptr_tx = next_w_ptr;
ret = 1;
}
uart_ring_process(q);
return ret;
}
int injectc(uart_ring *q, char elem) {
uint8_t next_w_ptr = q->w_ptr_rx + 1;
int ret = 0;
if (next_w_ptr != q->r_ptr_rx) {
q->elems_rx[q->w_ptr_rx] = elem;
q->w_ptr_rx = next_w_ptr;
ret = 1;
}
return ret;
}
void uart_ring_process(uart_ring *q) {
// TODO: check if external serial is connected
int sr = q->uart->SR;
if (q->w_ptr_tx != q->r_ptr_tx) {
if (sr & USART_SR_TXE) {
q->uart->DR = q->elems_tx[q->r_ptr_tx];
q->r_ptr_tx += 1;
} else {
// push on interrupt later
q->uart->CR1 |= USART_CR1_TXEIE;
}
} else {
// nothing to send
q->uart->CR1 &= ~USART_CR1_TXEIE;
}
if (sr & USART_SR_RXNE) {
uint8_t c = q->uart->DR; // TODO: can drop packets
uint8_t next_w_ptr = q->w_ptr_rx + 1;
if (next_w_ptr != q->r_ptr_rx) {
q->elems_rx[q->w_ptr_rx] = c;
q->w_ptr_rx = next_w_ptr;
if (q->callback) q->callback(q);
}
}
}

View File

@ -1,70 +1,48 @@
#define __DIV(_PCLK_, _BAUD_) (((_PCLK_)*25)/(4*(_BAUD_)))
#define __DIVMANT(_PCLK_, _BAUD_) (__DIV((_PCLK_), (_BAUD_))/100)
#define __DIVFRAQ(_PCLK_, _BAUD_) (((__DIV((_PCLK_), (_BAUD_)) - (__DIVMANT((_PCLK_), (_BAUD_)) * 100)) * 16 + 50) / 100)
#define __USART_BRR(_PCLK_, _BAUD_) ((__DIVMANT((_PCLK_), (_BAUD_)) << 4)|(__DIVFRAQ((_PCLK_), (_BAUD_)) & 0x0F))
#ifndef PANDA_UART_H
#define PANDA_UART_H
void uart_set_baud(USART_TypeDef *u, int baud) {
if (u == USART1) {
// USART1 is on APB2
u->BRR = __USART_BRR(48000000, baud);
} else {
u->BRR = __USART_BRR(24000000, baud);
}
}
#define __DIV(_PCLK_, _BAUD_) (((_PCLK_)*25)/(4*(_BAUD_)))
#define __DIVMANT(_PCLK_, _BAUD_) (__DIV((_PCLK_), (_BAUD_))/100)
#define __DIVFRAQ(_PCLK_, _BAUD_) (((__DIV((_PCLK_), (_BAUD_)) - (__DIVMANT((_PCLK_), (_BAUD_)) * 100)) * 16 + 50) / 100)
#define __USART_BRR(_PCLK_, _BAUD_) ((__DIVMANT((_PCLK_), (_BAUD_)) << 4)|(__DIVFRAQ((_PCLK_), (_BAUD_)) & 0x0F))
void uart_init(USART_TypeDef *u, int baud) {
// enable uart and tx+rx mode
u->CR1 = USART_CR1_UE;
uart_set_baud(u, baud);
u->CR1 |= USART_CR1_TE | USART_CR1_RE;
//u->CR2 = USART_CR2_STOP_0 | USART_CR2_STOP_1;
//u->CR2 = USART_CR2_STOP_0;
// ** UART is ready to work **
typedef struct uart_ring {
uint8_t w_ptr_tx;
uint8_t r_ptr_tx;
uint8_t elems_tx[FIFO_SIZE];
uint8_t w_ptr_rx;
uint8_t r_ptr_rx;
uint8_t elems_rx[FIFO_SIZE];
USART_TypeDef *uart;
void (*callback)(struct uart_ring*);
} uart_ring;
// enable interrupts
u->CR1 |= USART_CR1_RXNEIE;
}
extern int has_external_debug_serial;
void putch(const char a) {
if (has_external_debug_serial) {
putc(&debug_ring, a);
} else {
injectc(&debug_ring, a);
}
}
extern uart_ring debug_ring;
int puts(const char *a) {
for (;*a;a++) {
if (*a == '\n') putch('\r');
putch(*a);
}
return 0;
}
void debug_ring_callback(uart_ring *ring);
void puth(unsigned int i) {
int pos;
char c[] = "0123456789abcdef";
for (pos = 28; pos != -4; pos -= 4) {
putch(c[(i >> pos) & 0xF]);
}
}
void uart_set_baud(USART_TypeDef *u, int baud);
void puth2(unsigned int i) {
int pos;
char c[] = "0123456789abcdef";
for (pos = 4; pos != -4; pos -= 4) {
putch(c[(i >> pos) & 0xF]);
}
}
void uart_init(USART_TypeDef *u, int baud);
void hexdump(void *a, int l) {
int i;
for (i=0;i<l;i++) {
if (i != 0 && (i&0xf) == 0) puts("\n");
puth2(((unsigned char*)a)[i]);
puts(" ");
}
puts("\n");
}
void putch(const char a);
int puts(const char *a);
void puth(unsigned int i);
void puth2(unsigned int i);
void hexdump(void *a, int l);
int getc(uart_ring *q, char *elem);
int putc(uart_ring *q, char elem);
int injectc(uart_ring *q, char elem);
void uart_ring_process(uart_ring *q);
#endif

View File

@ -80,6 +80,7 @@ USB_Setup_TypeDef;
// interfaces
void usb_cb_enumeration_complete();
int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *usbdata, int hardwired);
void usb_cb_ep0_out(uint8_t *usbdata, int len, int hardwired);
int usb_cb_ep1_in(uint8_t *usbdata, int len, int hardwired);
void usb_cb_ep2_out(uint8_t *usbdata, int len, int hardwired);
void usb_cb_ep3_out(uint8_t *usbdata, int len, int hardwired);
@ -221,8 +222,8 @@ void *USB_ReadPacket(void *dest, uint16_t len) {
void USB_WritePacket(const uint8_t *src, uint16_t len, uint32_t ep) {
#ifdef DEBUG_USB
puts("writing ");
hexdump(src, len);
//puts("writing ");
//hexdump(src, len);
#endif
uint8_t numpacket = (len+(MAX_RESP_LEN-1))/MAX_RESP_LEN;
@ -405,11 +406,19 @@ void usb_setup() {
current_int0_alt_setting = setup.b.wValue.w;
USB_WritePacket(0, 0, 0);
USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
//USBx_INEP(0)->DIEPINT = USBx_INEP(0)->DIEPINT
puts("Setting Interface Alt: ");
puth(current_int0_alt_setting);
puts("\n");
break;
default:
resp_len = usb_cb_control_msg(&setup, resp, 1);
USB_WritePacket(resp, min(resp_len, setup.b.wLength.w), 0);
USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
if(resp_len == -1){
USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_STALL;
}else{
USB_WritePacket(resp, min(resp_len, setup.b.wLength.w), 0);
USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
}
}
}
@ -470,10 +479,11 @@ void usb_init() {
// all interrupts except TXFIFO EMPTY
//USBx->GINTMSK = 0xFFFFFFFF & ~(USB_OTG_GINTMSK_NPTXFEM | USB_OTG_GINTMSK_PTXFEM | USB_OTG_GINTSTS_SOF | USB_OTG_GINTSTS_EOPF);
//USBx->GINTMSK = 0xFFFFFFFF & ~(USB_OTG_GINTMSK_NPTXFEM | USB_OTG_GINTMSK_PTXFEM);
USBx->GINTMSK = USB_OTG_GINTMSK_USBRST | USB_OTG_GINTMSK_ENUMDNEM | USB_OTG_GINTMSK_OTGINT |
USB_OTG_GINTMSK_RXFLVLM | USB_OTG_GINTMSK_GONAKEFFM | USB_OTG_GINTMSK_GINAKEFFM |
USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT | USB_OTG_GINTMSK_USBSUSPM |
USB_OTG_GINTMSK_CIDSCHGM | USB_OTG_GINTMSK_SRQIM | USB_OTG_GINTMSK_MMISM;
//SRQ is when a 'session' starts.
USBx->GINTMSK = USB_OTG_GINTMSK_SRQIM | USB_OTG_GINTMSK_CIDSCHGM | USB_OTG_GINTMSK_OEPINT |
USB_OTG_GINTMSK_IEPINT | USB_OTG_GINTMSK_ENUMDNEM | USB_OTG_GINTMSK_USBRST |
USB_OTG_GINTMSK_USBSUSPM | USB_OTG_GINTMSK_GONAKEFFM | USB_OTG_GINTMSK_GINAKEFFM |
USB_OTG_GINTMSK_RXFLVLM | USB_OTG_GINTMSK_OTGINT | USB_OTG_GINTMSK_MMISM;
USBx->GAHBCFG = USB_OTG_GAHBCFG_GINT;
@ -483,7 +493,7 @@ void usb_init() {
}
// ***************************** USB port *****************************
int dumb = 0;
void usb_irqhandler(void) {
//USBx->GINTMSK = 0;
@ -558,6 +568,10 @@ void usb_irqhandler(void) {
hexdump(&usbdata, len);
#endif
if(endpoint == 0){
usb_cb_ep0_out(usbdata, len, 1);
}
if (endpoint == 2) {
usb_cb_ep2_out(usbdata, len, 1);
}
@ -690,6 +704,12 @@ void usb_irqhandler(void) {
case 0: ////// Bulk config
// *** IN token received when TxFIFO is empty
if (USBx_INEP(1)->DIEPINT & USB_OTG_DIEPMSK_ITTXFEMSK) {
puth(dumb++);
if (can_rx_q.w_ptr != can_rx_q.r_ptr)
puts("Rx CAN bulk: There is CAN data to send.\n");
else
puts("Rx CAN bulk: No can data\n");
#ifdef DEBUG_USB
puts(" IN PACKET QUEUE\n");
#endif