commit
14fb17e22f
257 changed files with 54725 additions and 0 deletions
@ -0,0 +1,12 @@ |
||||
*.pyc |
||||
.*.swp |
||||
.*.swo |
||||
*.o |
||||
a.out |
||||
*~ |
||||
.#* |
||||
dist/ |
||||
pandacan.egg-info/ |
||||
board/obj/ |
||||
examples/output.csv |
||||
.DS_Store |
@ -0,0 +1,20 @@ |
||||
language: python |
||||
|
||||
cache: |
||||
directories: |
||||
- build/commaai/panda/boardesp/esp-open-sdk/crosstool-NG |
||||
|
||||
addons: |
||||
apt: |
||||
packages: |
||||
- gcc-arm-none-eabi |
||||
- libnewlib-arm-none-eabi |
||||
- gperf |
||||
- texinfo |
||||
- help2man |
||||
|
||||
script: |
||||
- python setup.py install |
||||
- pushd board && make bin && popd |
||||
- pushd boardesp && git clone --recursive https://github.com/pfalcon/esp-open-sdk.git && pushd esp-open-sdk && git checkout 03f5e898a059451ec5f3de30e7feff30455f7cec && LD_LIBRARY_PATH="" make STANDALONE=y && popd && popd |
||||
- pushd boardesp && make user1.bin && popd |
@ -0,0 +1,7 @@ |
||||
Copyright (c) 2016, Comma.ai, Inc. |
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: |
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. |
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
@ -0,0 +1,31 @@ |
||||
** Projects ** |
||||
|
||||
== ELM327 Emulator == |
||||
|
||||
Write an elm327 emulator in boardesp/elm327.c and make it work with Torque |
||||
|
||||
You'll find a start at this in the "elm327" branch. |
||||
|
||||
== socketcan Kernel Driver == |
||||
|
||||
Write a kernel driver version of lib/panda.py that exposes the Panda on socketcan and makes it work with those tools. |
||||
|
||||
You may want to switch to interrupt endpoint first. Should LIN be exposed as a serial interface? |
||||
|
||||
== Windows J2534 DLL == |
||||
|
||||
Write a Windows DLL that exposes the J2534 API. |
||||
|
||||
Will make the Panda work with car diagnostic software. |
||||
|
||||
|
||||
** Refactors ** |
||||
|
||||
== USB Interrupt Endpoint == |
||||
|
||||
Switch USB to use an interrupt endpoint instead of a bulk endpoint for can recv |
||||
|
||||
== WebSocket Support == |
||||
|
||||
Add CAN streaming over WebSocket to the ELM code in addition to the UDP pipe. |
||||
|
@ -0,0 +1,9 @@ |
||||
# Updating your panda |
||||
|
||||
Panda should update automatically via the [Chffr](http://chffr.comma.ai/) app ([apple](https://itunes.apple.com/us/app/chffr-dash-cam-that-remembers/id1146683979) and [android](https://play.google.com/store/apps/details?id=ai.comma.chffr)) |
||||
|
||||
If it doesn't however, you can use the following commands on linux or Mac OSX |
||||
`sudo pip install --upgrade pandacan` |
||||
` PYTHONPATH="" sudo python -c "import panda; panda.flash_release()"` |
||||
|
||||
(You'll need to have `pip` and `sudo` installed.) |
@ -0,0 +1 @@ |
||||
v1.0.3 |
@ -0,0 +1 @@ |
||||
from .python import Panda, PandaWifiStreaming, PandaDFU, ESPROM, CesantaFlasher, flash_release, BASEDIR, ensure_st_up_to_date, build_st |
@ -0,0 +1,8 @@ |
||||
PROJ_NAME = panda
|
||||
CFLAGS = -g -Wall
|
||||
|
||||
CFLAGS += -mlittle-endian -mthumb -mcpu=cortex-m4
|
||||
CFLAGS += -mhard-float -DSTM32F4 -DSTM32F413xx
|
||||
STARTUP_FILE = startup_stm32f413xx
|
||||
|
||||
include build.mk |
@ -0,0 +1,9 @@ |
||||
# :set noet
|
||||
PROJ_NAME = comma
|
||||
CFLAGS = -g -Wall
|
||||
|
||||
CFLAGS += -mlittle-endian -mthumb -mcpu=cortex-m3
|
||||
CFLAGS += -msoft-float -DSTM32F2 -DSTM32F205xx
|
||||
STARTUP_FILE = startup_stm32f205xx
|
||||
|
||||
include build.mk |
@ -0,0 +1,41 @@ |
||||
Dependencies |
||||
-------- |
||||
|
||||
**Mac** |
||||
|
||||
``` |
||||
./get_sdk_mac.sh |
||||
``` |
||||
|
||||
**Debian / Ubuntu** |
||||
|
||||
``` |
||||
./get_sdk.sh |
||||
``` |
||||
|
||||
|
||||
Programming |
||||
---- |
||||
|
||||
**Panda** |
||||
|
||||
``` |
||||
make |
||||
``` |
||||
|
||||
**NEO** |
||||
|
||||
``` |
||||
make -f Makefile.legacy |
||||
``` |
||||
|
||||
Troubleshooting |
||||
---- |
||||
|
||||
If your panda will not flash and is quickly blinking a single Green LED, use: |
||||
``` |
||||
make recover |
||||
``` |
||||
|
||||
|
||||
[dfu-util](http://github.com/dsigma/dfu-util.git) for flashing |
@ -0,0 +1,91 @@ |
||||
#define BOOTSTUB |
||||
|
||||
#include "config.h" |
||||
#include "obj/gitversion.h" |
||||
|
||||
#ifdef STM32F4 |
||||
#define PANDA |
||||
#include "stm32f4xx.h" |
||||
#include "stm32f4xx_hal_gpio_ex.h" |
||||
#else |
||||
#include "stm32f2xx.h" |
||||
#include "stm32f2xx_hal_gpio_ex.h" |
||||
#endif |
||||
|
||||
#include "libc.h" |
||||
#include "provision.h" |
||||
|
||||
#include "drivers/drivers.h" |
||||
|
||||
#include "drivers/llgpio.h" |
||||
#include "gpio.h" |
||||
|
||||
#include "drivers/spi.h" |
||||
#include "drivers/usb.h" |
||||
//#include "drivers/uart.h"
|
||||
|
||||
int puts(const char *a) { return 0; } |
||||
void puth(unsigned int i) {} |
||||
|
||||
#include "crypto/rsa.h" |
||||
#include "crypto/sha.h" |
||||
|
||||
#include "obj/cert.h" |
||||
|
||||
#include "spi_flasher.h" |
||||
|
||||
void __initialize_hardware_early() { |
||||
early(); |
||||
} |
||||
|
||||
void fail() { |
||||
soft_flasher_start(); |
||||
} |
||||
|
||||
// know where to sig check
|
||||
extern void *_app_start[]; |
||||
|
||||
int main() { |
||||
__disable_irq(); |
||||
clock_init(); |
||||
detect(); |
||||
|
||||
if (revision == PANDA_REV_C) { |
||||
set_usb_power_mode(USB_POWER_CLIENT); |
||||
} |
||||
|
||||
if (enter_bootloader_mode == ENTER_SOFTLOADER_MAGIC) { |
||||
enter_bootloader_mode = 0; |
||||
soft_flasher_start(); |
||||
} |
||||
|
||||
// validate length
|
||||
int len = (int)_app_start[0]; |
||||
if ((len < 8) || (len > (0x1000000 - 0x4000 - 4 - RSANUMBYTES))) goto fail; |
||||
|
||||
// compute SHA hash
|
||||
uint8_t digest[SHA_DIGEST_SIZE]; |
||||
SHA_hash(&_app_start[1], len-4, digest); |
||||
|
||||
// verify RSA signature
|
||||
if (RSA_verify(&release_rsa_key, ((void*)&_app_start[0]) + len, RSANUMBYTES, digest, SHA_DIGEST_SIZE)) { |
||||
goto good; |
||||
} |
||||
|
||||
// allow debug if built from source
|
||||
#ifdef ALLOW_DEBUG |
||||
if (RSA_verify(&debug_rsa_key, ((void*)&_app_start[0]) + len, RSANUMBYTES, digest, SHA_DIGEST_SIZE)) { |
||||
goto good; |
||||
} |
||||
#endif |
||||
|
||||
// here is a failure
|
||||
fail: |
||||
fail(); |
||||
return 0; |
||||
good: |
||||
// jump to flash
|
||||
((void(*)()) _app_start[1])(); |
||||
return 0; |
||||
} |
||||
|
@ -0,0 +1,59 @@ |
||||
CFLAGS += -I inc -I ../ -nostdlib -fno-builtin -std=gnu11 -O0
|
||||
CFLAGS += -Tstm32_flash.ld
|
||||
|
||||
CC = arm-none-eabi-gcc
|
||||
OBJCOPY = arm-none-eabi-objcopy
|
||||
OBJDUMP = arm-none-eabi-objdump
|
||||
|
||||
ifeq ($(RELEASE),1) |
||||
CERT = ../../pandaextra/certs/release
|
||||
else |
||||
# enable the debug cert
|
||||
CERT = ../certs/debug
|
||||
CFLAGS += "-DALLOW_DEBUG"
|
||||
endif |
||||
|
||||
DFU_UTIL = "dfu-util"
|
||||
|
||||
# this no longer pushes the bootstub
|
||||
flash: obj/$(PROJ_NAME).bin |
||||
PYTHONPATH=../ python -c "from panda import Panda; Panda().flash('obj/$(PROJ_NAME).bin')"
|
||||
|
||||
ota: obj/$(PROJ_NAME).bin |
||||
curl http://192.168.0.10/stupdate --upload-file $<
|
||||
|
||||
bin: obj/$(PROJ_NAME).bin |
||||
|
||||
# this flashes everything
|
||||
recover: obj/bootstub.$(PROJ_NAME).bin obj/$(PROJ_NAME).bin |
||||
-PYTHONPATH=../ python -c "from panda import Panda; Panda().reset(enter_bootloader=True)"
|
||||
sleep 1.0
|
||||
$(DFU_UTIL) -d 0483:df11 -a 0 -s 0x08004000 -D obj/$(PROJ_NAME).bin
|
||||
$(DFU_UTIL) -d 0483:df11 -a 0 -s 0x08000000:leave -D obj/bootstub.$(PROJ_NAME).bin
|
||||
|
||||
include ../common/version.mk |
||||
|
||||
obj/cert.h: ../crypto/getcertheader.py |
||||
../crypto/getcertheader.py ../certs/debug.pub ../certs/release.pub > $@
|
||||
|
||||
obj/%.$(PROJ_NAME).o: %.c obj/cert.h obj/gitversion.h config.h drivers/*.h gpio.h libc.h provision.h safety.h safety/*.h spi_flasher.h |
||||
$(CC) $(CFLAGS) -o $@ -c $<
|
||||
|
||||
obj/%.$(PROJ_NAME).o: ../crypto/%.c |
||||
$(CC) $(CFLAGS) -o $@ -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 |
||||
# 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 |
||||
$(CC) $(CFLAGS) -o obj/bootstub.$(PROJ_NAME).elf $^
|
||||
$(OBJCOPY) -v -O binary obj/bootstub.$(PROJ_NAME).elf $@
|
||||
|
||||
clean: |
||||
@rm -f obj/*
|
@ -0,0 +1,40 @@ |
||||
#ifndef PANDA_CONFIG_H |
||||
#define PANDA_CONFIG_H |
||||
|
||||
//#define DEBUG
|
||||
//#define DEBUG_USB
|
||||
//#define DEBUG_SPI
|
||||
|
||||
#ifdef STM32F4 |
||||
#define PANDA |
||||
#include "stm32f4xx.h" |
||||
#else |
||||
#include "stm32f2xx.h" |
||||
#endif |
||||
|
||||
#define USB_VID 0xbbaa |
||||
|
||||
#ifdef BOOTSTUB |
||||
#define USB_PID 0xddee |
||||
#else |
||||
#define USB_PID 0xddcc |
||||
#endif |
||||
|
||||
#include <stdbool.h> |
||||
#define NULL ((void*)0) |
||||
#define COMPILE_TIME_ASSERT(pred) switch(0){case 0:case pred:;} |
||||
|
||||
#define min(a,b) \ |
||||
({ __typeof__ (a) _a = (a); \
|
||||
__typeof__ (b) _b = (b); \
|
||||
_a < _b ? _a : _b; }) |
||||
|
||||
#define max(a,b) \ |
||||
({ __typeof__ (a) _a = (a); \
|
||||
__typeof__ (b) _b = (b); \
|
||||
_a > _b ? _a : _b; }) |
||||
|
||||
#define MAX_RESP_LEN 0x40 |
||||
|
||||
#endif |
||||
|
@ -0,0 +1,38 @@ |
||||
// ACCEL1 = ADC10
|
||||
// ACCEL2 = ADC11
|
||||
// VOLT_S = ADC12
|
||||
// CURR_S = ADC13
|
||||
|
||||
#define ADCCHAN_ACCEL0 10 |
||||
#define ADCCHAN_ACCEL1 11 |
||||
#define ADCCHAN_VOLTAGE 12 |
||||
#define ADCCHAN_CURRENT 13 |
||||
|
||||
void adc_init() { |
||||
// global setup
|
||||
ADC->CCR = ADC_CCR_TSVREFE | ADC_CCR_VBATE; |
||||
//ADC1->CR2 = ADC_CR2_ADON | ADC_CR2_EOCS | ADC_CR2_DDS;
|
||||
ADC1->CR2 = ADC_CR2_ADON; |
||||
|
||||
// long
|
||||
//ADC1->SMPR1 = ADC_SMPR1_SMP10 | ADC_SMPR1_SMP11 | ADC_SMPR1_SMP12 | ADC_SMPR1_SMP13;
|
||||
ADC1->SMPR1 = ADC_SMPR1_SMP12 | ADC_SMPR1_SMP13; |
||||
} |
||||
|
||||
uint32_t adc_get(int channel) { |
||||
// includes length
|
||||
//ADC1->SQR1 = 0;
|
||||
|
||||
// select channel
|
||||
ADC1->JSQR = channel << 15; |
||||
|
||||
//ADC1->CR1 = ADC_CR1_DISCNUM_0;
|
||||
//ADC1->CR1 = ADC_CR1_EOCIE;
|
||||
|
||||
ADC1->SR &= ~(ADC_SR_JEOC); |
||||
ADC1->CR2 |= ADC_CR2_JSWSTART; |
||||
while (!(ADC1->SR & ADC_SR_JEOC)); |
||||
|
||||
return ADC1->JDR1; |
||||
} |
||||
|
@ -0,0 +1,401 @@ |
||||
// IRQs: CAN1_TX, CAN1_RX0, CAN1_SCE, CAN2_TX, CAN2_RX0, CAN2_SCE, CAN3_TX, CAN3_RX0, CAN3_SCE
|
||||
#define ALL_CAN_SILENT 0xFF |
||||
#define ALL_CAN_BUT_MAIN_SILENT 0xFE |
||||
#define ALL_CAN_LIVE 0 |
||||
|
||||
int can_live = 0, pending_can_live = 0, can_loopback = 0, can_silent = ALL_CAN_SILENT; |
||||
|
||||
// ********************* instantiate queues *********************
|
||||
|
||||
#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 }; |
||||
|
||||
can_buffer(rx_q, 0x1000) |
||||
can_buffer(tx1_q, 0x100) |
||||
can_buffer(tx2_q, 0x100) |
||||
|
||||
#ifdef PANDA |
||||
can_buffer(tx3_q, 0x100) |
||||
can_buffer(txgmlan_q, 0x100) |
||||
can_ring *can_queues[] = {&can_tx1_q, &can_tx2_q, &can_tx3_q, &can_txgmlan_q}; |
||||
#else |
||||
can_ring *can_queues[] = {&can_tx1_q, &can_tx2_q}; |
||||
#endif |
||||
|
||||
// ********************* interrupt safe queue *********************
|
||||
|
||||
int can_pop(can_ring *q, CAN_FIFOMailBox_TypeDef *elem) { |
||||
int ret = 0; |
||||
|
||||
enter_critical_section(); |
||||
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; |
||||
ret = 1; |
||||
} |
||||
exit_critical_section(); |
||||
|
||||
return ret; |
||||
} |
||||
|
||||
int can_push(can_ring *q, CAN_FIFOMailBox_TypeDef *elem) { |
||||
int ret = 0; |
||||
uint32_t next_w_ptr; |
||||
|
||||
enter_critical_section(); |
||||
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; |
||||
ret = 1; |
||||
} |
||||
exit_critical_section(); |
||||
if (ret == 0) puts("can_push failed!\n"); |
||||
return ret; |
||||
} |
||||
|
||||
void can_clear(can_ring *q) { |
||||
enter_critical_section(); |
||||
q->w_ptr = 0; |
||||
q->r_ptr = 0; |
||||
exit_critical_section(); |
||||
} |
||||
|
||||
// assign CAN numbering
|
||||
// bus num: Can bus number on ODB connector. Sent to/from USB
|
||||
// Min: 0; Max: 127; Bit 7 marks message as receipt (bus 129 is receipt for but 1)
|
||||
// cans: Look up MCU can interface from bus number
|
||||
// can number: numeric lookup for MCU CAN interfaces (0 = CAN1, 1 = CAN2, etc);
|
||||
// bus_lookup: Translates from 'can number' to 'bus number'.
|
||||
// can_num_lookup: Translates from 'bus number' to 'can number'.
|
||||
// can_forwarding: Given a bus num, lookup bus num to forward to. -1 means no forward.
|
||||
|
||||
int can_rx_cnt = 0; |
||||
int can_tx_cnt = 0; |
||||
int can_txd_cnt = 0; |
||||
int can_err_cnt = 0; |
||||
|
||||
// NEO: Bus 1=CAN1 Bus 2=CAN2
|
||||
// Panda: Bus 0=CAN1 Bus 1=CAN2 Bus 2=CAN3
|
||||
#ifdef PANDA |
||||
CAN_TypeDef *cans[] = {CAN1, CAN2, CAN3}; |
||||
uint8_t bus_lookup[] = {0,1,2}; |
||||
uint8_t can_num_lookup[] = {0,1,2,-1}; |
||||
int8_t can_forwarding[] = {-1,-1,-1,-1}; |
||||
uint32_t can_speed[] = {5000, 5000, 5000, 333}; |
||||
#define CAN_MAX 3 |
||||
#else |
||||
CAN_TypeDef *cans[] = {CAN1, CAN2}; |
||||
uint8_t bus_lookup[] = {1,0}; |
||||
uint8_t can_num_lookup[] = {1,0}; |
||||
int8_t can_forwarding[] = {-1,-1}; |
||||
uint32_t can_speed[] = {5000, 5000}; |
||||
#define CAN_MAX 2 |
||||
#endif |
||||
|
||||
#define CANIF_FROM_CAN_NUM(num) (cans[num]) |
||||
#define BUS_NUM_FROM_CAN_NUM(num) (bus_lookup[num]) |
||||
#define CAN_NUM_FROM_BUS_NUM(num) (can_num_lookup[num]) |
||||
|
||||
// other option
|
||||
/*#define CAN_QUANTA 16
|
||||
#define CAN_SEQ1 13 |
||||
#define CAN_SEQ2 2*/ |
||||
|
||||
// this is needed for 1 mbps support
|
||||
#define CAN_QUANTA 8 |
||||
#define CAN_SEQ1 6 // roundf(quanta * 0.875f) - 1;
|
||||
#define CAN_SEQ2 1 // roundf(quanta * 0.125f);
|
||||
|
||||
#define CAN_PCLK 24000 |
||||
// 333 = 33.3 kbps
|
||||
// 5000 = 500 kbps
|
||||
#define can_speed_to_prescaler(x) (CAN_PCLK / CAN_QUANTA * 10 / (x)) |
||||
|
||||
void process_can(uint8_t can_number); |
||||
|
||||
void can_init(uint8_t can_number) { |
||||
if (can_number == 0xff) return; |
||||
|
||||
CAN_TypeDef *CAN = CANIF_FROM_CAN_NUM(can_number); |
||||
set_can_enable(CAN, 1); |
||||
|
||||
CAN->MCR = CAN_MCR_TTCM | CAN_MCR_INRQ; |
||||
while((CAN->MSR & CAN_MSR_INAK) != CAN_MSR_INAK); |
||||
|
||||
// set time quanta from defines
|
||||
CAN->BTR = (CAN_BTR_TS1_0 * (CAN_SEQ1-1)) | |
||||
(CAN_BTR_TS2_0 * (CAN_SEQ2-1)) | |
||||
(can_speed_to_prescaler(can_speed[BUS_NUM_FROM_CAN_NUM(can_number)]) - 1); |
||||
|
||||
// silent loopback mode for debugging
|
||||
if (can_loopback) { |
||||
CAN->BTR |= CAN_BTR_SILM | CAN_BTR_LBKM; |
||||
} |
||||
|
||||
if (can_silent & (1 << can_number)) { |
||||
CAN->BTR |= CAN_BTR_SILM; |
||||
} |
||||
|
||||
// reset
|
||||
CAN->MCR = CAN_MCR_TTCM | CAN_MCR_ABOM; |
||||
|
||||
#define CAN_TIMEOUT 1000000 |
||||
int tmp = 0; |
||||
while((CAN->MSR & CAN_MSR_INAK) == CAN_MSR_INAK && tmp < CAN_TIMEOUT) tmp++; |
||||
|
||||
if (tmp == CAN_TIMEOUT) { |
||||
puts("CAN init FAILED!!!!!\n"); |
||||
puth(can_number); puts(" "); |
||||
puth(BUS_NUM_FROM_CAN_NUM(can_number)); puts("\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 certain CAN interrupts
|
||||
CAN->IER = CAN_IER_TMEIE | CAN_IER_FMPIE0; |
||||
|
||||
switch (can_number) { |
||||
case 0: |
||||
NVIC_EnableIRQ(CAN1_TX_IRQn); |
||||
NVIC_EnableIRQ(CAN1_RX0_IRQn); |
||||
NVIC_EnableIRQ(CAN1_SCE_IRQn); |
||||
break; |
||||
case 1: |
||||
NVIC_EnableIRQ(CAN2_TX_IRQn); |
||||
NVIC_EnableIRQ(CAN2_RX0_IRQn); |
||||
NVIC_EnableIRQ(CAN2_SCE_IRQn); |
||||
break; |
||||
#ifdef CAN3 |
||||
case 2: |
||||
NVIC_EnableIRQ(CAN3_TX_IRQn); |
||||
NVIC_EnableIRQ(CAN3_RX0_IRQn); |
||||
NVIC_EnableIRQ(CAN3_SCE_IRQn); |
||||
break; |
||||
#endif |
||||
} |
||||
|
||||
// in case there are queued up messages
|
||||
process_can(can_number); |
||||
} |
||||
|
||||
void can_init_all() { |
||||
for (int i=0; i < CAN_MAX; i++) { |
||||
can_init(i); |
||||
} |
||||
} |
||||
|
||||
void can_set_gmlan(int bus) { |
||||
if (bus == -1 || bus != can_num_lookup[3]) { |
||||
// GMLAN OFF
|
||||
switch (can_num_lookup[3]) { |
||||
case 1: |
||||
puts("disable GMLAN on CAN2\n"); |
||||
set_can_mode(1, 0); |
||||
bus_lookup[1] = 1; |
||||
can_num_lookup[1] = 1; |
||||
can_num_lookup[3] = -1; |
||||
can_init(1); |
||||
break; |
||||
case 2: |
||||
puts("disable GMLAN on CAN3\n"); |
||||
set_can_mode(2, 0); |
||||
bus_lookup[2] = 2; |
||||
can_num_lookup[2] = 2; |
||||
can_num_lookup[3] = -1; |
||||
can_init(2); |
||||
break; |
||||
} |
||||
} |
||||
|
||||
if (bus == 1) { |
||||
puts("GMLAN on CAN2\n"); |
||||
// GMLAN on CAN2
|
||||
set_can_mode(1, 1); |
||||
bus_lookup[1] = 3; |
||||
can_num_lookup[1] = -1; |
||||
can_num_lookup[3] = 1; |
||||
can_init(1); |
||||
} else if (bus == 2 && revision == PANDA_REV_C) { |
||||
puts("GMLAN on CAN3\n"); |
||||
// GMLAN on CAN3
|
||||
set_can_mode(2, 1); |
||||
bus_lookup[2] = 3; |
||||
can_num_lookup[2] = -1; |
||||
can_num_lookup[3] = 2; |
||||
can_init(2); |
||||
} |
||||
} |
||||
|
||||
// CAN error
|
||||
void can_sce(CAN_TypeDef *CAN) { |
||||
can_err_cnt += 1; |
||||
#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 current send
|
||||
CAN->TSR |= CAN_TSR_ABRQ0; |
||||
CAN->MSR = CAN->MSR; |
||||
} |
||||
|
||||
// ***************************** CAN *****************************
|
||||
|
||||
void process_can(uint8_t can_number) { |
||||
if (can_number == 0xff) return; |
||||
|
||||
enter_critical_section(); |
||||
|
||||
CAN_TypeDef *CAN = CANIF_FROM_CAN_NUM(can_number); |
||||
uint8_t bus_number = BUS_NUM_FROM_CAN_NUM(can_number); |
||||
#ifdef DEBUG |
||||
puts("process CAN TX\n"); |
||||
#endif |
||||
|
||||
// check for empty mailbox
|
||||
CAN_FIFOMailBox_TypeDef to_send; |
||||
if ((CAN->TSR & CAN_TSR_TME0) == CAN_TSR_TME0) { |
||||
// add successfully transmitted message to my fifo
|
||||
if ((CAN->TSR & CAN_TSR_RQCP0) == CAN_TSR_RQCP0) { |
||||
can_txd_cnt += 1; |
||||
|
||||
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_BUS_RET_FLAG | bus_number) << 4); |
||||
to_push.RDLR = CAN->sTxMailBox[0].TDLR; |
||||
to_push.RDHR = CAN->sTxMailBox[0].TDHR; |
||||
can_push(&can_rx_q, &to_push); |
||||
} |
||||
|
||||
if ((CAN->TSR & CAN_TSR_TERR0) == CAN_TSR_TERR0) { |
||||
#ifdef DEBUG |
||||
puts("CAN TX ERROR!\n"); |
||||
#endif |
||||
} |
||||
|
||||
if ((CAN->TSR & CAN_TSR_ALST0) == CAN_TSR_ALST0) { |
||||
#ifdef DEBUG |
||||
puts("CAN TX ARBITRATION LOST!\n"); |
||||
#endif |
||||
} |
||||
|
||||
// clear interrupt
|
||||
// careful, this can also be cleared by requesting a transmission
|
||||
CAN->TSR |= CAN_TSR_RQCP0; |
||||
} |
||||
|
||||
if (can_pop(can_queues[bus_number], &to_send)) { |
||||
can_tx_cnt += 1; |
||||
// only send if we have received a packet
|
||||
CAN->sTxMailBox[0].TDLR = to_send.RDLR; |
||||
CAN->sTxMailBox[0].TDHR = to_send.RDHR; |
||||
CAN->sTxMailBox[0].TDTR = to_send.RDTR; |
||||
CAN->sTxMailBox[0].TIR = to_send.RIR; |
||||
} |
||||
} |
||||
|
||||
exit_critical_section(); |
||||
} |
||||
|
||||
// CAN receive handlers
|
||||
// blink blue when we are receiving CAN messages
|
||||
void can_rx(uint8_t can_number) { |
||||
CAN_TypeDef *CAN = CANIF_FROM_CAN_NUM(can_number); |
||||
uint8_t bus_number = BUS_NUM_FROM_CAN_NUM(can_number); |
||||
while (CAN->RF0R & CAN_RF0R_FMP0) { |
||||
can_rx_cnt += 1; |
||||
|
||||
// can is live
|
||||
pending_can_live = 1; |
||||
|
||||
// add to my fifo
|
||||
CAN_FIFOMailBox_TypeDef to_push; |
||||
to_push.RIR = CAN->sFIFOMailBox[0].RIR; |
||||
to_push.RDTR = CAN->sFIFOMailBox[0].RDTR; |
||||
to_push.RDLR = CAN->sFIFOMailBox[0].RDLR; |
||||
to_push.RDHR = CAN->sFIFOMailBox[0].RDHR; |
||||
|
||||
// forwarding (panda only)
|
||||
#ifdef PANDA |
||||
if (can_forwarding[bus_number] != -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; |
||||
can_send(&to_send, can_forwarding[bus_number]); |
||||
} |
||||
#endif |
||||
|
||||
// modify RDTR for our API
|
||||
to_push.RDTR = (to_push.RDTR & 0xFFFF000F) | (bus_number << 4); |
||||
safety_rx_hook(&to_push); |
||||
|
||||
#ifdef PANDA |
||||
set_led(LED_BLUE, 1); |
||||
#endif |
||||
can_push(&can_rx_q, &to_push); |
||||
|
||||
// next
|
||||
CAN->RF0R |= CAN_RF0R_RFOM0; |
||||
} |
||||
} |
||||
|
||||
void CAN1_TX_IRQHandler() { process_can(0); } |
||||
void CAN1_RX0_IRQHandler() { can_rx(0); } |
||||
void CAN1_SCE_IRQHandler() { can_sce(CAN1); } |
||||
|
||||
void CAN2_TX_IRQHandler() { process_can(1); } |
||||
void CAN2_RX0_IRQHandler() { can_rx(1); } |
||||
void CAN2_SCE_IRQHandler() { can_sce(CAN2); } |
||||
|
||||
#ifdef CAN3 |
||||
void CAN3_TX_IRQHandler() { process_can(2); } |
||||
void CAN3_RX0_IRQHandler() { can_rx(2); } |
||||
void CAN3_SCE_IRQHandler() { can_sce(CAN3); } |
||||
#endif |
||||
|
||||
void can_send(CAN_FIFOMailBox_TypeDef *to_push, uint8_t bus_number) { |
||||
if (safety_tx_hook(to_push)) { |
||||
if (bus_number < BUS_MAX) { |
||||
// add CAN packet to send queue
|
||||
// bus number isn't passed through
|
||||
to_push->RDTR &= 0xF; |
||||
can_push(can_queues[bus_number], to_push); |
||||
process_can(CAN_NUM_FROM_BUS_NUM(bus_number)); |
||||
} |
||||
} |
||||
} |
||||
|
||||
void can_set_forwarding(int from, int to) { |
||||
can_forwarding[from] = to; |
||||
} |
@ -0,0 +1,16 @@ |
||||
void dac_init() { |
||||
// no buffers required since we have an opamp
|
||||
//DAC->CR = DAC_CR_EN1 | DAC_CR_BOFF1 | DAC_CR_EN2 | DAC_CR_BOFF2;
|
||||
DAC->DHR12R1 = 0; |
||||
DAC->DHR12R2 = 0; |
||||
DAC->CR = DAC_CR_EN1 | DAC_CR_EN2; |
||||
} |
||||
|
||||
void dac_set(int channel, uint32_t value) { |
||||
if (channel == 0) { |
||||
DAC->DHR12R1 = value; |
||||
} else if (channel == 1) { |
||||
DAC->DHR12R2 = value; |
||||
} |
||||
} |
||||
|
@ -0,0 +1,141 @@ |
||||
#ifndef PANDA_DRIVERS_H |
||||
#define PANDA_DRIVERS_H |
||||
|
||||
// ********************* LLGPIO *********************
|
||||
|
||||
#define MODE_INPUT 0 |
||||
#define MODE_OUTPUT 1 |
||||
#define MODE_ALTERNATE 2 |
||||
#define MODE_ANALOG 3 |
||||
|
||||
#define PULL_NONE 0 |
||||
#define PULL_UP 1 |
||||
#define PULL_DOWN 2 |
||||
|
||||
void set_gpio_mode(GPIO_TypeDef *GPIO, int pin, int mode); |
||||
void set_gpio_output(GPIO_TypeDef *GPIO, int pin, int val); |
||||
void set_gpio_alternate(GPIO_TypeDef *GPIO, int pin, int mode); |
||||
void set_gpio_pullup(GPIO_TypeDef *GPIO, int pin, int mode); |
||||
|
||||
int get_gpio_input(GPIO_TypeDef *GPIO, int pin); |
||||
|
||||
|
||||
// ********************* USB *********************
|
||||
// IRQs: OTG_FS
|
||||
|
||||
typedef union { |
||||
uint16_t w; |
||||
struct BW { |
||||
uint8_t msb; |
||||
uint8_t lsb; |
||||
} |
||||
bw; |
||||
} |
||||
uint16_t_uint8_t; |
||||
|
||||
typedef union _USB_Setup { |
||||
uint32_t d8[2]; |
||||
struct _SetupPkt_Struc |
||||
{ |
||||
uint8_t bmRequestType; |
||||
uint8_t bRequest; |
||||
uint16_t_uint8_t wValue; |
||||
uint16_t_uint8_t wIndex; |
||||
uint16_t_uint8_t wLength; |
||||
} b; |
||||
} |
||||
USB_Setup_TypeDef; |
||||
|
||||
void usb_init(); |
||||
int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, 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); |
||||
void usb_cb_enumeration_complete(); |
||||
|
||||
|
||||
// ********************* UART *********************
|
||||
// IRQs: USART1, USART2, USART3, UART5
|
||||
|
||||
#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; |
||||
|
||||
void uart_init(USART_TypeDef *u, int baud); |
||||
|
||||
int getc(uart_ring *q, char *elem); |
||||
int putc(uart_ring *q, char elem); |
||||
|
||||
int puts(const char *a); |
||||
void puth(unsigned int i); |
||||
void hexdump(const void *a, int l); |
||||
|
||||
|
||||
// ********************* ADC *********************
|
||||
|
||||
void adc_init(); |
||||
uint32_t adc_get(int channel); |
||||
|
||||
|
||||
// ********************* DAC *********************
|
||||
|
||||
void dac_init(); |
||||
uint32_t dac_set(int channel, uint32_t value); |
||||
|
||||
|
||||
// ********************* TIMER *********************
|
||||
|
||||
void timer_init(TIM_TypeDef *TIM, int psc); |
||||
|
||||
|
||||
// ********************* SPI *********************
|
||||
// IRQs: DMA2_Stream2, DMA2_Stream3, EXTI4
|
||||
|
||||
void spi_init(); |
||||
int spi_cb_rx(uint8_t *data, int len, uint8_t *data_out); |
||||
|
||||
|
||||
// ********************* CAN *********************
|
||||
// IRQs: CAN1_TX, CAN1_RX0, CAN1_SCE
|
||||
// CAN2_TX, CAN2_RX0, CAN2_SCE
|
||||
// CAN3_TX, CAN3_RX0, CAN3_SCE
|
||||
|
||||
typedef struct { |
||||
uint32_t w_ptr; |
||||
uint32_t r_ptr; |
||||
uint32_t fifo_size; |
||||
CAN_FIFOMailBox_TypeDef *elems; |
||||
} can_ring; |
||||
|
||||
#define CAN_BUS_RET_FLAG 0x80 |
||||
#define CAN_BUS_NUM_MASK 0x7F |
||||
|
||||
#ifdef PANDA |
||||
#define BUS_MAX 4 |
||||
#else |
||||
#define BUS_MAX 2 |
||||
#endif |
||||
|
||||
extern int can_live, pending_can_live; |
||||
|
||||
// must reinit after changing these
|
||||
extern int can_loopback, can_silent; |
||||
extern uint32_t can_speed[]; |
||||
|
||||
void can_set_forwarding(int from, int to); |
||||
|
||||
void can_init(uint8_t can_number); |
||||
void can_init_all(); |
||||
void can_send(CAN_FIFOMailBox_TypeDef *to_push, uint8_t bus_number); |
||||
int can_pop(can_ring *q, CAN_FIFOMailBox_TypeDef *elem); |
||||
|
||||
#endif |
||||
|
@ -0,0 +1,35 @@ |
||||
void set_gpio_mode(GPIO_TypeDef *GPIO, int pin, int mode) { |
||||
uint32_t tmp = GPIO->MODER; |
||||
tmp &= ~(3 << (pin*2)); |
||||
tmp |= (mode << (pin*2)); |
||||
GPIO->MODER = tmp; |
||||
} |
||||
|
||||
void set_gpio_output(GPIO_TypeDef *GPIO, int pin, int val) { |
||||
if (val) { |
||||
GPIO->ODR |= (1 << pin); |
||||
} else { |
||||
GPIO->ODR &= ~(1 << pin); |
||||
} |
||||
set_gpio_mode(GPIO, pin, MODE_OUTPUT); |
||||
} |
||||
|
||||
void set_gpio_alternate(GPIO_TypeDef *GPIO, int pin, int mode) { |
||||
uint32_t tmp = GPIO->AFR[pin>>3]; |
||||
tmp &= ~(0xF << ((pin&7)*4)); |
||||
tmp |= mode << ((pin&7)*4); |
||||
GPIO->AFR[pin>>3] = tmp; |
||||
set_gpio_mode(GPIO, pin, MODE_ALTERNATE); |
||||
} |
||||
|
||||
void set_gpio_pullup(GPIO_TypeDef *GPIO, int pin, int mode) { |
||||
uint32_t tmp = GPIO->PUPDR; |
||||
tmp &= ~(3 << (pin*2)); |
||||
tmp |= (mode << (pin*2)); |
||||
GPIO->PUPDR = tmp; |
||||
} |
||||
|
||||
int get_gpio_input(GPIO_TypeDef *GPIO, int pin) { |
||||
return (GPIO->IDR & (1 << pin)) == (1 << pin); |
||||
} |
||||
|
@ -0,0 +1,120 @@ |
||||
// IRQs: DMA2_Stream2, DMA2_Stream3, EXTI4
|
||||
|
||||
#define SPI_BUF_SIZE 256 |
||||
uint8_t spi_buf[SPI_BUF_SIZE]; |
||||
int spi_buf_count = 0; |
||||
int spi_total_count = 0; |
||||
|
||||
void spi_init() { |
||||
//puts("SPI init\n");
|
||||
SPI1->CR1 = SPI_CR1_SPE; |
||||
|
||||
// enable SPI interrupts
|
||||
//SPI1->CR2 = SPI_CR2_RXNEIE | SPI_CR2_ERRIE | SPI_CR2_TXEIE;
|
||||
SPI1->CR2 = SPI_CR2_RXNEIE; |
||||
|
||||
NVIC_EnableIRQ(DMA2_Stream2_IRQn); |
||||
NVIC_EnableIRQ(DMA2_Stream3_IRQn); |
||||
//NVIC_EnableIRQ(SPI1_IRQn);
|
||||
|
||||
// reset handshake back to pull up
|
||||
set_gpio_mode(GPIOB, 0, MODE_INPUT); |
||||
set_gpio_pullup(GPIOB, 0, PULL_UP); |
||||
|
||||
// setup interrupt on falling edge of SPI enable (on PA4)
|
||||
SYSCFG->EXTICR[2] = SYSCFG_EXTICR2_EXTI4_PA; |
||||
EXTI->IMR = (1 << 4); |
||||
EXTI->FTSR = (1 << 4); |
||||
NVIC_EnableIRQ(EXTI4_IRQn); |
||||
} |
||||
|
||||
void spi_tx_dma(void *addr, int len) { |
||||
// disable DMA
|
||||
SPI1->CR2 &= ~SPI_CR2_TXDMAEN; |
||||
DMA2_Stream3->CR &= ~DMA_SxCR_EN; |
||||
|
||||
// DMA2, stream 3, channel 3
|
||||
DMA2_Stream3->M0AR = (uint32_t)addr; |
||||
DMA2_Stream3->NDTR = len; |
||||
DMA2_Stream3->PAR = (uint32_t)&(SPI1->DR); |
||||
|
||||
// channel3, increment memory, memory -> periph, enable
|
||||
DMA2_Stream3->CR = DMA_SxCR_CHSEL_1 | DMA_SxCR_CHSEL_0 | DMA_SxCR_MINC | DMA_SxCR_DIR_0 | DMA_SxCR_EN; |
||||
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
|
||||
set_gpio_output(GPIOB, 0, 0); |
||||
} |
||||
|
||||
void spi_rx_dma(void *addr, int len) { |
||||
// disable DMA
|
||||
SPI1->CR2 &= ~SPI_CR2_RXDMAEN; |
||||
DMA2_Stream2->CR &= ~DMA_SxCR_EN; |
||||
|
||||
// drain the bus
|
||||
volatile uint8_t dat = SPI1->DR; |
||||
(void)dat; |
||||
|
||||
// DMA2, stream 2, channel 3
|
||||
DMA2_Stream2->M0AR = (uint32_t)addr; |
||||
DMA2_Stream2->NDTR = len; |
||||
DMA2_Stream2->PAR = (uint32_t)&(SPI1->DR); |
||||
|
||||
// channel3, increment memory, periph -> memory, enable
|
||||
DMA2_Stream2->CR = DMA_SxCR_CHSEL_1 | DMA_SxCR_CHSEL_0 | DMA_SxCR_MINC | DMA_SxCR_EN; |
||||
DMA2_Stream2->CR |= DMA_SxCR_TCIE; |
||||
|
||||
SPI1->CR2 |= SPI_CR2_RXDMAEN; |
||||
} |
||||
|
||||
// ***************************** 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) { |
||||
int *resp_len = (int*)spi_tx_buf; |
||||
memset(spi_tx_buf, 0xaa, 0x44); |
||||
*resp_len = spi_cb_rx(spi_buf, 0x14, 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); |
||||
|
||||
// ack
|
||||
DMA2->LIFCR = DMA_LIFCR_CTCIF2; |
||||
} |
||||
|
||||
// SPI TX
|
||||
void DMA2_Stream3_IRQHandler(void) { |
||||
#ifdef DEBUG_SPI |
||||
puts("SPI handshake\n"); |
||||
#endif |
||||
|
||||
// reset handshake back to pull up
|
||||
set_gpio_mode(GPIOB, 0, MODE_INPUT); |
||||
set_gpio_pullup(GPIOB, 0, PULL_UP); |
||||
|
||||
// ack
|
||||
DMA2->LIFCR = DMA_LIFCR_CTCIF3; |
||||
} |
||||
|
||||
void EXTI4_IRQHandler(void) { |
||||
volatile int pr = EXTI->PR; |
||||
#ifdef DEBUG_SPI |
||||
puts("exti4\n"); |
||||
#endif |
||||
// SPI CS falling
|
||||
if (pr & (1 << 4)) { |
||||
spi_total_count = 0; |
||||
spi_rx_dma(spi_buf, 0x14); |
||||
} |
||||
EXTI->PR = pr; |
||||
} |
||||
|
@ -0,0 +1,7 @@ |
||||
void timer_init(TIM_TypeDef *TIM, int psc) { |
||||
TIM->PSC = psc-1; |
||||
TIM->DIER = TIM_DIER_UIE; |
||||
TIM->CR1 = TIM_CR1_CEN; |
||||
TIM->SR = 0; |
||||
} |
||||
|
@ -0,0 +1,224 @@ |
||||
// IRQs: USART1, USART2, USART3, UART5
|
||||
|
||||
// ***************************** serial port queues *****************************
|
||||
|
||||
// esp = USART1
|
||||
uart_ring esp_ring = { .w_ptr_tx = 0, .r_ptr_tx = 0, |
||||
.w_ptr_rx = 0, .r_ptr_rx = 0, |
||||
.uart = USART1 }; |
||||
|
||||
// lin1, K-LINE = UART5
|
||||
// lin2, L-LINE = USART3
|
||||
uart_ring lin1_ring = { .w_ptr_tx = 0, .r_ptr_tx = 0, |
||||
.w_ptr_rx = 0, .r_ptr_rx = 0, |
||||
.uart = UART5 }; |
||||
uart_ring lin2_ring = { .w_ptr_tx = 0, .r_ptr_tx = 0, |
||||
.w_ptr_rx = 0, .r_ptr_rx = 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) { |
||||
case 0: |
||||
return &debug_ring; |
||||
case 1: |
||||
return &esp_ring; |
||||
case 2: |
||||
return &lin1_ring; |
||||
case 3: |
||||
return &lin2_ring; |
||||
default: |
||||
return NULL; |
||||
} |
||||
} |
||||
|
||||
// ***************************** serial port *****************************
|
||||
|
||||
void uart_ring_process(uart_ring *q) { |
||||
enter_critical_section(); |
||||
// 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); |
||||
} |
||||
} |
||||
exit_critical_section(); |
||||
} |
||||
|
||||
// interrupt boilerplate
|
||||
|
||||
void USART1_IRQHandler(void) { uart_ring_process(&esp_ring); } |
||||
void USART2_IRQHandler(void) { uart_ring_process(&debug_ring); } |
||||
void USART3_IRQHandler(void) { uart_ring_process(&lin2_ring); } |
||||
void UART5_IRQHandler(void) { uart_ring_process(&lin1_ring); } |
||||
|
||||
int getc(uart_ring *q, char *elem) { |
||||
int ret = 0; |
||||
|
||||
enter_critical_section(); |
||||
if (q->w_ptr_rx != q->r_ptr_rx) { |
||||
*elem = q->elems_rx[q->r_ptr_rx]; |
||||
q->r_ptr_rx += 1; |
||||
ret = 1; |
||||
} |
||||
exit_critical_section(); |
||||
|
||||
return ret; |
||||
} |
||||
|
||||
int injectc(uart_ring *q, char elem) { |
||||
int ret = 0; |
||||
uint8_t next_w_ptr; |
||||
|
||||
enter_critical_section(); |
||||
next_w_ptr = q->w_ptr_rx + 1; |
||||
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; |
||||
} |
||||
exit_critical_section(); |
||||
|
||||
return ret; |
||||
} |
||||
|
||||
int putc(uart_ring *q, char elem) { |
||||
int ret = 0; |
||||
uint8_t next_w_ptr; |
||||
|
||||
enter_critical_section(); |
||||
next_w_ptr = q->w_ptr_tx + 1; |
||||
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; |
||||
} |
||||
exit_critical_section(); |
||||
|
||||
uart_ring_process(q); |
||||
|
||||
return ret; |
||||
} |
||||
|
||||
void clear_uart_buff(uart_ring *q) { |
||||
enter_critical_section(); |
||||
q->w_ptr_tx = 0; |
||||
q->r_ptr_tx = 0; |
||||
q->w_ptr_rx = 0; |
||||
q->r_ptr_rx = 0; |
||||
exit_critical_section(); |
||||
} |
||||
|
||||
// ***************************** start UART code *****************************
|
||||
|
||||
#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_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; |
||||
|
||||
if (u == USART1) { |
||||
NVIC_EnableIRQ(USART1_IRQn); |
||||
} else if (u == USART2) { |
||||
NVIC_EnableIRQ(USART2_IRQn); |
||||
} else if (u == USART3) { |
||||
NVIC_EnableIRQ(USART3_IRQn); |
||||
} else if (u == UART5) { |
||||
NVIC_EnableIRQ(UART5_IRQn); |
||||
} |
||||
} |
||||
|
||||
void putch(const char a) { |
||||
if (has_external_debug_serial) { |
||||
/*while ((debug_ring.uart->SR & USART_SR_TXE) == 0);
|
||||
debug_ring.uart->DR = a;*/ |
||||
|
||||
// assuming debugging is important if there's external serial connected
|
||||
while (!putc(&debug_ring, a)); |
||||
|
||||
//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(const void *a, int l) { |
||||
int i; |
||||
for (i=0;i<l;i++) { |
||||
if (i != 0 && (i&0xf) == 0) puts("\n"); |
||||
puth2(((const unsigned char*)a)[i]); |
||||
puts(" "); |
||||
} |
||||
puts("\n"); |
||||
} |
@ -0,0 +1,705 @@ |
||||
// IRQs: OTG_FS
|
||||
|
||||
// **** supporting defines ****
|
||||
|
||||
typedef struct |
||||
{ |
||||
__IO uint32_t HPRT; |
||||
} |
||||
USB_OTG_HostPortTypeDef; |
||||
|
||||
USB_OTG_GlobalTypeDef *USBx = USB_OTG_FS; |
||||
|
||||
#define USBx_HOST ((USB_OTG_HostTypeDef *)((uint32_t)USBx + USB_OTG_HOST_BASE)) |
||||
#define USBx_HOST_PORT ((USB_OTG_HostPortTypeDef *)((uint32_t)USBx + USB_OTG_HOST_PORT_BASE)) |
||||
#define USBx_DEVICE ((USB_OTG_DeviceTypeDef *)((uint32_t)USBx + USB_OTG_DEVICE_BASE)) |
||||
#define USBx_INEP(i) ((USB_OTG_INEndpointTypeDef *)((uint32_t)USBx + USB_OTG_IN_ENDPOINT_BASE + (i)*USB_OTG_EP_REG_SIZE)) |
||||
#define USBx_OUTEP(i) ((USB_OTG_OUTEndpointTypeDef *)((uint32_t)USBx + USB_OTG_OUT_ENDPOINT_BASE + (i)*USB_OTG_EP_REG_SIZE)) |
||||
#define USBx_DFIFO(i) *(__IO uint32_t *)((uint32_t)USBx + USB_OTG_FIFO_BASE + (i) * USB_OTG_FIFO_SIZE) |
||||
#define USBx_PCGCCTL *(__IO uint32_t *)((uint32_t)USBx + USB_OTG_PCGCCTL_BASE) |
||||
|
||||
#define USB_REQ_GET_STATUS 0x00 |
||||
#define USB_REQ_CLEAR_FEATURE 0x01 |
||||
#define USB_REQ_SET_FEATURE 0x03 |
||||
#define USB_REQ_SET_ADDRESS 0x05 |
||||
#define USB_REQ_GET_DESCRIPTOR 0x06 |
||||
#define USB_REQ_SET_DESCRIPTOR 0x07 |
||||
#define USB_REQ_GET_CONFIGURATION 0x08 |
||||
#define USB_REQ_SET_CONFIGURATION 0x09 |
||||
#define USB_REQ_GET_INTERFACE 0x0A |
||||
#define USB_REQ_SET_INTERFACE 0x0B |
||||
#define USB_REQ_SYNCH_FRAME 0x0C |
||||
|
||||
#define USB_DESC_TYPE_DEVICE 1 |
||||
#define USB_DESC_TYPE_CONFIGURATION 2 |
||||
#define USB_DESC_TYPE_STRING 3 |
||||
#define USB_DESC_TYPE_INTERFACE 4 |
||||
#define USB_DESC_TYPE_ENDPOINT 5 |
||||
#define USB_DESC_TYPE_DEVICE_QUALIFIER 6 |
||||
#define USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION 7 |
||||
|
||||
#define STS_GOUT_NAK 1 |
||||
#define STS_DATA_UPDT 2 |
||||
#define STS_XFER_COMP 3 |
||||
#define STS_SETUP_COMP 4 |
||||
#define STS_SETUP_UPDT 6 |
||||
|
||||
#define USBD_FS_TRDT_VALUE 5 |
||||
|
||||
#define USB_OTG_SPEED_FULL 3 |
||||
|
||||
uint8_t resp[MAX_RESP_LEN]; |
||||
|
||||
// descriptor types
|
||||
// same as setupdat.h
|
||||
#define DSCR_DEVICE_TYPE 1 |
||||
#define DSCR_CONFIG_TYPE 2 |
||||
#define DSCR_STRING_TYPE 3 |
||||
#define DSCR_INTERFACE_TYPE 4 |
||||
#define DSCR_ENDPOINT_TYPE 5 |
||||
#define DSCR_DEVQUAL_TYPE 6 |
||||
|
||||
// for the repeating interfaces
|
||||
#define DSCR_INTERFACE_LEN 9 |
||||
#define DSCR_ENDPOINT_LEN 7 |
||||
#define DSCR_CONFIG_LEN 9 |
||||
#define DSCR_DEVICE_LEN 18 |
||||
|
||||
// endpoint types
|
||||
#define ENDPOINT_TYPE_CONTROL 0 |
||||
#define ENDPOINT_TYPE_ISO 1 |
||||
#define ENDPOINT_TYPE_BULK 2 |
||||
#define ENDPOINT_TYPE_INT 3 |
||||
|
||||
//Convert machine byte order to USB byte order
|
||||
#define TOUSBORDER(num)\ |
||||
(num&0xFF), ((num>>8)&0xFF) |
||||
|
||||
uint8_t device_desc[] = { |
||||
DSCR_DEVICE_LEN, DSCR_DEVICE_TYPE, 0x00, 0x01, //Length, Type, bcdUSB
|
||||
0xFF, 0xFF, 0xFF, 0x40, // Class, Subclass, Protocol, Max Packet Size
|
||||
TOUSBORDER(USB_VID), // idVendor
|
||||
TOUSBORDER(USB_PID), // idProduct
|
||||
#ifdef STM32F4 |
||||
0x00, 0x23, // bcdDevice
|
||||
#else |
||||
0x00, 0x22, // bcdDevice
|
||||
#endif |
||||
0x01, 0x02, // Manufacturer, Product
|
||||
0x03, 0x01 // Serial Number, Num Configurations
|
||||
}; |
||||
|
||||
#define ENDPOINT_RCV 0x80 |
||||
#define ENDPOINT_SND 0x00 |
||||
|
||||
uint8_t configuration_desc[] = { |
||||
DSCR_CONFIG_LEN, DSCR_CONFIG_TYPE, // Length, Type,
|
||||
TOUSBORDER(0x0045), // Total Len (uint16)
|
||||
0x01, 0x01, 0x00, // Num Interface, Config Value, Configuration
|
||||
0xc0, 0x32, // Attributes, Max Power
|
||||
// interface 0 ALT 0
|
||||
DSCR_INTERFACE_LEN, DSCR_INTERFACE_TYPE, // Length, Type
|
||||
0x00, 0x00, 0x03, // Index, Alt Index idx, Endpoint count
|
||||
0XFF, 0xFF, 0xFF, // Class, Subclass, Protocol
|
||||
0x00, // Interface
|
||||
// endpoint 1, read CAN
|
||||
DSCR_ENDPOINT_LEN, DSCR_ENDPOINT_TYPE, // Length, Type
|
||||
ENDPOINT_RCV | 1, ENDPOINT_TYPE_BULK, // Endpoint Num/Direction, Type
|
||||
TOUSBORDER(0x0040), // Max Packet (0x0040)
|
||||
0x00, // Polling Interval (NA)
|
||||
// endpoint 2, send serial
|
||||
DSCR_ENDPOINT_LEN, DSCR_ENDPOINT_TYPE, // Length, Type
|
||||
ENDPOINT_SND | 2, ENDPOINT_TYPE_BULK, // Endpoint Num/Direction, Type
|
||||
TOUSBORDER(0x0040), // Max Packet (0x0040)
|
||||
0x00, // Polling Interval
|
||||
// endpoint 3, send CAN
|
||||
DSCR_ENDPOINT_LEN, DSCR_ENDPOINT_TYPE, // Length, Type
|
||||
ENDPOINT_SND | 3, ENDPOINT_TYPE_BULK, // Endpoint Num/Direction, Type
|
||||
TOUSBORDER(0x0040), // Max Packet (0x0040)
|
||||
0x00, // Polling Interval
|
||||
// interface 0 ALT 1
|
||||
DSCR_INTERFACE_LEN, DSCR_INTERFACE_TYPE, // Length, Type
|
||||
0x00, 0x01, 0x03, // Index, Alt Index idx, Endpoint count
|
||||
0XFF, 0xFF, 0xFF, // Class, Subclass, Protocol
|
||||
0x00, // Interface
|
||||
// endpoint 1, read CAN
|
||||
DSCR_ENDPOINT_LEN, DSCR_ENDPOINT_TYPE, // Length, Type
|
||||
ENDPOINT_RCV | 1, ENDPOINT_TYPE_INT, // Endpoint Num/Direction, Type
|
||||
TOUSBORDER(0x0040), // Max Packet (0x0040)
|
||||
0x05, // Polling Interval (5 frames)
|
||||
// endpoint 2, send serial
|
||||
DSCR_ENDPOINT_LEN, DSCR_ENDPOINT_TYPE, // Length, Type
|
||||
ENDPOINT_SND | 2, ENDPOINT_TYPE_BULK, // Endpoint Num/Direction, Type
|
||||
TOUSBORDER(0x0040), // Max Packet (0x0040)
|
||||
0x00, // Polling Interval
|
||||
// endpoint 3, send CAN
|
||||
DSCR_ENDPOINT_LEN, DSCR_ENDPOINT_TYPE, // Length, Type
|
||||
ENDPOINT_SND | 3, ENDPOINT_TYPE_BULK, // Endpoint Num/Direction, Type
|
||||
TOUSBORDER(0x0040), // Max Packet (0x0040)
|
||||
0x00, // Polling Interval
|
||||
}; |
||||
|
||||
uint8_t string_0_desc[] = { |
||||
0x04, DSCR_STRING_TYPE, 0x09, 0x04 |
||||
}; |
||||
|
||||
uint16_t string_1_desc[] = { |
||||
0x0312, |
||||
'c', 'o', 'm', 'm', 'a', '.', 'a', 'i' |
||||
}; |
||||
|
||||
#ifdef PANDA |
||||
uint16_t string_2_desc[] = { |
||||
0x030c, |
||||
'p', 'a', 'n', 'd', 'a' |
||||
}; |
||||
#else |
||||
uint16_t string_2_desc[] = { |
||||
0x030c, |
||||
'N', 'E', 'O', 'v', '1' |
||||
}; |
||||
#endif |
||||
|
||||
uint16_t string_3_desc[] = { |
||||
0x030a, |
||||
'n', 'o', 'n', 'e' |
||||
}; |
||||
|
||||
// current packet
|
||||
USB_Setup_TypeDef setup; |
||||
uint8_t usbdata[0x100]; |
||||
|
||||
// Store the current interface alt setting.
|
||||
int current_int0_alt_setting = 0; |
||||
|
||||
// packet read and write
|
||||
|
||||
void *USB_ReadPacket(void *dest, uint16_t len) { |
||||
uint32_t i=0; |
||||
uint32_t count32b = (len + 3) / 4; |
||||
|
||||
for ( i = 0; i < count32b; i++, dest += 4 ) { |
||||
// packed?
|
||||
*(__attribute__((__packed__)) uint32_t *)dest = USBx_DFIFO(0); |
||||
} |
||||
return ((void *)dest); |
||||
} |
||||
|
||||
void USB_WritePacket(const uint8_t *src, uint16_t len, uint32_t ep) { |
||||
#ifdef DEBUG_USB |
||||
puts("writing "); |
||||
hexdump(src, len); |
||||
#endif |
||||
|
||||
uint8_t numpacket = (len+(MAX_RESP_LEN-1))/MAX_RESP_LEN; |
||||
uint32_t count32b = 0, i = 0; |
||||
count32b = (len + 3) / 4; |
||||
|
||||
// bullshit
|
||||
USBx_INEP(ep)->DIEPTSIZ = ((numpacket << 19) & USB_OTG_DIEPTSIZ_PKTCNT) | |
||||
(len & USB_OTG_DIEPTSIZ_XFRSIZ); |
||||
USBx_INEP(ep)->DIEPCTL |= (USB_OTG_DIEPCTL_CNAK | USB_OTG_DIEPCTL_EPENA); |
||||
|
||||
// load the FIFO
|
||||
for (i = 0; i < count32b; i++, src += 4) { |
||||
USBx_DFIFO(ep) = *((__attribute__((__packed__)) uint32_t *)src); |
||||
} |
||||
} |
||||
|
||||
void usb_reset() { |
||||
// unmask endpoint interrupts, so many sets
|
||||
USBx_DEVICE->DAINT = 0xFFFFFFFF; |
||||
USBx_DEVICE->DAINTMSK = 0xFFFFFFFF; |
||||
//USBx_DEVICE->DOEPMSK = (USB_OTG_DOEPMSK_STUPM | USB_OTG_DOEPMSK_XFRCM | USB_OTG_DOEPMSK_EPDM);
|
||||
//USBx_DEVICE->DIEPMSK = (USB_OTG_DIEPMSK_TOM | USB_OTG_DIEPMSK_XFRCM | USB_OTG_DIEPMSK_EPDM | USB_OTG_DIEPMSK_ITTXFEMSK);
|
||||
//USBx_DEVICE->DIEPMSK = (USB_OTG_DIEPMSK_TOM | USB_OTG_DIEPMSK_XFRCM | USB_OTG_DIEPMSK_EPDM);
|
||||
|
||||
// all interrupts for debugging
|
||||
USBx_DEVICE->DIEPMSK = 0xFFFFFFFF; |
||||
USBx_DEVICE->DOEPMSK = 0xFFFFFFFF; |
||||
|
||||
// clear interrupts
|
||||
USBx_INEP(0)->DIEPINT = 0xFF; |
||||
USBx_OUTEP(0)->DOEPINT = 0xFF; |
||||
|
||||
// unset the address
|
||||
USBx_DEVICE->DCFG &= ~USB_OTG_DCFG_DAD; |
||||
|
||||
// set up USB FIFOs
|
||||
// RX start address is fixed to 0
|
||||
USBx->GRXFSIZ = 0x40; |
||||
|
||||
// 0x100 to offset past GRXFSIZ
|
||||
USBx->DIEPTXF0_HNPTXFSIZ = (0x40 << 16) | 0x40; |
||||
|
||||
// EP1, massive
|
||||
USBx->DIEPTXF[0] = (0x40 << 16) | 0x80; |
||||
|
||||
// flush TX fifo
|
||||
USBx->GRSTCTL = USB_OTG_GRSTCTL_TXFFLSH | USB_OTG_GRSTCTL_TXFNUM_4; |
||||
while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_TXFFLSH) == USB_OTG_GRSTCTL_TXFFLSH); |
||||
// flush RX FIFO
|
||||
USBx->GRSTCTL = USB_OTG_GRSTCTL_RXFFLSH; |
||||
while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_RXFFLSH) == USB_OTG_GRSTCTL_RXFFLSH); |
||||
|
||||
// no global NAK
|
||||
USBx_DEVICE->DCTL |= USB_OTG_DCTL_CGINAK; |
||||
|
||||
// ready to receive setup packets
|
||||
USBx_OUTEP(0)->DOEPTSIZ = USB_OTG_DOEPTSIZ_STUPCNT | (USB_OTG_DOEPTSIZ_PKTCNT & (1 << 19)) | (3 * 8); |
||||
} |
||||
|
||||
char to_hex_char(int a) { |
||||
if (a < 10) { |
||||
return '0' + a; |
||||
} else { |
||||
return 'a' + (a-10); |
||||
} |
||||
} |
||||
|
||||
void usb_setup() { |
||||
int resp_len; |
||||
// setup packet is ready
|
||||
switch (setup.b.bRequest) { |
||||
case USB_REQ_SET_CONFIGURATION: |
||||
// enable other endpoints, has to be here?
|
||||
USBx_INEP(1)->DIEPCTL = (0x40 & USB_OTG_DIEPCTL_MPSIZ) | (2 << 18) | (1 << 22) | |
||||
USB_OTG_DIEPCTL_SD0PID_SEVNFRM | USB_OTG_DIEPCTL_USBAEP; |
||||
USBx_INEP(1)->DIEPINT = 0xFF; |
||||
|
||||
USBx_OUTEP(2)->DOEPTSIZ = (1 << 19) | 0x40; |
||||
USBx_OUTEP(2)->DOEPCTL = (0x40 & USB_OTG_DOEPCTL_MPSIZ) | (2 << 18) | |
||||
USB_OTG_DOEPCTL_SD0PID_SEVNFRM | USB_OTG_DOEPCTL_USBAEP; |
||||
USBx_OUTEP(2)->DOEPINT = 0xFF; |
||||
|
||||
USBx_OUTEP(3)->DOEPTSIZ = (1 << 19) | 0x40; |
||||
USBx_OUTEP(3)->DOEPCTL = (0x40 & USB_OTG_DOEPCTL_MPSIZ) | (2 << 18) | |
||||
USB_OTG_DOEPCTL_SD0PID_SEVNFRM | USB_OTG_DOEPCTL_USBAEP; |
||||
USBx_OUTEP(3)->DOEPINT = 0xFF; |
||||
|
||||
// mark ready to receive
|
||||
USBx_OUTEP(2)->DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK; |
||||
USBx_OUTEP(3)->DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK; |
||||
|
||||
USB_WritePacket(0, 0, 0); |
||||
USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK; |
||||
break; |
||||
case USB_REQ_SET_ADDRESS: |
||||
// set now?
|
||||
USBx_DEVICE->DCFG |= ((setup.b.wValue.w & 0x7f) << 4); |
||||
|
||||
#ifdef DEBUG_USB |
||||
puts(" set address\n"); |
||||
#endif |
||||
|
||||
// TODO: this isn't enumeration complete
|
||||
// moved here to work better on OS X
|
||||
usb_cb_enumeration_complete(); |
||||
|
||||
USB_WritePacket(0, 0, 0); |
||||
USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK; |
||||
|
||||
break; |
||||
case USB_REQ_GET_DESCRIPTOR: |
||||
switch (setup.b.wValue.bw.lsb) { |
||||
case USB_DESC_TYPE_DEVICE: |
||||
//puts(" writing device descriptor\n");
|
||||
|
||||
// setup transfer
|
||||
USB_WritePacket(device_desc, min(sizeof(device_desc), setup.b.wLength.w), 0); |
||||
USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK; |
||||
|
||||
//puts("D");
|
||||
break; |
||||
case USB_DESC_TYPE_CONFIGURATION: |
||||
USB_WritePacket(configuration_desc, min(sizeof(configuration_desc), setup.b.wLength.w), 0); |
||||
USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK; |
||||
break; |
||||
case USB_DESC_TYPE_STRING: |
||||
switch (setup.b.wValue.bw.msb) { |
||||
case 0: |
||||
USB_WritePacket((uint8_t*)string_0_desc, min(sizeof(string_0_desc), setup.b.wLength.w), 0); |
||||
break; |
||||
case 1: |
||||
USB_WritePacket((uint8_t*)string_1_desc, min(sizeof(string_1_desc), setup.b.wLength.w), 0); |
||||
break; |
||||
case 2: |
||||
USB_WritePacket((uint8_t*)string_2_desc, min(sizeof(string_2_desc), setup.b.wLength.w), 0); |
||||
break; |
||||
case 3: |
||||
#ifdef PANDA |
||||
resp[0] = 0x02 + 12*4; |
||||
resp[1] = 0x03; |
||||
|
||||
// 96 bits = 12 bytes
|
||||
for (int i = 0; i < 12; i++){ |
||||
uint8_t cc = ((uint8_t *)UID_BASE)[i]; |
||||
resp[2 + i*4 + 0] = to_hex_char((cc>>4)&0xF); |
||||
resp[2 + i*4 + 1] = '\0'; |
||||
resp[2 + i*4 + 2] = to_hex_char((cc>>0)&0xF); |
||||
resp[2 + i*4 + 3] = '\0'; |
||||
} |
||||
|
||||
USB_WritePacket(resp, min(resp[0], setup.b.wLength.w), 0); |
||||
#else |
||||
USB_WritePacket((const uint8_t *)string_3_desc, min(sizeof(string_3_desc), setup.b.wLength.w), 0); |
||||
#endif |
||||
break; |
||||
default: |
||||
// nothing
|
||||
USB_WritePacket(0, 0, 0); |
||||
break; |
||||
} |
||||
USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK; |
||||
break; |
||||
default: |
||||
// nothing here?
|
||||
USB_WritePacket(0, 0, 0); |
||||
USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK; |
||||
break; |
||||
} |
||||
break; |
||||
case USB_REQ_GET_STATUS: |
||||
// empty resp?
|
||||
resp[0] = 0; |
||||
resp[1] = 0; |
||||
USB_WritePacket((void*)&resp, 2, 0); |
||||
USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK; |
||||
break; |
||||
case USB_REQ_SET_INTERFACE: |
||||
// Store the alt setting number for IN EP behavior.
|
||||
current_int0_alt_setting = setup.b.wValue.w; |
||||
USB_WritePacket(0, 0, 0); |
||||
USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK; |
||||
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; |
||||
} |
||||
} |
||||
|
||||
void usb_init() { |
||||
// full speed PHY, do reset and remove power down
|
||||
/*puth(USBx->GRSTCTL);
|
||||
puts(" resetting PHY\n");*/ |
||||
while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_AHBIDL) == 0); |
||||
//puts("AHB idle\n");
|
||||
|
||||
// reset PHY here
|
||||
USBx->GRSTCTL |= USB_OTG_GRSTCTL_CSRST; |
||||
while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_CSRST) == USB_OTG_GRSTCTL_CSRST); |
||||
//puts("reset done\n");
|
||||
|
||||
// internal PHY, force device mode
|
||||
USBx->GUSBCFG = USB_OTG_GUSBCFG_PHYSEL | USB_OTG_GUSBCFG_FDMOD; |
||||
|
||||
// slowest timings
|
||||
USBx->GUSBCFG |= (uint32_t)((USBD_FS_TRDT_VALUE << 10) & USB_OTG_GUSBCFG_TRDT); |
||||
|
||||
// power up the PHY
|
||||
#ifdef STM32F4 |
||||
USBx->GCCFG = USB_OTG_GCCFG_PWRDWN; |
||||
|
||||
//USBx->GCCFG |= USB_OTG_GCCFG_VBDEN | USB_OTG_GCCFG_SDEN |USB_OTG_GCCFG_PDEN | USB_OTG_GCCFG_DCDEN;
|
||||
|
||||
/* B-peripheral session valid override enable*/ |
||||
USBx->GOTGCTL |= USB_OTG_GOTGCTL_BVALOVAL; |
||||
USBx->GOTGCTL |= USB_OTG_GOTGCTL_BVALOEN; |
||||
#else |
||||
USBx->GCCFG = USB_OTG_GCCFG_PWRDWN | USB_OTG_GCCFG_NOVBUSSENS; |
||||
#endif |
||||
|
||||
// be a device, slowest timings
|
||||
//USBx->GUSBCFG = USB_OTG_GUSBCFG_FDMOD | USB_OTG_GUSBCFG_PHYSEL | USB_OTG_GUSBCFG_TRDT | USB_OTG_GUSBCFG_TOCAL;
|
||||
//USBx->GUSBCFG |= (uint32_t)((USBD_FS_TRDT_VALUE << 10) & USB_OTG_GUSBCFG_TRDT);
|
||||
//USBx->GUSBCFG = USB_OTG_GUSBCFG_PHYSEL | USB_OTG_GUSBCFG_TRDT | USB_OTG_GUSBCFG_TOCAL;
|
||||
|
||||
// **** for debugging, doesn't seem to work ****
|
||||
//USBx->GUSBCFG |= USB_OTG_GUSBCFG_CTXPKT;
|
||||
|
||||
// reset PHY clock
|
||||
USBx_PCGCCTL = 0; |
||||
|
||||
// enable the fancy OTG things
|
||||
// DCFG_FRAME_INTERVAL_80 is 0
|
||||
//USBx->GUSBCFG |= USB_OTG_GUSBCFG_HNPCAP | USB_OTG_GUSBCFG_SRPCAP;
|
||||
USBx_DEVICE->DCFG |= USB_OTG_SPEED_FULL | USB_OTG_DCFG_NZLSOHSK; |
||||
|
||||
//USBx_DEVICE->DCFG = USB_OTG_DCFG_NZLSOHSK | USB_OTG_DCFG_DSPD;
|
||||
//USBx_DEVICE->DCFG = USB_OTG_DCFG_DSPD;
|
||||
|
||||
// clear pending interrupts
|
||||
USBx->GINTSTS = 0xBFFFFFFFU; |
||||
|
||||
// setup USB interrupts
|
||||
// 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; |
||||
|
||||
USBx->GAHBCFG = USB_OTG_GAHBCFG_GINT; |
||||
|
||||
// DCTL startup value is 2 on new chip, 0 on old chip
|
||||
// THIS IS FUCKING BULLSHIT
|
||||
USBx_DEVICE->DCTL = 0; |
||||
|
||||
// enable the IRQ
|
||||
NVIC_EnableIRQ(OTG_FS_IRQn); |
||||
} |
||||
|
||||
// ***************************** USB port *****************************
|
||||
|
||||
void usb_irqhandler(void) { |
||||
//USBx->GINTMSK = 0;
|
||||
|
||||
unsigned int gintsts = USBx->GINTSTS; |
||||
unsigned int gotgint = USBx->GOTGINT; |
||||
unsigned int daint = USBx_DEVICE->DAINT; |
||||
|
||||
// gintsts SUSPEND? 04008428
|
||||
#ifdef DEBUG_USB |
||||
puth(gintsts); |
||||
puts(" "); |
||||
/*puth(USBx->GCCFG);
|
||||
puts(" ");*/ |
||||
puth(gotgint); |
||||
puts(" ep "); |
||||
puth(daint); |
||||
puts(" USB interrupt!\n"); |
||||
#endif |
||||
|
||||
if (gintsts & USB_OTG_GINTSTS_CIDSCHG) { |
||||
puts("connector ID status change\n"); |
||||
} |
||||
|
||||
if (gintsts & USB_OTG_GINTSTS_ESUSP) { |
||||
puts("ESUSP detected\n"); |
||||
} |
||||
|
||||
if (gintsts & USB_OTG_GINTSTS_USBRST) { |
||||
puts("USB reset\n"); |
||||
usb_reset(); |
||||
} |
||||
|
||||
if (gintsts & USB_OTG_GINTSTS_ENUMDNE) { |
||||
puts("enumeration done"); |
||||
// Full speed, ENUMSPD
|
||||
//puth(USBx_DEVICE->DSTS);
|
||||
puts("\n"); |
||||
} |
||||
|
||||
if (gintsts & USB_OTG_GINTSTS_OTGINT) { |
||||
puts("OTG int:"); |
||||
puth(USBx->GOTGINT); |
||||
puts("\n"); |
||||
|
||||
// getting ADTOCHG
|
||||
//USBx->GOTGINT = USBx->GOTGINT;
|
||||
} |
||||
|
||||
// RX FIFO first
|
||||
if (gintsts & USB_OTG_GINTSTS_RXFLVL) { |
||||
// 1. Read the Receive status pop register
|
||||
volatile unsigned int rxst = USBx->GRXSTSP; |
||||
|
||||
#ifdef DEBUG_USB |
||||
puts(" RX FIFO:"); |
||||
puth(rxst); |
||||
puts(" status: "); |
||||
puth((rxst & USB_OTG_GRXSTSP_PKTSTS) >> 17); |
||||
puts(" len: "); |
||||
puth((rxst & USB_OTG_GRXSTSP_BCNT) >> 4); |
||||
puts("\n"); |
||||
#endif |
||||
|
||||
if (((rxst & USB_OTG_GRXSTSP_PKTSTS) >> 17) == STS_DATA_UPDT) { |
||||
int endpoint = (rxst & USB_OTG_GRXSTSP_EPNUM); |
||||
int len = (rxst & USB_OTG_GRXSTSP_BCNT) >> 4; |
||||
USB_ReadPacket(&usbdata, len); |
||||
#ifdef DEBUG_USB |
||||
puts(" data "); |
||||
puth(len); |
||||
puts("\n"); |
||||
hexdump(&usbdata, len); |
||||
#endif |
||||
|
||||
if (endpoint == 2) { |
||||
usb_cb_ep2_out(usbdata, len, 1); |
||||
} |
||||
|
||||
if (endpoint == 3) { |
||||
usb_cb_ep3_out(usbdata, len, 1); |
||||
} |
||||
} else if (((rxst & USB_OTG_GRXSTSP_PKTSTS) >> 17) == STS_SETUP_UPDT) { |
||||
USB_ReadPacket(&setup, 8); |
||||
#ifdef DEBUG_USB |
||||
puts(" setup "); |
||||
hexdump(&setup, 8); |
||||
puts("\n"); |
||||
#endif |
||||
} |
||||
} |
||||
|
||||
/*if (gintsts & USB_OTG_GINTSTS_HPRTINT) {
|
||||
// host
|
||||
puts("HPRT:"); |
||||
puth(USBx_HOST_PORT->HPRT); |
||||
puts("\n"); |
||||
if (USBx_HOST_PORT->HPRT & USB_OTG_HPRT_PCDET) { |
||||
USBx_HOST_PORT->HPRT |= USB_OTG_HPRT_PRST; |
||||
USBx_HOST_PORT->HPRT |= USB_OTG_HPRT_PCDET; |
||||
} |
||||
|
||||
}*/ |
||||
|
||||
if ((gintsts & USB_OTG_GINTSTS_BOUTNAKEFF) || (gintsts & USB_OTG_GINTSTS_GINAKEFF)) { |
||||
// no global NAK, why is this getting set?
|
||||
#ifdef DEBUG_USB |
||||
puts("GLOBAL NAK\n"); |
||||
#endif |
||||
USBx_DEVICE->DCTL |= USB_OTG_DCTL_CGONAK | USB_OTG_DCTL_CGINAK; |
||||
} |
||||
|
||||
if (gintsts & USB_OTG_GINTSTS_SRQINT) { |
||||
// we want to do "A-device host negotiation protocol" since we are the A-device
|
||||
/*puts("start request\n");
|
||||
puth(USBx->GOTGCTL); |
||||
puts("\n");*/ |
||||
//USBx->GUSBCFG |= USB_OTG_GUSBCFG_FDMOD;
|
||||
//USBx_HOST_PORT->HPRT = USB_OTG_HPRT_PPWR | USB_OTG_HPRT_PENA;
|
||||
//USBx->GOTGCTL |= USB_OTG_GOTGCTL_SRQ;
|
||||
} |
||||
|
||||
// out endpoint hit
|
||||
if (gintsts & USB_OTG_GINTSTS_OEPINT) { |
||||
#ifdef DEBUG_USB |
||||
puts(" 0:"); |
||||
puth(USBx_OUTEP(0)->DOEPINT); |
||||
puts(" 2:"); |
||||
puth(USBx_OUTEP(2)->DOEPINT); |
||||
puts(" 3:"); |
||||
puth(USBx_OUTEP(3)->DOEPINT); |
||||
puts(" "); |
||||
puth(USBx_OUTEP(3)->DOEPCTL); |
||||
puts(" 4:"); |
||||
puth(USBx_OUTEP(4)->DOEPINT); |
||||
puts(" OUT ENDPOINT\n"); |
||||
#endif |
||||
|
||||
if (USBx_OUTEP(2)->DOEPINT & USB_OTG_DOEPINT_XFRC) { |
||||
#ifdef DEBUG_USB |
||||
puts(" OUT2 PACKET XFRC\n"); |
||||
#endif |
||||
USBx_OUTEP(2)->DOEPTSIZ = (1 << 19) | 0x40; |
||||
USBx_OUTEP(2)->DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK; |
||||
} |
||||
|
||||
if (USBx_OUTEP(3)->DOEPINT & USB_OTG_DOEPINT_XFRC) { |
||||
#ifdef DEBUG_USB |
||||
puts(" OUT3 PACKET XFRC\n"); |
||||
#endif |
||||
USBx_OUTEP(3)->DOEPTSIZ = (1 << 19) | 0x40; |
||||
USBx_OUTEP(3)->DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK; |
||||
} else if (USBx_OUTEP(3)->DOEPINT & 0x2000) { |
||||
#ifdef DEBUG_USB |
||||
puts(" OUT3 PACKET WTF\n"); |
||||
#endif |
||||
// if NAK was set trigger this, unknown interrupt
|
||||
USBx_OUTEP(3)->DOEPTSIZ = (1 << 19) | 0x40; |
||||
USBx_OUTEP(3)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK; |
||||
} else if (USBx_OUTEP(3)->DOEPINT) { |
||||
puts("OUTEP3 error "); |
||||
puth(USBx_OUTEP(3)->DOEPINT); |
||||
puts("\n"); |
||||
} |
||||
|
||||
if (USBx_OUTEP(0)->DOEPINT & USB_OTG_DIEPINT_XFRC) { |
||||
// ready for next packet
|
||||
USBx_OUTEP(0)->DOEPTSIZ = USB_OTG_DOEPTSIZ_STUPCNT | (USB_OTG_DOEPTSIZ_PKTCNT & (1 << 19)) | (1 * 8); |
||||
} |
||||
|
||||
// respond to setup packets
|
||||
if (USBx_OUTEP(0)->DOEPINT & USB_OTG_DOEPINT_STUP) { |
||||
usb_setup(); |
||||
} |
||||
|
||||
USBx_OUTEP(0)->DOEPINT = USBx_OUTEP(0)->DOEPINT; |
||||
USBx_OUTEP(2)->DOEPINT = USBx_OUTEP(2)->DOEPINT; |
||||
USBx_OUTEP(3)->DOEPINT = USBx_OUTEP(3)->DOEPINT; |
||||
} |
||||
|
||||
// interrupt endpoint hit (Page 1221)
|
||||
if (gintsts & USB_OTG_GINTSTS_IEPINT) { |
||||
#ifdef DEBUG_USB |
||||
puts(" "); |
||||
puth(USBx_INEP(0)->DIEPINT); |
||||
puts(" "); |
||||
puth(USBx_INEP(1)->DIEPINT); |
||||
puts(" IN ENDPOINT\n"); |
||||
#endif |
||||
|
||||
// Should likely check the EP of the IN request even if there is
|
||||
// only one IN endpoint.
|
||||
|
||||
// No need to set NAK in OTG_DIEPCTL0 when nothing to send,
|
||||
// Appears USB core automatically sets NAK. WritePacket clears it.
|
||||
|
||||
// Handle the two interface alternate settings. Setting 0 is has
|
||||
// EP1 as bulk. Setting 1 has EP1 as interrupt. The code to handle
|
||||
// these two EP variations are very similar and can be
|
||||
// restructured for smaller code footprint. Keeping split out for
|
||||
// now for clarity.
|
||||
|
||||
//TODO add default case. Should it NAK?
|
||||
switch (current_int0_alt_setting) { |
||||
case 0: ////// Bulk config
|
||||
// *** IN token received when TxFIFO is empty
|
||||
if (USBx_INEP(1)->DIEPINT & USB_OTG_DIEPMSK_ITTXFEMSK) { |
||||
#ifdef DEBUG_USB |
||||
puts(" IN PACKET QUEUE\n"); |
||||
#endif |
||||
// TODO: always assuming max len, can we get the length?
|
||||
USB_WritePacket((void *)resp, usb_cb_ep1_in(resp, 0x40, 1), 1); |
||||
} |
||||
break; |
||||
|
||||
case 1: ////// Interrupt config
|
||||
// *** IN token received when TxFIFO is empty
|
||||
if (USBx_INEP(1)->DIEPINT & USB_OTG_DIEPMSK_ITTXFEMSK) { |
||||
#ifdef DEBUG_USB |
||||
puts(" IN PACKET QUEUE\n"); |
||||
#endif |
||||
// TODO: always assuming max len, can we get the length?
|
||||
int len = usb_cb_ep1_in(resp, 0x40, 1); |
||||
if (len > 0) { |
||||
USB_WritePacket((void *)resp, len, 1); |
||||
} |
||||
} |
||||
break; |
||||
} |
||||
|
||||
// clear interrupts
|
||||
USBx_INEP(0)->DIEPINT = USBx_INEP(0)->DIEPINT; // Why ep0?
|
||||
USBx_INEP(1)->DIEPINT = USBx_INEP(1)->DIEPINT; |
||||
} |
||||
|
||||
// clear all interrupts we handled
|
||||
USBx_DEVICE->DAINT = daint; |
||||
USBx->GOTGINT = gotgint; |
||||
USBx->GINTSTS = gintsts; |
||||
|
||||
//USBx->GINTMSK = 0xFFFFFFFF & ~(USB_OTG_GINTMSK_NPTXFEM | USB_OTG_GINTMSK_PTXFEM | USB_OTG_GINTSTS_SOF | USB_OTG_GINTSTS_EOPF);
|
||||
} |
||||
|
||||
void OTG_FS_IRQHandler(void) { |
||||
NVIC_DisableIRQ(OTG_FS_IRQn); |
||||
//__disable_irq();
|
||||
usb_irqhandler(); |
||||
//__enable_irq();
|
||||
NVIC_EnableIRQ(OTG_FS_IRQn); |
||||
} |
||||
|
@ -0,0 +1,3 @@ |
||||
#!/bin/bash |
||||
sudo apt-get install gcc-arm-none-eabi python-pip |
||||
sudo pip2 install libusb1 |
@ -0,0 +1,5 @@ |
||||
#!/bin/bash |
||||
# Need formula for gcc |
||||
brew tap ArmMbed/homebrew-formulae |
||||
brew install python dfu-util arm-none-eabi-gcc |
||||
pip2 install libusb1 |
@ -0,0 +1,450 @@ |
||||
#ifdef STM32F4 |
||||
#include "stm32f4xx_hal_gpio_ex.h" |
||||
#else |
||||
#include "stm32f2xx_hal_gpio_ex.h" |
||||
#endif |
||||
|
||||
// ********************* 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(GPIO, pin, PULL_NONE); |
||||
return ret; |
||||
} |
||||
|
||||
// must call again from main because BSS is zeroed
|
||||
void detect() { |
||||
// 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); |
||||
#else |
||||
// need to do this for early detect
|
||||
is_giant_panda = 0; |
||||
revision = PANDA_REV_AB; |
||||
is_entering_bootmode = 0; |
||||
#endif |
||||
} |
||||
|
||||
// ********************* bringup *********************
|
||||
|
||||
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 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_TIM2EN; |
||||
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; |
||||
} |
||||
|
||||
// ********************* setters *********************
|
||||
|
||||
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_mode(int can, int use_gmlan) { |
||||
// 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); |
||||
#ifdef CAN3 |
||||
} 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); |
||||
#endif |
||||
} |
||||
} 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); |
||||
#ifdef CAN3 |
||||
} 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); |
||||
#endif |
||||
} |
||||
} |
||||
} |
||||
|
||||
#define USB_POWER_NONE 0 |
||||
#define USB_POWER_CLIENT 1 |
||||
#define USB_POWER_CDP 2 |
||||
#define USB_POWER_DCP 3 |
||||
|
||||
int usb_power_mode = USB_POWER_NONE; |
||||
|
||||
void set_usb_power_mode(int mode) { |
||||
switch (mode) { |
||||
case USB_POWER_CLIENT: |
||||
// B2,A13: set client mode
|
||||
set_gpio_output(GPIOB, 2, 0); |
||||
set_gpio_output(GPIOA, 13, 1); |
||||
break; |
||||
case USB_POWER_CDP: |
||||
// B2,A13: set CDP mode
|
||||
set_gpio_output(GPIOB, 2, 1); |
||||
set_gpio_output(GPIOA, 13, 1); |
||||
break; |
||||
case USB_POWER_DCP: |
||||
// B2,A13: set DCP mode on the charger (breaks USB!)
|
||||
set_gpio_output(GPIOB, 2, 0); |
||||
set_gpio_output(GPIOA, 13, 0); |
||||
break; |
||||
} |
||||
usb_power_mode = 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: |
||||
// ESP ON
|
||||
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
|
||||
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
|
||||
#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 |
||||
set_can_enable(CAN1, 1); |
||||
|
||||
// B5,B6: CAN 2
|
||||
set_can_mode(1, 0); |
||||
set_can_enable(CAN2, 1); |
||||
|
||||
// A8,A15: CAN 3
|
||||
#ifdef CAN3 |
||||
set_can_mode(2, 0); |
||||
set_can_enable(CAN3, 1); |
||||
#endif |
||||
|
||||
/* GMLAN mode pins:
|
||||
M0(B15) M1(B14) mode |
||||
======================= |
||||
0 0 sleep |
||||
1 0 100kbit |
||||
0 1 high voltage wakeup |
||||
1 1 33kbit (normal) |
||||
*/ |
||||
|
||||
// put gmlan transceiver in normal mode
|
||||
set_gpio_output(GPIOB, 14, 1); |
||||
set_gpio_output(GPIOB, 15, 1); |
||||
|
||||
#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) { |
||||
set_usb_power_mode(USB_POWER_CLIENT); |
||||
} |
||||
} |
||||
|
||||
// ********************* early bringup *********************
|
||||
|
||||
#define ENTER_BOOTLOADER_MAGIC 0xdeadbeef |
||||
#define ENTER_SOFTLOADER_MAGIC 0xdeadc0de |
||||
#define BOOT_NORMAL 0xdeadb111 |
||||
|
||||
extern void *g_pfnVectors; |
||||
extern uint32_t enter_bootloader_mode; |
||||
|
||||
void jump_to_bootloader() { |
||||
// do enter bootloader
|
||||
enter_bootloader_mode = 0; |
||||
void (*bootloader)(void) = (void (*)(void)) (*((uint32_t *)0x1fff0004)); |
||||
|
||||
// jump to bootloader
|
||||
bootloader(); |
||||
|
||||
// reset on exit
|
||||
enter_bootloader_mode = BOOT_NORMAL; |
||||
NVIC_SystemReset(); |
||||
} |
||||
|
||||
void early() { |
||||
// after it's been in the bootloader, things are initted differently, so we reset
|
||||
if (enter_bootloader_mode != BOOT_NORMAL && |
||||
enter_bootloader_mode != ENTER_BOOTLOADER_MAGIC && |
||||
enter_bootloader_mode != ENTER_SOFTLOADER_MAGIC) { |
||||
enter_bootloader_mode = BOOT_NORMAL; |
||||
NVIC_SystemReset(); |
||||
} |
||||
|
||||
// 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; |
||||
|
||||
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) { |
||||
set_esp_mode(ESP_DISABLED); |
||||
} else { |
||||
set_esp_mode(ESP_ENABLED); |
||||
} |
||||
#endif |
||||
|
||||
|
||||
if (enter_bootloader_mode == ENTER_BOOTLOADER_MAGIC) { |
||||
set_esp_mode(ESP_DISABLED); |
||||
set_led(LED_GREEN, 1); |
||||
|
||||
jump_to_bootloader(); |
||||
} |
||||
|
||||
if (is_entering_bootmode) { |
||||
enter_bootloader_mode = ENTER_SOFTLOADER_MAGIC; |
||||
} |
||||
} |
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,87 @@ |
||||
/**************************************************************************//**
|
||||
* @file core_cmFunc.h |
||||
* @brief CMSIS Cortex-M Core Function Access Header File |
||||
* @version V4.30 |
||||
* @date 20. October 2015 |
||||
******************************************************************************/ |
||||
/* Copyright (c) 2009 - 2015 ARM LIMITED
|
||||
|
||||
All rights reserved. |
||||
Redistribution and use in source and binary forms, with or without |
||||
modification, are permitted provided that the following conditions are met: |
||||
- Redistributions of source code must retain the above copyright |
||||
notice, this list of conditions and the following disclaimer. |
||||
- Redistributions in binary form must reproduce the above copyright |
||||
notice, this list of conditions and the following disclaimer in the |
||||
documentation and/or other materials provided with the distribution. |
||||
- Neither the name of ARM nor the names of its contributors may be used |
||||
to endorse or promote products derived from this software without |
||||
specific prior written permission. |
||||
* |
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||||
ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE |
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
||||
POSSIBILITY OF SUCH DAMAGE. |
||||
---------------------------------------------------------------------------*/ |
||||
|
||||
|
||||
#if defined ( __ICCARM__ ) |
||||
#pragma system_include /* treat file as system include file for MISRA check */ |
||||
#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) |
||||
#pragma clang system_header /* treat file as system include file */ |
||||
#endif |
||||
|
||||
#ifndef __CORE_CMFUNC_H |
||||
#define __CORE_CMFUNC_H |
||||
|
||||
|
||||
/* ########################### Core Function Access ########################### */ |
||||
/** \ingroup CMSIS_Core_FunctionInterface
|
||||
\defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions |
||||
@{ |
||||
*/ |
||||
|
||||
/*------------------ RealView Compiler -----------------*/ |
||||
#if defined ( __CC_ARM ) |
||||
#include "cmsis_armcc.h" |
||||
|
||||
/*------------------ ARM Compiler V6 -------------------*/ |
||||
#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) |
||||
#include "cmsis_armcc_V6.h" |
||||
|
||||
/*------------------ GNU Compiler ----------------------*/ |
||||
#elif defined ( __GNUC__ ) |
||||
#include "cmsis_gcc.h" |
||||
|
||||
/*------------------ ICC Compiler ----------------------*/ |
||||
#elif defined ( __ICCARM__ ) |
||||
#include <cmsis_iar.h> |
||||
|
||||
/*------------------ TI CCS Compiler -------------------*/ |
||||
#elif defined ( __TMS470__ ) |
||||
#include <cmsis_ccs.h> |
||||
|
||||
/*------------------ TASKING Compiler ------------------*/ |
||||
#elif defined ( __TASKING__ ) |
||||
/*
|
||||
* The CMSIS functions have been implemented as intrinsics in the compiler. |
||||
* Please use "carm -?i" to get an up to date list of all intrinsics, |
||||
* Including the CMSIS ones. |
||||
*/ |
||||
|
||||
/*------------------ COSMIC Compiler -------------------*/ |
||||
#elif defined ( __CSMC__ ) |
||||
#include <cmsis_csm.h> |
||||
|
||||
#endif |
||||
|
||||
/*@} end of CMSIS_Core_RegAccFunctions */ |
||||
|
||||
#endif /* __CORE_CMFUNC_H */ |
@ -0,0 +1,87 @@ |
||||
/**************************************************************************//**
|
||||
* @file core_cmInstr.h |
||||
* @brief CMSIS Cortex-M Core Instruction Access Header File |
||||
* @version V4.30 |
||||
* @date 20. October 2015 |
||||
******************************************************************************/ |
||||
/* Copyright (c) 2009 - 2015 ARM LIMITED
|
||||
|
||||
All rights reserved. |
||||
Redistribution and use in source and binary forms, with or without |
||||
modification, are permitted provided that the following conditions are met: |
||||
- Redistributions of source code must retain the above copyright |
||||
notice, this list of conditions and the following disclaimer. |
||||
- Redistributions in binary form must reproduce the above copyright |
||||
notice, this list of conditions and the following disclaimer in the |
||||
documentation and/or other materials provided with the distribution. |
||||
- Neither the name of ARM nor the names of its contributors may be used |
||||
to endorse or promote products derived from this software without |
||||
specific prior written permission. |
||||
* |
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||||
ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE |
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
||||
POSSIBILITY OF SUCH DAMAGE. |
||||
---------------------------------------------------------------------------*/ |
||||
|
||||
|
||||
#if defined ( __ICCARM__ ) |
||||
#pragma system_include /* treat file as system include file for MISRA check */ |
||||
#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) |
||||
#pragma clang system_header /* treat file as system include file */ |
||||
#endif |
||||
|
||||
#ifndef __CORE_CMINSTR_H |
||||
#define __CORE_CMINSTR_H |
||||
|
||||
|
||||
/* ########################## Core Instruction Access ######################### */ |
||||
/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface
|
||||
Access to dedicated instructions |
||||
@{ |
||||
*/ |
||||
|
||||
/*------------------ RealView Compiler -----------------*/ |
||||
#if defined ( __CC_ARM ) |
||||
#include "cmsis_armcc.h" |
||||
|
||||
/*------------------ ARM Compiler V6 -------------------*/ |
||||
#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) |
||||
#include "cmsis_armcc_V6.h" |
||||
|
||||
/*------------------ GNU Compiler ----------------------*/ |
||||
#elif defined ( __GNUC__ ) |
||||
#include "cmsis_gcc.h" |
||||
|
||||
/*------------------ ICC Compiler ----------------------*/ |
||||
#elif defined ( __ICCARM__ ) |
||||
#include <cmsis_iar.h> |
||||
|
||||
/*------------------ TI CCS Compiler -------------------*/ |
||||
#elif defined ( __TMS470__ ) |
||||
#include <cmsis_ccs.h> |
||||
|
||||
/*------------------ TASKING Compiler ------------------*/ |
||||
#elif defined ( __TASKING__ ) |
||||
/*
|
||||
* The CMSIS functions have been implemented as intrinsics in the compiler. |
||||
* Please use "carm -?i" to get an up to date list of all intrinsics, |
||||
* Including the CMSIS ones. |
||||
*/ |
||||
|
||||
/*------------------ COSMIC Compiler -------------------*/ |
||||
#elif defined ( __CSMC__ ) |
||||
#include <cmsis_csm.h> |
||||
|
||||
#endif |
||||
|
||||
/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ |
||||
|
||||
#endif /* __CORE_CMINSTR_H */ |
@ -0,0 +1,96 @@ |
||||
/**************************************************************************//**
|
||||
* @file core_cmSimd.h |
||||
* @brief CMSIS Cortex-M SIMD Header File |
||||
* @version V4.30 |
||||
* @date 20. October 2015 |
||||
******************************************************************************/ |
||||
/* Copyright (c) 2009 - 2015 ARM LIMITED
|
||||
|
||||
All rights reserved. |
||||
Redistribution and use in source and binary forms, with or without |
||||
modification, are permitted provided that the following conditions are met: |
||||
- Redistributions of source code must retain the above copyright |
||||
notice, this list of conditions and the following disclaimer. |
||||
- Redistributions in binary form must reproduce the above copyright |
||||
notice, this list of conditions and the following disclaimer in the |
||||
documentation and/or other materials provided with the distribution. |
||||
- Neither the name of ARM nor the names of its contributors may be used |
||||
to endorse or promote products derived from this software without |
||||
specific prior written permission. |
||||
* |
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||||
ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE |
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
||||
POSSIBILITY OF SUCH DAMAGE. |
||||
---------------------------------------------------------------------------*/ |
||||
|
||||
|
||||
#if defined ( __ICCARM__ ) |
||||
#pragma system_include /* treat file as system include file for MISRA check */ |
||||
#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) |
||||
#pragma clang system_header /* treat file as system include file */ |
||||
#endif |
||||
|
||||
#ifndef __CORE_CMSIMD_H |
||||
#define __CORE_CMSIMD_H |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
|
||||
/* ################### Compiler specific Intrinsics ########################### */ |
||||
/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics
|
||||
Access to dedicated SIMD instructions |
||||
@{ |
||||
*/ |
||||
|
||||
/*------------------ RealView Compiler -----------------*/ |
||||
#if defined ( __CC_ARM ) |
||||
#include "cmsis_armcc.h" |
||||
|
||||
/*------------------ ARM Compiler V6 -------------------*/ |
||||
#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) |
||||
#include "cmsis_armcc_V6.h" |
||||
|
||||
/*------------------ GNU Compiler ----------------------*/ |
||||
#elif defined ( __GNUC__ ) |
||||
#include "cmsis_gcc.h" |
||||
|
||||
/*------------------ ICC Compiler ----------------------*/ |
||||
#elif defined ( __ICCARM__ ) |
||||
#include <cmsis_iar.h> |
||||
|
||||
/*------------------ TI CCS Compiler -------------------*/ |
||||
#elif defined ( __TMS470__ ) |
||||
#include <cmsis_ccs.h> |
||||
|
||||
/*------------------ TASKING Compiler ------------------*/ |
||||
#elif defined ( __TASKING__ ) |
||||
/*
|
||||
* The CMSIS functions have been implemented as intrinsics in the compiler. |
||||
* Please use "carm -?i" to get an up to date list of all intrinsics, |
||||
* Including the CMSIS ones. |
||||
*/ |
||||
|
||||
/*------------------ COSMIC Compiler -------------------*/ |
||||
#elif defined ( __CSMC__ ) |
||||
#include <cmsis_csm.h> |
||||
|
||||
#endif |
||||
|
||||
/*@} end of group CMSIS_SIMD_intrinsics */ |
||||
|
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif /* __CORE_CMSIMD_H */ |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,209 @@ |
||||
/**
|
||||
****************************************************************************** |
||||
* @file stm32f2xx.h |
||||
* @author MCD Application Team |
||||
* @version V2.1.2 |
||||
* @date 29-June-2016 |
||||
* @brief CMSIS STM32F2xx Device Peripheral Access Layer Header File.
|
||||
* |
||||
* The file is the unique include file that the application programmer |
||||
* is using in the C source code, usually in main.c. This file contains: |
||||
* - Configuration section that allows to select: |
||||
* - The STM32F2xx device used in the target application |
||||
* - To use or not the peripheral’s drivers in application code(i.e.
|
||||
* code will be based on direct access to peripheral’s registers
|
||||
* rather than drivers API), this option is controlled by
|
||||
* "#define USE_HAL_DRIVER" |
||||
*
|
||||
****************************************************************************** |
||||
* @attention |
||||
* |
||||
* <h2><center>© COPYRIGHT(c) 2016 STMicroelectronics</center></h2> |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without modification, |
||||
* are permitted provided that the following conditions are met: |
||||
* 1. Redistributions of source code must retain the above copyright notice, |
||||
* this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, |
||||
* this list of conditions and the following disclaimer in the documentation |
||||
* and/or other materials provided with the distribution. |
||||
* 3. Neither the name of STMicroelectronics nor the names of its contributors |
||||
* may be used to endorse or promote products derived from this software |
||||
* without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE |
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
* |
||||
****************************************************************************** |
||||
*/ |
||||
|
||||
/** @addtogroup CMSIS
|
||||
* @{ |
||||
*/ |
||||
|
||||
/** @addtogroup stm32f2xx
|
||||
* @{ |
||||
*/ |
||||
|
||||
#ifndef __STM32F2xx_H |
||||
#define __STM32F2xx_H |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif /* __cplusplus */ |
||||
|
||||
/** @addtogroup Library_configuration_section
|
||||
* @{ |
||||
*/ |
||||
|
||||
/**
|
||||
* @brief STM32 Family |
||||
*/ |
||||
#if !defined (STM32F2) |
||||
#define STM32F2 |
||||
#endif /* STM32F2 */ |
||||
|
||||
/* Uncomment the line below according to the target STM32 device used in your
|
||||
application
|
||||
*/ |
||||
#if !defined (STM32F205xx) && !defined (STM32F215xx) && !defined (STM32F207xx) && !defined (STM32F217xx) |
||||
|
||||
/* #define STM32F205xx */ /*!< STM32F205RG, STM32F205VG, STM32F205ZG, STM32F205RF, STM32F205VF, STM32F205ZF,
|
||||
STM32F205RE, STM32F205VE, STM32F205ZE, STM32F205RC, STM32F205VC, STM32F205ZC, |
||||
STM32F205RB and STM32F205VB Devices */ |
||||
/* #define STM32F215xx */ /*!< STM32F215RG, STM32F215VG, STM32F215ZG, STM32F215RE, STM32F215VE and STM32F215ZE Devices */ |
||||
/* #define STM32F207xx */ /*!< STM32F207VG, STM32F207ZG, STM32F207IG, STM32F207VF, STM32F207ZF, STM32F207IF,
|
||||
STM32F207VE, STM32F207ZE, STM32F207IE, STM32F207VC, STM32F207ZC and STM32F207IC Devices */ |
||||
/* #define STM32F217xx */ /*!< STM32F217VG, STM32F217ZG, STM32F217IG, STM32F217VE, STM32F217ZE and STM32F217IE Devices */ |
||||
|
||||
#endif |
||||
|
||||
/* Tip: To avoid modifying this file each time you need to switch between these
|
||||
devices, you can define the device in your toolchain compiler preprocessor. |
||||
*/ |
||||
#if !defined (USE_HAL_DRIVER) |
||||
/**
|
||||
* @brief Comment the line below if you will not use the peripherals drivers. |
||||
In this case, these drivers will not be included and the application code will
|
||||
be based on direct access to peripherals registers
|
||||
*/ |
||||
/*#define USE_HAL_DRIVER */ |
||||
#endif /* USE_HAL_DRIVER */ |
||||
|
||||
/**
|
||||
* @brief CMSIS Device version number V2.1.2 |
||||
*/ |
||||
#define __STM32F2xx_CMSIS_VERSION_MAIN (0x02U) /*!< [31:24] main version */ |
||||
#define __STM32F2xx_CMSIS_VERSION_SUB1 (0x01U) /*!< [23:16] sub1 version */ |
||||
#define __STM32F2xx_CMSIS_VERSION_SUB2 (0x02U) /*!< [15:8] sub2 version */ |
||||
#define __STM32F2xx_CMSIS_VERSION_RC (0x00U) /*!< [7:0] release candidate */ |
||||
#define __STM32F2xx_CMSIS_VERSION ((__STM32F2xx_CMSIS_VERSION_MAIN << 24)\ |
||||
|(__STM32F2xx_CMSIS_VERSION_SUB1 << 16)\
|
||||
|(__STM32F2xx_CMSIS_VERSION_SUB2 << 8 )\
|
||||
|(__STM32F2xx_CMSIS_VERSION)) |
||||
|
||||
/**
|
||||
* @} |
||||
*/ |
||||
|
||||
/** @addtogroup Device_Included
|
||||
* @{ |
||||
*/ |
||||
|
||||
#if defined(STM32F205xx) |
||||
#include "stm32f205xx.h" |
||||
#elif defined(STM32F215xx) |
||||
#include "stm32f215xx.h" |
||||
#elif defined(STM32F207xx) |
||||
#include "stm32f207xx.h" |
||||
#elif defined(STM32F217xx) |
||||
#include "stm32f217xx.h" |
||||
#else |
||||
#error "Please select first the target STM32F2xx device used in your application (in stm32f2xx.h file)" |
||||
#endif |
||||
|
||||
/**
|
||||
* @} |
||||
*/ |
||||
|
||||
/** @addtogroup Exported_types
|
||||
* @{ |
||||
*/
|
||||
typedef enum
|
||||
{ |
||||
RESET = 0,
|
||||
SET = !RESET |
||||
} FlagStatus, ITStatus; |
||||
|
||||
typedef enum
|
||||
{ |
||||
DISABLE = 0,
|
||||
ENABLE = !DISABLE |
||||
} FunctionalState; |
||||
#define IS_FUNCTIONAL_STATE(STATE) (((STATE) == DISABLE) || ((STATE) == ENABLE)) |
||||
|
||||
typedef enum
|
||||
{ |
||||
ERROR = 0,
|
||||
SUCCESS = !ERROR |
||||
} ErrorStatus; |
||||
|
||||
/**
|
||||
* @} |
||||
*/ |
||||
|
||||
|
||||
/** @addtogroup Exported_macro
|
||||
* @{ |
||||
*/ |
||||
#define SET_BIT(REG, BIT) ((REG) |= (BIT)) |
||||
|
||||
#define CLEAR_BIT(REG, BIT) ((REG) &= ~(BIT)) |
||||
|
||||
#define READ_BIT(REG, BIT) ((REG) & (BIT)) |
||||
|
||||
#define CLEAR_REG(REG) ((REG) = (0x0)) |
||||
|
||||
#define WRITE_REG(REG, VAL) ((REG) = (VAL)) |
||||
|
||||
#define READ_REG(REG) ((REG)) |
||||
|
||||
#define MODIFY_REG(REG, CLEARMASK, SETMASK) WRITE_REG((REG), (((READ_REG(REG)) & (~(CLEARMASK))) | (SETMASK))) |
||||
|
||||
#define POSITION_VAL(VAL) (__CLZ(__RBIT(VAL))) |
||||
|
||||
|
||||
/**
|
||||
* @} |
||||
*/ |
||||
|
||||
#if defined (USE_HAL_DRIVER) |
||||
#include "stm32f2xx_hal.h" |
||||
#endif /* USE_HAL_DRIVER */ |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif /* __cplusplus */ |
||||
|
||||
#endif /* __STM32F2xx_H */ |
||||
|
||||
/**
|
||||
* @} |
||||
*/ |
||||
|
||||
/**
|
||||
* @} |
||||
*/ |
||||
|
||||
|
||||
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ |
@ -0,0 +1,181 @@ |
||||
/**
|
||||
****************************************************************************** |
||||
* @file stm32f2xx_hal_def.h |
||||
* @author MCD Application Team |
||||
* @version V1.1.3 |
||||
* @date 29-June-2016 |
||||
* @brief This file contains HAL common defines, enumeration, macros and
|
||||
* structures definitions.
|
||||
****************************************************************************** |
||||
* @attention |
||||
* |
||||
* <h2><center>© COPYRIGHT(c) 2016 STMicroelectronics</center></h2> |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without modification, |
||||
* are permitted provided that the following conditions are met: |
||||
* 1. Redistributions of source code must retain the above copyright notice, |
||||
* this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, |
||||
* this list of conditions and the following disclaimer in the documentation |
||||
* and/or other materials provided with the distribution. |
||||
* 3. Neither the name of STMicroelectronics nor the names of its contributors |
||||
* may be used to endorse or promote products derived from this software |
||||
* without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE |
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
* |
||||
****************************************************************************** |
||||
*/ |
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/ |
||||
#ifndef __STM32F2xx_HAL_DEF |
||||
#define __STM32F2xx_HAL_DEF |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
/* Includes ------------------------------------------------------------------*/ |
||||
#include "stm32f2xx.h" |
||||
//#include "Legacy/stm32_hal_legacy.h"
|
||||
//#include <stdio.h>
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/ |
||||
|
||||
/**
|
||||
* @brief HAL Status structures definition
|
||||
*/
|
||||
typedef enum
|
||||
{ |
||||
HAL_OK = 0x00U, |
||||
HAL_ERROR = 0x01U, |
||||
HAL_BUSY = 0x02U, |
||||
HAL_TIMEOUT = 0x03U |
||||
} HAL_StatusTypeDef; |
||||
|
||||
/**
|
||||
* @brief HAL Lock structures definition
|
||||
*/ |
||||
typedef enum
|
||||
{ |
||||
HAL_UNLOCKED = 0x00U, |
||||
HAL_LOCKED = 0x01U
|
||||
} HAL_LockTypeDef; |
||||
|
||||
/* Exported macro ------------------------------------------------------------*/ |
||||
#define HAL_MAX_DELAY 0xFFFFFFFFU |
||||
|
||||
#define HAL_IS_BIT_SET(REG, BIT) (((REG) & (BIT)) != RESET) |
||||
#define HAL_IS_BIT_CLR(REG, BIT) (((REG) & (BIT)) == RESET) |
||||
|
||||
#define __HAL_LINKDMA(__HANDLE__, __PPP_DMA_FIELD_, __DMA_HANDLE_) \ |
||||
do{ \
|
||||
(__HANDLE__)->__PPP_DMA_FIELD_ = &(__DMA_HANDLE_); \
|
||||
(__DMA_HANDLE_).Parent = (__HANDLE__); \
|
||||
} while(0) |
||||
|
||||
#define UNUSED(x) ((void)(x)) |
||||
|
||||
/** @brief Reset the Handle's State field.
|
||||
* @param __HANDLE__: specifies the Peripheral Handle. |
||||
* @note This macro can be used for the following purpose:
|
||||
* - When the Handle is declared as local variable; before passing it as parameter |
||||
* to HAL_PPP_Init() for the first time, it is mandatory to use this macro
|
||||
* to set to 0 the Handle's "State" field. |
||||
* Otherwise, "State" field may have any random value and the first time the function
|
||||
* HAL_PPP_Init() is called, the low level hardware initialization will be missed |
||||
* (i.e. HAL_PPP_MspInit() will not be executed). |
||||
* - When there is a need to reconfigure the low level hardware: instead of calling |
||||
* HAL_PPP_DeInit() then HAL_PPP_Init(), user can make a call to this macro then HAL_PPP_Init(). |
||||
* In this later function, when the Handle's "State" field is set to 0, it will execute the function |
||||
* HAL_PPP_MspInit() which will reconfigure the low level hardware. |
||||
* @retval None |
||||
*/ |
||||
#define __HAL_RESET_HANDLE_STATE(__HANDLE__) ((__HANDLE__)->State = 0U) |
||||
|
||||
#if (USE_RTOS == 1) |
||||
/* Reserved for future use */ |
||||
#error " USE_RTOS should be 0 in the current HAL release " |
||||
#else |
||||
#define __HAL_LOCK(__HANDLE__) \ |
||||
do{ \
|
||||
if((__HANDLE__)->Lock == HAL_LOCKED) \
|
||||
{ \
|
||||
return HAL_BUSY; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
(__HANDLE__)->Lock = HAL_LOCKED; \
|
||||
} \
|
||||
}while (0) |
||||
|
||||
#define __HAL_UNLOCK(__HANDLE__) \ |
||||
do{ \
|
||||
(__HANDLE__)->Lock = HAL_UNLOCKED; \
|
||||
}while (0) |
||||
#endif /* USE_RTOS */ |
||||
|
||||
#if defined ( __GNUC__ ) |
||||
#ifndef __weak |
||||
#define __weak __attribute__((weak)) |
||||
#endif /* __weak */ |
||||
#ifndef __packed |
||||
#define __packed __attribute__((__packed__)) |
||||
#endif /* __packed */ |
||||
#endif /* __GNUC__ */ |
||||
|
||||
|
||||
/* Macro to get variable aligned on 4-bytes, for __ICCARM__ the directive "#pragma data_alignment=4" must be used instead */ |
||||
#if defined (__GNUC__) /* GNU Compiler */ |
||||
#ifndef __ALIGN_END |
||||
#define __ALIGN_END __attribute__ ((aligned (4))) |
||||
#endif /* __ALIGN_END */ |
||||
#ifndef __ALIGN_BEGIN |
||||
#define __ALIGN_BEGIN |
||||
#endif /* __ALIGN_BEGIN */ |
||||
#else |
||||
#ifndef __ALIGN_END |
||||
#define __ALIGN_END |
||||
#endif /* __ALIGN_END */ |
||||
#ifndef __ALIGN_BEGIN |
||||
#if defined (__CC_ARM) /* ARM Compiler */ |
||||
#define __ALIGN_BEGIN __align(4) |
||||
#elif defined (__ICCARM__) /* IAR Compiler */ |
||||
#define __ALIGN_BEGIN |
||||
#endif /* __CC_ARM */ |
||||
#endif /* __ALIGN_BEGIN */ |
||||
#endif /* __GNUC__ */ |
||||
|
||||
/**
|
||||
* @brief __NOINLINE definition |
||||
*/
|
||||
#if defined ( __CC_ARM ) || defined ( __GNUC__ ) |
||||
/* ARM & GNUCompiler
|
||||
----------------
|
||||
*/ |
||||
#define __NOINLINE __attribute__ ( (noinline) ) |
||||
|
||||
#elif defined ( __ICCARM__ ) |
||||
/* ICCARM Compiler
|
||||
--------------- |
||||
*/ |
||||
#define __NOINLINE _Pragma("optimize = no_inline") |
||||
|
||||
#endif |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif /* ___STM32F2xx_HAL_DEF */ |
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ |
@ -0,0 +1,299 @@ |
||||
/**
|
||||
****************************************************************************** |
||||
* @file stm32f2xx_hal_gpio_ex.h |
||||
* @author MCD Application Team |
||||
* @version V1.1.3 |
||||
* @date 29-June-2016 |
||||
* @brief Header file of GPIO HAL Extension module. |
||||
****************************************************************************** |
||||
* @attention |
||||
* |
||||
* <h2><center>© COPYRIGHT(c) 2016 STMicroelectronics</center></h2> |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without modification, |
||||
* are permitted provided that the following conditions are met: |
||||
* 1. Redistributions of source code must retain the above copyright notice, |
||||
* this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, |
||||
* this list of conditions and the following disclaimer in the documentation |
||||
* and/or other materials provided with the distribution. |
||||
* 3. Neither the name of STMicroelectronics nor the names of its contributors |
||||
* may be used to endorse or promote products derived from this software |
||||
* without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE |
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
* |
||||
****************************************************************************** |
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/ |
||||
#ifndef __STM32F2xx_HAL_GPIO_EX_H |
||||
#define __STM32F2xx_HAL_GPIO_EX_H |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
/* Includes ------------------------------------------------------------------*/ |
||||
#include "stm32f2xx_hal_def.h" |
||||
|
||||
/** @addtogroup STM32F2xx_HAL_Driver
|
||||
* @{ |
||||
*/ |
||||
|
||||
/** @defgroup GPIOEx GPIOEx
|
||||
* @{ |
||||
*/
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/ |
||||
/* Exported constants --------------------------------------------------------*/ |
||||
/* Exported constants --------------------------------------------------------*/ |
||||
|
||||
/** @defgroup GPIOEx_Exported_Constants GPIO Exported Constants
|
||||
* @{ |
||||
*/
|
||||
|
||||
/** @defgroup GPIO_Alternate_function_selection GPIO Alternate function selection
|
||||
* @{ |
||||
*/ |
||||
|
||||
/**
|
||||
* @brief AF 0 selection
|
||||
*/
|
||||
#define GPIO_AF0_RTC_50Hz ((uint8_t)0x00U) /* RTC_50Hz Alternate Function mapping */ |
||||
#define GPIO_AF0_MCO ((uint8_t)0x00U) /* MCO (MCO1 and MCO2) Alternate Function mapping */ |
||||
#define GPIO_AF0_TAMPER ((uint8_t)0x00U) /* TAMPER (TAMPER_1 and TAMPER_2) Alternate Function mapping */ |
||||
#define GPIO_AF0_SWJ ((uint8_t)0x00U) /* SWJ (SWD and JTAG) Alternate Function mapping */ |
||||
#define GPIO_AF0_TRACE ((uint8_t)0x00U) /* TRACE Alternate Function mapping */ |
||||
|
||||
/**
|
||||
* @brief AF 1 selection
|
||||
*/
|
||||
#define GPIO_AF1_TIM1 ((uint8_t)0x01U) /* TIM1 Alternate Function mapping */ |
||||
#define GPIO_AF1_TIM2 ((uint8_t)0x01U) /* TIM2 Alternate Function mapping */ |
||||
|
||||
/**
|
||||
* @brief AF 2 selection
|
||||
*/
|
||||
#define GPIO_AF2_TIM3 ((uint8_t)0x02U) /* TIM3 Alternate Function mapping */ |
||||
#define GPIO_AF2_TIM4 ((uint8_t)0x02U) /* TIM4 Alternate Function mapping */ |
||||
#define GPIO_AF2_TIM5 ((uint8_t)0x02U) /* TIM5 Alternate Function mapping */ |
||||
|
||||
/**
|
||||
* @brief AF 3 selection
|
||||
*/
|
||||
#define GPIO_AF3_TIM8 ((uint8_t)0x03U) /* TIM8 Alternate Function mapping */ |
||||
#define GPIO_AF3_TIM9 ((uint8_t)0x03U) /* TIM9 Alternate Function mapping */ |
||||
#define GPIO_AF3_TIM10 ((uint8_t)0x03U) /* TIM10 Alternate Function mapping */ |
||||
#define GPIO_AF3_TIM11 ((uint8_t)0x03U) /* TIM11 Alternate Function mapping */ |
||||
|
||||
/**
|
||||
* @brief AF 4 selection
|
||||
*/
|
||||
#define GPIO_AF4_I2C1 ((uint8_t)0x04U) /* I2C1 Alternate Function mapping */ |
||||
#define GPIO_AF4_I2C2 ((uint8_t)0x04U) /* I2C2 Alternate Function mapping */ |
||||
#define GPIO_AF4_I2C3 ((uint8_t)0x04U) /* I2C3 Alternate Function mapping */ |
||||
|
||||
/**
|
||||
* @brief AF 5 selection
|
||||
*/
|
||||
#define GPIO_AF5_SPI1 ((uint8_t)0x05U) /* SPI1 Alternate Function mapping */ |
||||
#define GPIO_AF5_SPI2 ((uint8_t)0x05U) /* SPI2/I2S2 Alternate Function mapping */ |
||||
/**
|
||||
* @brief AF 6 selection
|
||||
*/
|
||||
#define GPIO_AF6_SPI3 ((uint8_t)0x06U) /* SPI3/I2S3 Alternate Function mapping */ |
||||
|
||||
/**
|
||||
* @brief AF 7 selection
|
||||
*/
|
||||
#define GPIO_AF7_USART1 ((uint8_t)0x07U) /* USART1 Alternate Function mapping */ |
||||
#define GPIO_AF7_USART2 ((uint8_t)0x07U) /* USART2 Alternate Function mapping */ |
||||
#define GPIO_AF7_USART3 ((uint8_t)0x07U) /* USART3 Alternate Function mapping */ |
||||
|
||||
/**
|
||||
* @brief AF 8 selection
|
||||
*/
|
||||
#define GPIO_AF8_UART4 ((uint8_t)0x08U) /* UART4 Alternate Function mapping */ |
||||
#define GPIO_AF8_UART5 ((uint8_t)0x08U) /* UART5 Alternate Function mapping */ |
||||
#define GPIO_AF8_USART6 ((uint8_t)0x08U) /* USART6 Alternate Function mapping */ |
||||
|
||||
/**
|
||||
* @brief AF 9 selection
|
||||
*/
|
||||
#define GPIO_AF9_CAN1 ((uint8_t)0x09U) /* CAN1 Alternate Function mapping */ |
||||
#define GPIO_AF9_CAN2 ((uint8_t)0x09U) /* CAN2 Alternate Function mapping */ |
||||
#define GPIO_AF9_TIM12 ((uint8_t)0x09U) /* TIM12 Alternate Function mapping */ |
||||
#define GPIO_AF9_TIM13 ((uint8_t)0x09U) /* TIM13 Alternate Function mapping */ |
||||
#define GPIO_AF9_TIM14 ((uint8_t)0x09U) /* TIM14 Alternate Function mapping */ |
||||
|
||||
/**
|
||||
* @brief AF 10 selection
|
||||
*/
|
||||
#define GPIO_AF10_OTG_FS ((uint8_t)0xAU) /* OTG_FS Alternate Function mapping */ |
||||
#define GPIO_AF10_OTG_HS ((uint8_t)0xAU) /* OTG_HS Alternate Function mapping */ |
||||
|
||||
/**
|
||||
* @brief AF 11 selection
|
||||
*/
|
||||
#if defined(STM32F207xx) || defined(STM32F217xx) |
||||
#define GPIO_AF11_ETH ((uint8_t)0x0BU) /* ETHERNET Alternate Function mapping */ |
||||
#endif /* STM32F207xx || STM32F217xx */ |
||||
|
||||
/**
|
||||
* @brief AF 12 selection
|
||||
*/
|
||||
#define GPIO_AF12_FSMC ((uint8_t)0xCU) /* FSMC Alternate Function mapping */ |
||||
#define GPIO_AF12_OTG_HS_FS ((uint8_t)0xCU) /* OTG HS configured in FS, Alternate Function mapping */ |
||||
#define GPIO_AF12_SDIO ((uint8_t)0xCU) /* SDIO Alternate Function mapping */ |
||||
|
||||
/**
|
||||
* @brief AF 13 selection
|
||||
*/
|
||||
#if defined(STM32F207xx) || defined(STM32F217xx) |
||||
#define GPIO_AF13_DCMI ((uint8_t)0x0DU) /* DCMI Alternate Function mapping */ |
||||
#endif /* STM32F207xx || STM32F217xx */ |
||||
|
||||
/**
|
||||
* @brief AF 15 selection
|
||||
*/
|
||||
#define GPIO_AF15_EVENTOUT ((uint8_t)0x0FU) /* EVENTOUT Alternate Function mapping */ |
||||
|
||||
/**
|
||||
* @} |
||||
*/
|
||||
|
||||
/**
|
||||
* @} |
||||
*/ |
||||
|
||||
/* Exported macro ------------------------------------------------------------*/ |
||||
/** @defgroup GPIOEx_Exported_Macros GPIO Exported Macros
|
||||
* @{ |
||||
*/ |
||||
/**
|
||||
* @} |
||||
*/ |
||||
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
/** @defgroup GPIOEx_Exported_Functions GPIO Exported Functions
|
||||
* @{ |
||||
*/ |
||||
/**
|
||||
* @} |
||||
*/ |
||||
|
||||
/* Private types -------------------------------------------------------------*/ |
||||
/* Private variables ---------------------------------------------------------*/ |
||||
/* Private constants ---------------------------------------------------------*/ |
||||
/** @defgroup GPIOEx_Private_Constants GPIO Private Constants
|
||||
* @{ |
||||
*/ |
||||
/**
|
||||
* @} |
||||
*/ |
||||
|
||||
/* Private macros ------------------------------------------------------------*/ |
||||
/** @defgroup GPIOEx_Private_Macros GPIO Private Macros
|
||||
* @{ |
||||
*/ |
||||
/** @defgroup GPIOEx_Get_Port_Index GPIO Get Port Index
|
||||
* @{ |
||||
*/ |
||||
#define GPIO_GET_INDEX(__GPIOx__) (uint8_t)(((__GPIOx__) == (GPIOA))? 0U :\ |
||||
((__GPIOx__) == (GPIOB))? 1U :\
|
||||
((__GPIOx__) == (GPIOC))? 2U :\
|
||||
((__GPIOx__) == (GPIOD))? 3U :\
|
||||
((__GPIOx__) == (GPIOE))? 4U :\
|
||||
((__GPIOx__) == (GPIOF))? 5U :\
|
||||
((__GPIOx__) == (GPIOG))? 6U :\
|
||||
((__GPIOx__) == (GPIOH))? 7U :\
|
||||
((__GPIOx__) == (GPIOI))? 8U : 9U) |
||||
/**
|
||||
* @} |
||||
*/ |
||||
|
||||
/** @defgroup GPIOEx_IS_Alternat_function_selection GPIO Check Alternate Function
|
||||
* @{ |
||||
*/
|
||||
#if defined(STM32F207xx) || defined(STM32F217xx) |
||||
|
||||
#define IS_GPIO_AF(AF) (((AF) == GPIO_AF0_RTC_50Hz) || ((AF) == GPIO_AF9_TIM14) || \ |
||||
((AF) == GPIO_AF0_MCO) || ((AF) == GPIO_AF0_TAMPER) || \
|
||||
((AF) == GPIO_AF0_SWJ) || ((AF) == GPIO_AF0_TRACE) || \
|
||||
((AF) == GPIO_AF1_TIM1) || ((AF) == GPIO_AF1_TIM2) || \
|
||||
((AF) == GPIO_AF2_TIM3) || ((AF) == GPIO_AF2_TIM4) || \
|
||||
((AF) == GPIO_AF2_TIM5) || ((AF) == GPIO_AF3_TIM8) || \
|
||||
((AF) == GPIO_AF4_I2C1) || ((AF) == GPIO_AF4_I2C2) || \
|
||||
((AF) == GPIO_AF4_I2C3) || ((AF) == GPIO_AF5_SPI1) || \
|
||||
((AF) == GPIO_AF5_SPI2) || ((AF) == GPIO_AF9_TIM13) || \
|
||||
((AF) == GPIO_AF6_SPI3) || ((AF) == GPIO_AF9_TIM12) || \
|
||||
((AF) == GPIO_AF7_USART1) || ((AF) == GPIO_AF7_USART2) || \
|
||||
((AF) == GPIO_AF7_USART3) || ((AF) == GPIO_AF8_UART4) || \
|
||||
((AF) == GPIO_AF8_UART5) || ((AF) == GPIO_AF8_USART6) || \
|
||||
((AF) == GPIO_AF9_CAN1) || ((AF) == GPIO_AF9_CAN2) || \
|
||||
((AF) == GPIO_AF10_OTG_FS) || ((AF) == GPIO_AF10_OTG_HS) || \
|
||||
((AF) == GPIO_AF11_ETH) || ((AF) == GPIO_AF12_OTG_HS_FS) || \
|
||||
((AF) == GPIO_AF12_SDIO) || ((AF) == GPIO_AF13_DCMI) || \
|
||||
((AF) == GPIO_AF12_FSMC) || ((AF) == GPIO_AF15_EVENTOUT)) |
||||
#else /* STM32F207xx || STM32F217xx */ |
||||
#define IS_GPIO_AF(AF) (((AF) == GPIO_AF0_RTC_50Hz) || ((AF) == GPIO_AF9_TIM14) || \ |
||||
((AF) == GPIO_AF0_MCO) || ((AF) == GPIO_AF0_TAMPER) || \
|
||||
((AF) == GPIO_AF0_SWJ) || ((AF) == GPIO_AF0_TRACE) || \
|
||||
((AF) == GPIO_AF1_TIM1) || ((AF) == GPIO_AF1_TIM2) || \
|
||||
((AF) == GPIO_AF2_TIM3) || ((AF) == GPIO_AF2_TIM4) || \
|
||||
((AF) == GPIO_AF2_TIM5) || ((AF) == GPIO_AF3_TIM8) || \
|
||||
((AF) == GPIO_AF4_I2C1) || ((AF) == GPIO_AF4_I2C2) || \
|
||||
((AF) == GPIO_AF4_I2C3) || ((AF) == GPIO_AF5_SPI1) || \
|
||||
((AF) == GPIO_AF5_SPI2) || ((AF) == GPIO_AF9_TIM13) || \
|
||||
((AF) == GPIO_AF6_SPI3) || ((AF) == GPIO_AF9_TIM12) || \
|
||||
((AF) == GPIO_AF7_USART1) || ((AF) == GPIO_AF7_USART2) || \
|
||||
((AF) == GPIO_AF7_USART3) || ((AF) == GPIO_AF8_UART4) || \
|
||||
((AF) == GPIO_AF8_UART5) || ((AF) == GPIO_AF8_USART6) || \
|
||||
((AF) == GPIO_AF9_CAN1) || ((AF) == GPIO_AF9_CAN2) || \
|
||||
((AF) == GPIO_AF10_OTG_FS) || ((AF) == GPIO_AF10_OTG_HS) || \
|
||||
((AF) == GPIO_AF12_OTG_HS_FS) || ((AF) == GPIO_AF12_SDIO) || \
|
||||
((AF) == GPIO_AF12_FSMC) || ((AF) == GPIO_AF15_EVENTOUT)) |
||||
#endif /* STM32F207xx || STM32F217xx */ |
||||
|
||||
/**
|
||||
* @} |
||||
*/
|
||||
|
||||
/**
|
||||
* @} |
||||
*/ |
||||
|
||||
/* Private functions ---------------------------------------------------------*/ |
||||
/** @defgroup GPIOEx_Private_Functions GPIO Private Functions
|
||||
* @{ |
||||
*/ |
||||
|
||||
/**
|
||||
* @} |
||||
*/ |
||||
|
||||
/**
|
||||
* @} |
||||
*/
|
||||
|
||||
/**
|
||||
* @} |
||||
*/
|
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif /* __STM32F2xx_HAL_GPIO_EX_H */ |
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,271 @@ |
||||
/**
|
||||
****************************************************************************** |
||||
* @file stm32f4xx.h |
||||
* @author MCD Application Team |
||||
* @version V2.6.0 |
||||
* @date 04-November-2016 |
||||
* @brief CMSIS STM32F4xx Device Peripheral Access Layer Header File. |
||||
*
|
||||
* The file is the unique include file that the application programmer |
||||
* is using in the C source code, usually in main.c. This file contains: |
||||
* - Configuration section that allows to select: |
||||
* - The STM32F4xx device used in the target application |
||||
* - To use or not the peripheral’s drivers in application code(i.e.
|
||||
* code will be based on direct access to peripheral’s registers
|
||||
* rather than drivers API), this option is controlled by
|
||||
* "#define USE_HAL_DRIVER" |
||||
*
|
||||
****************************************************************************** |
||||
* @attention |
||||
* |
||||
* <h2><center>© COPYRIGHT(c) 2016 STMicroelectronics</center></h2> |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without modification, |
||||
* are permitted provided that the following conditions are met: |
||||
* 1. Redistributions of source code must retain the above copyright notice, |
||||
* this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, |
||||
* this list of conditions and the following disclaimer in the documentation |
||||
* and/or other materials provided with the distribution. |
||||
* 3. Neither the name of STMicroelectronics nor the names of its contributors |
||||
* may be used to endorse or promote products derived from this software |
||||
* without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE |
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
* |
||||
****************************************************************************** |
||||
*/ |
||||
|
||||
/** @addtogroup CMSIS
|
||||
* @{ |
||||
*/ |
||||
|
||||
/** @addtogroup stm32f4xx
|
||||
* @{ |
||||
*/ |
||||
|
||||
#ifndef __STM32F4xx_H |
||||
#define __STM32F4xx_H |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif /* __cplusplus */ |
||||
|
||||
/** @addtogroup Library_configuration_section
|
||||
* @{ |
||||
*/ |
||||
|
||||
/**
|
||||
* @brief STM32 Family |
||||
*/ |
||||
#if !defined (STM32F4) |
||||
#define STM32F4 |
||||
#endif /* STM32F4 */ |
||||
|
||||
/* Uncomment the line below according to the target STM32 device used in your
|
||||
application
|
||||
*/ |
||||
#if !defined (STM32F405xx) && !defined (STM32F415xx) && !defined (STM32F407xx) && !defined (STM32F417xx) && \ |
||||
!defined (STM32F427xx) && !defined (STM32F437xx) && !defined (STM32F429xx) && !defined (STM32F439xx) && \
|
||||
!defined (STM32F401xC) && !defined (STM32F401xE) && !defined (STM32F410Tx) && !defined (STM32F410Cx) && \
|
||||
!defined (STM32F410Rx) && !defined (STM32F411xE) && !defined (STM32F446xx) && !defined (STM32F469xx) && \
|
||||
!defined (STM32F479xx) && !defined (STM32F412Cx) && !defined (STM32F412Rx) && !defined (STM32F412Vx) && \
|
||||
!defined (STM32F412Zx) && !defined (STM32F413xx) && !defined (STM32F423xx) |
||||
/* #define STM32F405xx */ /*!< STM32F405RG, STM32F405VG and STM32F405ZG Devices */ |
||||
/* #define STM32F415xx */ /*!< STM32F415RG, STM32F415VG and STM32F415ZG Devices */ |
||||
/* #define STM32F407xx */ /*!< STM32F407VG, STM32F407VE, STM32F407ZG, STM32F407ZE, STM32F407IG and STM32F407IE Devices */ |
||||
/* #define STM32F417xx */ /*!< STM32F417VG, STM32F417VE, STM32F417ZG, STM32F417ZE, STM32F417IG and STM32F417IE Devices */ |
||||
/* #define STM32F427xx */ /*!< STM32F427VG, STM32F427VI, STM32F427ZG, STM32F427ZI, STM32F427IG and STM32F427II Devices */ |
||||
/* #define STM32F437xx */ /*!< STM32F437VG, STM32F437VI, STM32F437ZG, STM32F437ZI, STM32F437IG and STM32F437II Devices */ |
||||
/* #define STM32F429xx */ /*!< STM32F429VG, STM32F429VI, STM32F429ZG, STM32F429ZI, STM32F429BG, STM32F429BI, STM32F429NG,
|
||||
STM32F439NI, STM32F429IG and STM32F429II Devices */ |
||||
/* #define STM32F439xx */ /*!< STM32F439VG, STM32F439VI, STM32F439ZG, STM32F439ZI, STM32F439BG, STM32F439BI, STM32F439NG,
|
||||
STM32F439NI, STM32F439IG and STM32F439II Devices */ |
||||
/* #define STM32F401xC */ /*!< STM32F401CB, STM32F401CC, STM32F401RB, STM32F401RC, STM32F401VB and STM32F401VC Devices */ |
||||
/* #define STM32F401xE */ /*!< STM32F401CD, STM32F401RD, STM32F401VD, STM32F401CE, STM32F401RE and STM32F401VE Devices */ |
||||
/* #define STM32F410Tx */ /*!< STM32F410T8 and STM32F410TB Devices */ |
||||
/* #define STM32F410Cx */ /*!< STM32F410C8 and STM32F410CB Devices */ |
||||
/* #define STM32F410Rx */ /*!< STM32F410R8 and STM32F410RB Devices */ |
||||
/* #define STM32F411xE */ /*!< STM32F411CC, STM32F411RC, STM32F411VC, STM32F411CE, STM32F411RE and STM32F411VE Devices */ |
||||
/* #define STM32F446xx */ /*!< STM32F446MC, STM32F446ME, STM32F446RC, STM32F446RE, STM32F446VC, STM32F446VE, STM32F446ZC,
|
||||
and STM32F446ZE Devices */ |
||||
/* #define STM32F469xx */ /*!< STM32F469AI, STM32F469II, STM32F469BI, STM32F469NI, STM32F469AG, STM32F469IG, STM32F469BG,
|
||||
STM32F469NG, STM32F469AE, STM32F469IE, STM32F469BE and STM32F469NE Devices */ |
||||
/* #define STM32F479xx */ /*!< STM32F479AI, STM32F479II, STM32F479BI, STM32F479NI, STM32F479AG, STM32F479IG, STM32F479BG
|
||||
and STM32F479NG Devices */ |
||||
/* #define STM32F412Cx */ /*!< STM32F412CEU and STM32F412CGU Devices */ |
||||
/* #define STM32F412Zx */ /*!< STM32F412ZET, STM32F412ZGT, STM32F412ZEJ and STM32F412ZGJ Devices */ |
||||
/* #define STM32F412Vx */ /*!< STM32F412VET, STM32F412VGT, STM32F412VEH and STM32F412VGH Devices */ |
||||
/* #define STM32F412Rx */ /*!< STM32F412RET, STM32F412RGT, STM32F412REY and STM32F412RGY Devices */ |
||||
/* #define STM32F413xx */ /*!< STM32F413CH, STM32F413MH, STM32F413RH, STM32F413VH, STM32F413ZH, STM32F413CG, STM32F413MG,
|
||||
STM32F413RG, STM32F413VG and STM32F413ZG Devices */ |
||||
/* #define STM32F423xx */ /*!< STM32F423CH, STM32F423RH, STM32F423VH and STM32F423ZH Devices */ |
||||
#endif |
||||
|
||||
/* Tip: To avoid modifying this file each time you need to switch between these
|
||||
devices, you can define the device in your toolchain compiler preprocessor. |
||||
*/ |
||||
#if !defined (USE_HAL_DRIVER) |
||||
/**
|
||||
* @brief Comment the line below if you will not use the peripherals drivers. |
||||
In this case, these drivers will not be included and the application code will
|
||||
be based on direct access to peripherals registers
|
||||
*/ |
||||
/*#define USE_HAL_DRIVER */ |
||||
#endif /* USE_HAL_DRIVER */ |
||||
|
||||
/**
|
||||
* @brief CMSIS version number V2.6.0 |
||||
*/ |
||||
#define __STM32F4xx_CMSIS_VERSION_MAIN (0x02U) /*!< [31:24] main version */ |
||||
#define __STM32F4xx_CMSIS_VERSION_SUB1 (0x06U) /*!< [23:16] sub1 version */ |
||||
#define __STM32F4xx_CMSIS_VERSION_SUB2 (0x00U) /*!< [15:8] sub2 version */ |
||||
#define __STM32F4xx_CMSIS_VERSION_RC (0x00U) /*!< [7:0] release candidate */ |
||||
#define __STM32F4xx_CMSIS_VERSION ((__STM32F4xx_CMSIS_VERSION_MAIN << 24)\ |
||||
|(__STM32F4xx_CMSIS_VERSION_SUB1 << 16)\
|
||||
|(__STM32F4xx_CMSIS_VERSION_SUB2 << 8 )\
|
||||
|(__STM32F4xx_CMSIS_VERSION)) |
||||
|
||||
/**
|
||||
* @} |
||||
*/ |
||||
|
||||
/** @addtogroup Device_Included
|
||||
* @{ |
||||
*/ |
||||
|
||||
#if defined(STM32F405xx) |
||||
#include "stm32f405xx.h" |
||||
#elif defined(STM32F415xx) |
||||
#include "stm32f415xx.h" |
||||
#elif defined(STM32F407xx) |
||||
#include "stm32f407xx.h" |
||||
#elif defined(STM32F417xx) |
||||
#include "stm32f417xx.h" |
||||
#elif defined(STM32F427xx) |
||||
#include "stm32f427xx.h" |
||||
#elif defined(STM32F437xx) |
||||
#include "stm32f437xx.h" |
||||
#elif defined(STM32F429xx) |
||||
#include "stm32f429xx.h" |
||||
#elif defined(STM32F439xx) |
||||
#include "stm32f439xx.h" |
||||
#elif defined(STM32F401xC) |
||||
#include "stm32f401xc.h" |
||||
#elif defined(STM32F401xE) |
||||
#include "stm32f401xe.h" |
||||
#elif defined(STM32F410Tx) |
||||
#include "stm32f410tx.h" |
||||
#elif defined(STM32F410Cx) |
||||
#include "stm32f410cx.h" |
||||
#elif defined(STM32F410Rx) |
||||
#include "stm32f410rx.h" |
||||
#elif defined(STM32F411xE) |
||||
#include "stm32f411xe.h" |
||||
#elif defined(STM32F446xx) |
||||
#include "stm32f446xx.h" |
||||
#elif defined(STM32F469xx) |
||||
#include "stm32f469xx.h" |
||||
#elif defined(STM32F479xx) |
||||
#include "stm32f479xx.h" |
||||
#elif defined(STM32F412Cx) |
||||
#include "stm32f412cx.h" |
||||
#elif defined(STM32F412Zx) |
||||
#include "stm32f412zx.h" |
||||
#elif defined(STM32F412Rx) |
||||
#include "stm32f412rx.h" |
||||
#elif defined(STM32F412Vx) |
||||
#include "stm32f412vx.h" |
||||
#elif defined(STM32F413xx) |
||||
#include "stm32f413xx.h" |
||||
#elif defined(STM32F423xx) |
||||
#include "stm32f423xx.h" |
||||
#else |
||||
#error "Please select first the target STM32F4xx device used in your application (in stm32f4xx.h file)" |
||||
#endif |
||||
|
||||
/**
|
||||
* @} |
||||
*/ |
||||
|
||||
/** @addtogroup Exported_types
|
||||
* @{ |
||||
*/
|
||||
typedef enum
|
||||
{ |
||||
RESET = 0U,
|
||||
SET = !RESET |
||||
} FlagStatus, ITStatus; |
||||
|
||||
typedef enum
|
||||
{ |
||||
DISABLE = 0U,
|
||||
ENABLE = !DISABLE |
||||
} FunctionalState; |
||||
#define IS_FUNCTIONAL_STATE(STATE) (((STATE) == DISABLE) || ((STATE) == ENABLE)) |
||||
|
||||
typedef enum
|
||||
{ |
||||
ERROR = 0U,
|
||||
SUCCESS = !ERROR |
||||
} ErrorStatus; |
||||
|
||||
/**
|
||||
* @} |
||||
*/ |
||||
|
||||
|
||||
/** @addtogroup Exported_macro
|
||||
* @{ |
||||
*/ |
||||
#define SET_BIT(REG, BIT) ((REG) |= (BIT)) |
||||
|
||||
#define CLEAR_BIT(REG, BIT) ((REG) &= ~(BIT)) |
||||
|
||||
#define READ_BIT(REG, BIT) ((REG) & (BIT)) |
||||
|
||||
#define CLEAR_REG(REG) ((REG) = (0x0)) |
||||
|
||||
#define WRITE_REG(REG, VAL) ((REG) = (VAL)) |
||||
|
||||
#define READ_REG(REG) ((REG)) |
||||
|
||||
#define MODIFY_REG(REG, CLEARMASK, SETMASK) WRITE_REG((REG), (((READ_REG(REG)) & (~(CLEARMASK))) | (SETMASK))) |
||||
|
||||
#define POSITION_VAL(VAL) (__CLZ(__RBIT(VAL))) |
||||
|
||||
|
||||
/**
|
||||
* @} |
||||
*/ |
||||
|
||||
#if defined (USE_HAL_DRIVER) |
||||
#include "stm32f4xx_hal.h" |
||||
#endif /* USE_HAL_DRIVER */ |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif /* __cplusplus */ |
||||
|
||||
#endif /* __STM32F4xx_H */ |
||||
/**
|
||||
* @} |
||||
*/ |
||||
|
||||
/**
|
||||
* @} |
||||
*/ |
||||
|
||||
|
||||
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ |
@ -0,0 +1,214 @@ |
||||
/**
|
||||
****************************************************************************** |
||||
* @file stm32f4xx_hal_def.h |
||||
* @author MCD Application Team |
||||
* @version V1.6.0 |
||||
* @date 04-November-2016 |
||||
* @brief This file contains HAL common defines, enumeration, macros and
|
||||
* structures definitions.
|
||||
****************************************************************************** |
||||
* @attention |
||||
* |
||||
* <h2><center>© COPYRIGHT(c) 2016 STMicroelectronics</center></h2> |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without modification, |
||||
* are permitted provided that the following conditions are met: |
||||
* 1. Redistributions of source code must retain the above copyright notice, |
||||
* this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, |
||||
* this list of conditions and the following disclaimer in the documentation |
||||
* and/or other materials provided with the distribution. |
||||
* 3. Neither the name of STMicroelectronics nor the names of its contributors |
||||
* may be used to endorse or promote products derived from this software |
||||
* without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE |
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
* |
||||
****************************************************************************** |
||||
*/ |
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/ |
||||
#ifndef __STM32F4xx_HAL_DEF |
||||
#define __STM32F4xx_HAL_DEF |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
/* Includes ------------------------------------------------------------------*/ |
||||
#include "stm32f4xx.h" |
||||
//#include "Legacy/stm32_hal_legacy.h"
|
||||
//#include <stdio.h>
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/ |
||||
|
||||
/**
|
||||
* @brief HAL Status structures definition
|
||||
*/
|
||||
typedef enum
|
||||
{ |
||||
HAL_OK = 0x00U, |
||||
HAL_ERROR = 0x01U, |
||||
HAL_BUSY = 0x02U, |
||||
HAL_TIMEOUT = 0x03U |
||||
} HAL_StatusTypeDef; |
||||
|
||||
/**
|
||||
* @brief HAL Lock structures definition
|
||||
*/ |
||||
typedef enum
|
||||
{ |
||||
HAL_UNLOCKED = 0x00U, |
||||
HAL_LOCKED = 0x01U
|
||||
} HAL_LockTypeDef; |
||||
|
||||
/* Exported macro ------------------------------------------------------------*/ |
||||
#define HAL_MAX_DELAY 0xFFFFFFFFU |
||||
|
||||
#define HAL_IS_BIT_SET(REG, BIT) (((REG) & (BIT)) != RESET) |
||||
#define HAL_IS_BIT_CLR(REG, BIT) (((REG) & (BIT)) == RESET) |
||||
|
||||
#define __HAL_LINKDMA(__HANDLE__, __PPP_DMA_FIELD__, __DMA_HANDLE__) \ |
||||
do{ \
|
||||
(__HANDLE__)->__PPP_DMA_FIELD__ = &(__DMA_HANDLE__); \
|
||||
(__DMA_HANDLE__).Parent = (__HANDLE__); \
|
||||
} while(0) |
||||
|
||||
#define UNUSED(x) ((void)(x)) |
||||
|
||||
/** @brief Reset the Handle's State field.
|
||||
* @param __HANDLE__: specifies the Peripheral Handle. |
||||
* @note This macro can be used for the following purpose:
|
||||
* - When the Handle is declared as local variable; before passing it as parameter |
||||
* to HAL_PPP_Init() for the first time, it is mandatory to use this macro
|
||||
* to set to 0 the Handle's "State" field. |
||||
* Otherwise, "State" field may have any random value and the first time the function
|
||||
* HAL_PPP_Init() is called, the low level hardware initialization will be missed |
||||
* (i.e. HAL_PPP_MspInit() will not be executed). |
||||
* - When there is a need to reconfigure the low level hardware: instead of calling |
||||
* HAL_PPP_DeInit() then HAL_PPP_Init(), user can make a call to this macro then HAL_PPP_Init(). |
||||
* In this later function, when the Handle's "State" field is set to 0, it will execute the function |
||||
* HAL_PPP_MspInit() which will reconfigure the low level hardware. |
||||
* @retval None |
||||
*/ |
||||
#define __HAL_RESET_HANDLE_STATE(__HANDLE__) ((__HANDLE__)->State = 0U) |
||||
|
||||
#if (USE_RTOS == 1) |
||||
/* Reserved for future use */ |
||||
#error "USE_RTOS should be 0 in the current HAL release" |
||||
#else |
||||
#define __HAL_LOCK(__HANDLE__) \ |
||||
do{ \
|
||||
if((__HANDLE__)->Lock == HAL_LOCKED) \
|
||||
{ \
|
||||
return HAL_BUSY; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
(__HANDLE__)->Lock = HAL_LOCKED; \
|
||||
} \
|
||||
}while (0) |
||||
|
||||
#define __HAL_UNLOCK(__HANDLE__) \ |
||||
do{ \
|
||||
(__HANDLE__)->Lock = HAL_UNLOCKED; \
|
||||
}while (0) |
||||
#endif /* USE_RTOS */ |
||||
|
||||
#if defined ( __GNUC__ ) |
||||
#ifndef __weak |
||||
#define __weak __attribute__((weak)) |
||||
#endif /* __weak */ |
||||
#ifndef __packed |
||||
#define __packed __attribute__((__packed__)) |
||||
#endif /* __packed */ |
||||
#endif /* __GNUC__ */ |
||||
|
||||
|
||||
/* Macro to get variable aligned on 4-bytes, for __ICCARM__ the directive "#pragma data_alignment=4" must be used instead */ |
||||
#if defined (__GNUC__) /* GNU Compiler */ |
||||
#ifndef __ALIGN_END |
||||
#define __ALIGN_END __attribute__ ((aligned (4))) |
||||
#endif /* __ALIGN_END */ |
||||
#ifndef __ALIGN_BEGIN |
||||
#define __ALIGN_BEGIN |
||||
#endif /* __ALIGN_BEGIN */ |
||||
#else |
||||
#ifndef __ALIGN_END |
||||
#define __ALIGN_END |
||||
#endif /* __ALIGN_END */ |
||||
#ifndef __ALIGN_BEGIN |
||||
#if defined (__CC_ARM) /* ARM Compiler */ |
||||
#define __ALIGN_BEGIN __align(4) |
||||
#elif defined (__ICCARM__) /* IAR Compiler */ |
||||
#define __ALIGN_BEGIN |
||||
#endif /* __CC_ARM */ |
||||
#endif /* __ALIGN_BEGIN */ |
||||
#endif /* __GNUC__ */ |
||||
|
||||
|
||||
/**
|
||||
* @brief __RAM_FUNC definition |
||||
*/
|
||||
#if defined ( __CC_ARM ) |
||||
/* ARM Compiler
|
||||
------------ |
||||
RAM functions are defined using the toolchain options.
|
||||
Functions that are executed in RAM should reside in a separate source module. |
||||
Using the 'Options for File' dialog you can simply change the 'Code / Const'
|
||||
area of a module to a memory space in physical RAM. |
||||
Available memory areas are declared in the 'Target' tab of the 'Options for Target' |
||||
dialog.
|
||||
*/ |
||||
#define __RAM_FUNC HAL_StatusTypeDef |
||||
|
||||
#elif defined ( __ICCARM__ ) |
||||
/* ICCARM Compiler
|
||||
--------------- |
||||
RAM functions are defined using a specific toolchain keyword "__ramfunc".
|
||||
*/ |
||||
#define __RAM_FUNC __ramfunc HAL_StatusTypeDef |
||||
|
||||
#elif defined ( __GNUC__ ) |
||||
/* GNU Compiler
|
||||
------------ |
||||
RAM functions are defined using a specific toolchain attribute
|
||||
"__attribute__((section(".RamFunc")))". |
||||
*/ |
||||
#define __RAM_FUNC HAL_StatusTypeDef __attribute__((section(".RamFunc"))) |
||||
|
||||
#endif |
||||
|
||||
/**
|
||||
* @brief __NOINLINE definition |
||||
*/
|
||||
#if defined ( __CC_ARM ) || defined ( __GNUC__ ) |
||||
/* ARM & GNUCompiler
|
||||
----------------
|
||||
*/ |
||||
#define __NOINLINE __attribute__ ( (noinline) ) |
||||
|
||||
#elif defined ( __ICCARM__ ) |
||||
/* ICCARM Compiler
|
||||
--------------- |
||||
*/ |
||||
#define __NOINLINE _Pragma("optimize = no_inline") |
||||
|
||||
#endif |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif /* ___STM32F4xx_HAL_DEF */ |
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,122 @@ |
||||
/**
|
||||
****************************************************************************** |
||||
* @file system_stm32f2xx.h |
||||
* @author MCD Application Team |
||||
* @version V2.1.2 |
||||
* @date 29-June-2016 |
||||
* @brief CMSIS Cortex-M3 Device System Source File for STM32F2xx devices.
|
||||
****************************************************************************** |
||||
* @attention |
||||
* |
||||
* <h2><center>© COPYRIGHT(c) 2016 STMicroelectronics</center></h2> |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without modification, |
||||
* are permitted provided that the following conditions are met: |
||||
* 1. Redistributions of source code must retain the above copyright notice, |
||||
* this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, |
||||
* this list of conditions and the following disclaimer in the documentation |
||||
* and/or other materials provided with the distribution. |
||||
* 3. Neither the name of STMicroelectronics nor the names of its contributors |
||||
* may be used to endorse or promote products derived from this software |
||||
* without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE |
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
* |
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/** @addtogroup CMSIS
|
||||
* @{ |
||||
*/ |
||||
|
||||
/** @addtogroup stm32f2xx_system
|
||||
* @{ |
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Define to prevent recursive inclusion |
||||
*/ |
||||
#ifndef __SYSTEM_STM32F2XX_H |
||||
#define __SYSTEM_STM32F2XX_H |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
/** @addtogroup STM32F2xx_System_Includes
|
||||
* @{ |
||||
*/ |
||||
|
||||
/**
|
||||
* @} |
||||
*/ |
||||
|
||||
|
||||
/** @addtogroup STM32F2xx_System_Exported_types
|
||||
* @{ |
||||
*/ |
||||
/* This variable is updated in three ways:
|
||||
1) by calling CMSIS function SystemCoreClockUpdate() |
||||
2) by calling HAL API function HAL_RCC_GetSysClockFreq() |
||||
3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency
|
||||
Note: If you use this function to configure the system clock; then there |
||||
is no need to call the 2 first functions listed above, since SystemCoreClock |
||||
variable is updated automatically. |
||||
*/ |
||||
extern uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock) */ |
||||
|
||||
|
||||
/**
|
||||
* @} |
||||
*/ |
||||
|
||||
/** @addtogroup STM32F2xx_System_Exported_Constants
|
||||
* @{ |
||||
*/ |
||||
|
||||
/**
|
||||
* @} |
||||
*/ |
||||
|
||||
/** @addtogroup STM32F2xx_System_Exported_Macros
|
||||
* @{ |
||||
*/ |
||||
|
||||
/**
|
||||
* @} |
||||
*/ |
||||
|
||||
/** @addtogroup STM32F2xx_System_Exported_Functions
|
||||
* @{ |
||||
*/ |
||||
|
||||
extern void SystemInit(void); |
||||
extern void SystemCoreClockUpdate(void); |
||||
/**
|
||||
* @} |
||||
*/ |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif /*__SYSTEM_STM32F2XX_H */ |
||||
|
||||
/**
|
||||
* @} |
||||
*/ |
||||
|
||||
/**
|
||||
* @} |
||||
*/
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ |
@ -0,0 +1,124 @@ |
||||
/**
|
||||
****************************************************************************** |
||||
* @file system_stm32f4xx.h |
||||
* @author MCD Application Team |
||||
* @version V2.6.0 |
||||
* @date 04-November-2016 |
||||
* @brief CMSIS Cortex-M4 Device System Source File for STM32F4xx devices.
|
||||
******************************************************************************
|
||||
* @attention |
||||
* |
||||
* <h2><center>© COPYRIGHT(c) 2016 STMicroelectronics</center></h2> |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without modification, |
||||
* are permitted provided that the following conditions are met: |
||||
* 1. Redistributions of source code must retain the above copyright notice, |
||||
* this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, |
||||
* this list of conditions and the following disclaimer in the documentation |
||||
* and/or other materials provided with the distribution. |
||||
* 3. Neither the name of STMicroelectronics nor the names of its contributors |
||||
* may be used to endorse or promote products derived from this software |
||||
* without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE |
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
* |
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/** @addtogroup CMSIS
|
||||
* @{ |
||||
*/ |
||||
|
||||
/** @addtogroup stm32f4xx_system
|
||||
* @{ |
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Define to prevent recursive inclusion |
||||
*/ |
||||
#ifndef __SYSTEM_STM32F4XX_H |
||||
#define __SYSTEM_STM32F4XX_H |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
/** @addtogroup STM32F4xx_System_Includes
|
||||
* @{ |
||||
*/ |
||||
|
||||
/**
|
||||
* @} |
||||
*/ |
||||
|
||||
|
||||
/** @addtogroup STM32F4xx_System_Exported_types
|
||||
* @{ |
||||
*/ |
||||
/* This variable is updated in three ways:
|
||||
1) by calling CMSIS function SystemCoreClockUpdate() |
||||
2) by calling HAL API function HAL_RCC_GetSysClockFreq() |
||||
3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency
|
||||
Note: If you use this function to configure the system clock; then there |
||||
is no need to call the 2 first functions listed above, since SystemCoreClock |
||||
variable is updated automatically. |
||||
*/ |
||||
extern uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock) */ |
||||
|
||||
extern const uint8_t AHBPrescTable[16]; /*!< AHB prescalers table values */ |
||||
extern const uint8_t APBPrescTable[8]; /*!< APB prescalers table values */ |
||||
|
||||
/**
|
||||
* @} |
||||
*/ |
||||
|
||||
/** @addtogroup STM32F4xx_System_Exported_Constants
|
||||
* @{ |
||||
*/ |
||||
|
||||
/**
|
||||
* @} |
||||
*/ |
||||
|
||||
/** @addtogroup STM32F4xx_System_Exported_Macros
|
||||
* @{ |
||||
*/ |
||||
|
||||
/**
|
||||
* @} |
||||
*/ |
||||
|
||||
/** @addtogroup STM32F4xx_System_Exported_Functions
|
||||
* @{ |
||||
*/ |
||||
|
||||
extern void SystemInit(void); |
||||
extern void SystemCoreClockUpdate(void); |
||||
/**
|
||||
* @} |
||||
*/ |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif /*__SYSTEM_STM32F4XX_H */ |
||||
|
||||
/**
|
||||
* @} |
||||
*/ |
||||
|
||||
/**
|
||||
* @} |
||||
*/
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ |
@ -0,0 +1,51 @@ |
||||
// **** shitty libc ****
|
||||
|
||||
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; |
||||
} |
||||
|
||||
// ********************* IRQ helpers *********************
|
||||
|
||||
int critical_depth = 0; |
||||
void enter_critical_section() { |
||||
__disable_irq(); |
||||
// this is safe because interrupts are disabled
|
||||
critical_depth += 1; |
||||
} |
||||
|
||||
void exit_critical_section() { |
||||
// this is safe because interrupts are disabled
|
||||
critical_depth -= 1; |
||||
if (critical_depth == 0) { |
||||
__enable_irq(); |
||||
} |
||||
} |
||||
|
@ -0,0 +1,644 @@ |
||||
#include "config.h" |
||||
#include "obj/gitversion.h" |
||||
|
||||
// ********************* includes *********************
|
||||
|
||||
#include "libc.h" |
||||
#include "safety.h" |
||||
#include "provision.h" |
||||
|
||||
#include "drivers/drivers.h" |
||||
|
||||
#include "drivers/llgpio.h" |
||||
#include "gpio.h" |
||||
|
||||
#include "drivers/uart.h" |
||||
#include "drivers/adc.h" |
||||
#include "drivers/usb.h" |
||||
#include "drivers/can.h" |
||||
#include "drivers/spi.h" |
||||
#include "drivers/timer.h" |
||||
|
||||
|
||||
// ***************************** fan *****************************
|
||||
|
||||
void fan_init() { |
||||
// timer for fan PWM
|
||||
TIM3->CCMR2 = TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3M_1; |
||||
TIM3->CCER = TIM_CCER_CC3E; |
||||
timer_init(TIM3, 10); |
||||
} |
||||
|
||||
void fan_set_speed(int fan_speed) { |
||||
TIM3->CCR3 = fan_speed; |
||||
} |
||||
|
||||
// ********************* serial debugging *********************
|
||||
|
||||
void debug_ring_callback(uart_ring *ring) { |
||||
char rcv; |
||||
while (getc(ring, &rcv)) { |
||||
putc(ring, rcv); |
||||
|
||||
// jump to DFU flash
|
||||
if (rcv == 'z') { |
||||
enter_bootloader_mode = ENTER_BOOTLOADER_MAGIC; |
||||
NVIC_SystemReset(); |
||||
} |
||||
|
||||
// normal reset
|
||||
if (rcv == 'x') { |
||||
NVIC_SystemReset(); |
||||
} |
||||
|
||||
// enable CDP mode
|
||||
if (rcv == 'C') { |
||||
puts("switching USB to CDP mode\n"); |
||||
set_usb_power_mode(USB_POWER_CDP); |
||||
} |
||||
if (rcv == 'c') { |
||||
puts("switching USB to client mode\n"); |
||||
set_usb_power_mode(USB_POWER_CLIENT); |
||||
} |
||||
if (rcv == 'D') { |
||||
puts("switching USB to DCP mode\n"); |
||||
set_usb_power_mode(USB_POWER_DCP); |
||||
} |
||||
} |
||||
} |
||||
|
||||
// ***************************** USB port *****************************
|
||||
|
||||
int get_health_pkt(void *dat) { |
||||
struct __attribute__((packed)) { |
||||
uint32_t voltage; |
||||
uint32_t current; |
||||
uint8_t started; |
||||
uint8_t controls_allowed; |
||||
uint8_t gas_interceptor_detected; |
||||
uint8_t started_signal_detected; |
||||
uint8_t started_alt; |
||||
} *health = dat; |
||||
|
||||
//Voltage will be measured in mv. 5000 = 5V
|
||||
uint32_t voltage = adc_get(ADCCHAN_VOLTAGE); |
||||
if (revision == PANDA_REV_AB) { |
||||
//REVB has a 100, 27 (27/127) voltage divider
|
||||
//Here is the calculation for the scale
|
||||
//ADCV = VIN_S * (27/127) * (4095/3.3)
|
||||
//RETVAL = ADCV * s = VIN_S*1000
|
||||
//s = 1000/((4095/3.3)*(27/127)) = 3.79053046
|
||||
|
||||
//Avoid needing floating point math
|
||||
health->voltage = (voltage * 3791) / 1000; |
||||
} else { |
||||
//REVC has a 10, 1 (1/11) voltage divider
|
||||
//Here is the calculation for the scale (s)
|
||||
//ADCV = VIN_S * (1/11) * (4095/3.3)
|
||||
//RETVAL = ADCV * s = VIN_S*1000
|
||||
//s = 1000/((4095/3.3)*(1/11)) = 8.8623046875
|
||||
|
||||
//Avoid needing floating point math
|
||||
health->voltage = (voltage * 8862) / 1000; |
||||
} |
||||
|
||||
#ifdef PANDA |
||||
health->current = adc_get(ADCCHAN_CURRENT); |
||||
health->started = (GPIOA->IDR & (1 << 1)) == 0; |
||||
#else |
||||
health->current = 0; |
||||
health->started = (GPIOC->IDR & (1 << 13)) != 0; |
||||
#endif |
||||
|
||||
health->controls_allowed = controls_allowed; |
||||
health->gas_interceptor_detected = gas_interceptor_detected; |
||||
|
||||
// DEPRECATED
|
||||
health->started_alt = 0; |
||||
health->started_signal_detected = 0; |
||||
|
||||
return sizeof(*health); |
||||
} |
||||
|
||||
int usb_cb_ep1_in(uint8_t *usbdata, int len, int hardwired) { |
||||
CAN_FIFOMailBox_TypeDef *reply = (CAN_FIFOMailBox_TypeDef *)usbdata; |
||||
int ilen = 0; |
||||
while (ilen < min(len/0x10, 4) && can_pop(&can_rx_q, &reply[ilen])) ilen++; |
||||
return ilen*0x10; |
||||
} |
||||
|
||||
// send on serial, first byte to select the ring
|
||||
void usb_cb_ep2_out(uint8_t *usbdata, int len, int hardwired) { |
||||
if (len == 0) return; |
||||
uart_ring *ur = get_ring_by_number(usbdata[0]); |
||||
if (!ur) return; |
||||
if ((usbdata[0] < 2) || safety_tx_lin_hook(usbdata[0]-2, usbdata+1, len-1)) { |
||||
for (int i = 1; i < len; i++) while (!putc(ur, usbdata[i])); |
||||
} |
||||
} |
||||
|
||||
// send on CAN
|
||||
void usb_cb_ep3_out(uint8_t *usbdata, int len, int hardwired) { |
||||
int dpkt = 0; |
||||
for (dpkt = 0; dpkt < len; dpkt += 0x10) { |
||||
uint32_t *tf = (uint32_t*)(&usbdata[dpkt]); |
||||
|
||||
// make a copy
|
||||
CAN_FIFOMailBox_TypeDef to_push; |
||||
to_push.RDHR = tf[3]; |
||||
to_push.RDLR = tf[2]; |
||||
to_push.RDTR = tf[1]; |
||||
to_push.RIR = tf[0]; |
||||
|
||||
uint8_t bus_number = (to_push.RDTR >> 4) & CAN_BUS_NUM_MASK; |
||||
can_send(&to_push, bus_number); |
||||
} |
||||
} |
||||
|
||||
int is_enumerated = 0; |
||||
|
||||
void usb_cb_enumeration_complete() { |
||||
puts("USB enumeration complete\n"); |
||||
is_enumerated = 1; |
||||
} |
||||
|
||||
int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, int hardwired) { |
||||
int resp_len = 0; |
||||
uart_ring *ur = NULL; |
||||
int i; |
||||
switch (setup->b.bRequest) { |
||||
// **** 0xc0: get CAN debug info
|
||||
case 0xc0: |
||||
puts("can tx: "); puth(can_tx_cnt); |
||||
puts(" txd: "); puth(can_txd_cnt); |
||||
puts(" rx: "); puth(can_rx_cnt); |
||||
puts(" err: "); puth(can_err_cnt); |
||||
puts("\n"); |
||||
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; |
||||
// **** 0xd2: get health packet
|
||||
case 0xd2: |
||||
resp_len = get_health_pkt(resp); |
||||
break; |
||||
// **** 0xd3: set fan speed
|
||||
case 0xd3: |
||||
fan_set_speed(setup->b.wValue.w); |
||||
break; |
||||
// **** 0xd6: get version
|
||||
case 0xd6: |
||||
COMPILE_TIME_ASSERT(sizeof(gitversion) <= MAX_RESP_LEN) |
||||
memcpy(resp, gitversion, sizeof(gitversion)); |
||||
resp_len = sizeof(gitversion)-1; |
||||
break; |
||||
// **** 0xd8: reset ST
|
||||
case 0xd8: |
||||
NVIC_SystemReset(); |
||||
break; |
||||
// **** 0xd9: set ESP power
|
||||
case 0xd9: |
||||
if (setup->b.wValue.w == 1) { |
||||
set_esp_mode(ESP_ENABLED); |
||||
} else { |
||||
set_esp_mode(ESP_DISABLED); |
||||
} |
||||
break; |
||||
// **** 0xda: reset ESP, with optional boot mode
|
||||
case 0xda: |
||||
set_esp_mode(ESP_DISABLED); |
||||
delay(1000000); |
||||
if (setup->b.wValue.w == 1) { |
||||
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: |
||||
#ifdef PANDA |
||||
if (setup->b.wValue.w == 1) { |
||||
// GMLAN ON
|
||||
if (setup->b.wIndex.w == 1) { |
||||
can_set_gmlan(1); |
||||
} else if (setup->b.wIndex.w == 2) { |
||||
// might be ignored on rev b panda
|
||||
can_set_gmlan(2); |
||||
} |
||||
} else { |
||||
can_set_gmlan(-1); |
||||
} |
||||
#endif |
||||
break; |
||||
// **** 0xdc: set safety mode
|
||||
case 0xdc: |
||||
// this is the only way to leave silent mode
|
||||
// and it's blocked over WiFi
|
||||
// Allow ELM security mode to be set over wifi.
|
||||
if (hardwired || setup->b.wValue.w == SAFETY_NOOUTPUT || setup->b.wValue.w == SAFETY_ELM327) { |
||||
safety_set_mode(setup->b.wValue.w); |
||||
switch (setup->b.wValue.w) { |
||||
case SAFETY_NOOUTPUT: |
||||
can_silent = ALL_CAN_SILENT; |
||||
break; |
||||
case SAFETY_ELM327: |
||||
can_silent = ALL_CAN_BUT_MAIN_SILENT; |
||||
break; |
||||
default: |
||||
can_silent = ALL_CAN_LIVE; |
||||
break; |
||||
} |
||||
can_init_all(); |
||||
} |
||||
break; |
||||
// **** 0xdd: enable can forwarding
|
||||
case 0xdd: |
||||
// wValue = Can Bus Num to forward from
|
||||
// wIndex = Can Bus Num to forward to
|
||||
if (setup->b.wValue.w < BUS_MAX && setup->b.wIndex.w < BUS_MAX && |
||||
setup->b.wValue.w != setup->b.wIndex.w) { // set forwarding
|
||||
can_set_forwarding(setup->b.wValue.w, setup->b.wIndex.w & CAN_BUS_NUM_MASK); |
||||
} else if(setup->b.wValue.w < BUS_MAX && setup->b.wIndex.w == 0xFF){ //Clear Forwarding
|
||||
can_set_forwarding(setup->b.wValue.w, -1); |
||||
} |
||||
break; |
||||
// **** 0xde: set can bitrate
|
||||
case 0xde: |
||||
if (setup->b.wValue.w < BUS_MAX) { |
||||
can_speed[setup->b.wValue.w] = setup->b.wIndex.w; |
||||
can_init(CAN_NUM_FROM_BUS_NUM(setup->b.wValue.w)); |
||||
} |
||||
break; |
||||
// **** 0xe0: uart read
|
||||
case 0xe0: |
||||
ur = get_ring_by_number(setup->b.wValue.w); |
||||
if (!ur) break; |
||||
// read
|
||||
while ((resp_len < min(setup->b.wLength.w, MAX_RESP_LEN)) && |
||||
getc(ur, (char*)&resp[resp_len])) { |
||||
++resp_len; |
||||
} |
||||
break; |
||||
// **** 0xe1: uart set baud rate
|
||||
case 0xe1: |
||||
ur = get_ring_by_number(setup->b.wValue.w); |
||||
if (!ur) break; |
||||
uart_set_baud(ur->uart, setup->b.wIndex.w); |
||||
break; |
||||
// **** 0xe2: uart set parity
|
||||
case 0xe2: |
||||
ur = get_ring_by_number(setup->b.wValue.w); |
||||
if (!ur) break; |
||||
switch (setup->b.wIndex.w) { |
||||
case 0: |
||||
// disable parity, 8-bit
|
||||
ur->uart->CR1 &= ~(USART_CR1_PCE | USART_CR1_M); |
||||
break; |
||||
case 1: |
||||
// even parity, 9-bit
|
||||
ur->uart->CR1 &= ~USART_CR1_PS; |
||||
ur->uart->CR1 |= USART_CR1_PCE | USART_CR1_M; |
||||
break; |
||||
case 2: |
||||
// odd parity, 9-bit
|
||||
ur->uart->CR1 |= USART_CR1_PS; |
||||
ur->uart->CR1 |= USART_CR1_PCE | USART_CR1_M; |
||||
break; |
||||
default: |
||||
break; |
||||
} |
||||
break; |
||||
// **** 0xe4: uart set baud rate extended
|
||||
case 0xe4: |
||||
ur = get_ring_by_number(setup->b.wValue.w); |
||||
if (!ur) break; |
||||
uart_set_baud(ur->uart, (int)setup->b.wIndex.w*300); |
||||
break; |
||||
// **** 0xe5: set CAN loopback (for testing)
|
||||
case 0xe5: |
||||
can_loopback = (setup->b.wValue.w > 0); |
||||
can_init_all(); |
||||
break; |
||||
// **** 0xe6: set USB power
|
||||
case 0xe6: |
||||
if (revision == PANDA_REV_C) { |
||||
if (setup->b.wValue.w == 1) { |
||||
puts("user setting CDP mode\n"); |
||||
set_usb_power_mode(USB_POWER_CDP); |
||||
} else if (setup->b.wValue.w == 2) { |
||||
puts("user setting DCP mode\n"); |
||||
set_usb_power_mode(USB_POWER_DCP); |
||||
} else { |
||||
puts("user setting CLIENT mode\n"); |
||||
set_usb_power_mode(USB_POWER_CLIENT); |
||||
} |
||||
} |
||||
break; |
||||
// **** 0xf0: do k-line wValue pulse on uart2 for Acura
|
||||
case 0xf0: |
||||
if (setup->b.wValue.w == 1) { |
||||
GPIOC->ODR &= ~(1 << 10); |
||||
GPIOC->MODER &= ~GPIO_MODER_MODER10_1; |
||||
GPIOC->MODER |= GPIO_MODER_MODER10_0; |
||||
} else { |
||||
GPIOC->ODR &= ~(1 << 12); |
||||
GPIOC->MODER &= ~GPIO_MODER_MODER12_1; |
||||
GPIOC->MODER |= GPIO_MODER_MODER12_0; |
||||
} |
||||
|
||||
for (i = 0; i < 80; i++) { |
||||
delay(8000); |
||||
if (setup->b.wValue.w == 1) { |
||||
GPIOC->ODR |= (1 << 10); |
||||
GPIOC->ODR &= ~(1 << 10); |
||||
} else { |
||||
GPIOC->ODR |= (1 << 12); |
||||
GPIOC->ODR &= ~(1 << 12); |
||||
} |
||||
} |
||||
|
||||
if (setup->b.wValue.w == 1) { |
||||
GPIOC->MODER &= ~GPIO_MODER_MODER10_0; |
||||
GPIOC->MODER |= GPIO_MODER_MODER10_1; |
||||
} else { |
||||
GPIOC->MODER &= ~GPIO_MODER_MODER12_0; |
||||
GPIOC->MODER |= GPIO_MODER_MODER12_1; |
||||
} |
||||
|
||||
delay(140 * 9000); |
||||
break; |
||||
// **** 0xf1: Clear CAN ring buffer.
|
||||
case 0xf1: |
||||
if (setup->b.wValue.w == 0xFFFF) { |
||||
puts("Clearing CAN Rx queue\n"); |
||||
can_clear(&can_rx_q); |
||||
} else if (setup->b.wValue.w < BUS_MAX) { |
||||
puts("Clearing CAN Tx queue\n"); |
||||
can_clear(can_queues[setup->b.wValue.w]); |
||||
} |
||||
break; |
||||
// **** 0xf2: Clear UART ring buffer.
|
||||
case 0xf2: |
||||
{ |
||||
uart_ring * rb = get_ring_by_number(setup->b.wValue.w); |
||||
if (rb) { |
||||
puts("Clearing UART queue.\n"); |
||||
clear_uart_buff(rb); |
||||
} |
||||
break; |
||||
} |
||||
default: |
||||
puts("NO HANDLER "); |
||||
puth(setup->b.bRequest); |
||||
puts("\n"); |
||||
break; |
||||
} |
||||
return resp_len; |
||||
} |
||||
|
||||
#ifdef PANDA |
||||
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 = 0; |
||||
switch (data[0]) { |
||||
case 0: |
||||
// control transfer
|
||||
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(data_out, 0x40, 0); |
||||
break; |
||||
case 2: |
||||
// ep 2, send serial
|
||||
usb_cb_ep2_out(data+4, data[2], 0); |
||||
break; |
||||
case 3: |
||||
// ep 3, send CAN
|
||||
usb_cb_ep3_out(data+4, data[2], 0); |
||||
break; |
||||
} |
||||
return resp_len; |
||||
} |
||||
|
||||
#else |
||||
|
||||
int spi_cb_rx(uint8_t *data, int len, uint8_t *data_out) { return 0; }; |
||||
|
||||
#endif |
||||
|
||||
|
||||
// ***************************** main code *****************************
|
||||
|
||||
void __initialize_hardware_early() { |
||||
early(); |
||||
} |
||||
|
||||
int main() { |
||||
// shouldn't have interrupts here, but just in case
|
||||
__disable_irq(); |
||||
|
||||
// init early devices
|
||||
clock_init(); |
||||
periph_init(); |
||||
detect(); |
||||
|
||||
// print hello
|
||||
puts("\n\n\n************************ MAIN START ************************\n"); |
||||
|
||||
// detect the revision and init the GPIOs
|
||||
puts("config:\n"); |
||||
#ifdef PANDA |
||||
puts(revision == PANDA_REV_C ? " panda rev c\n" : " panda rev a or b\n"); |
||||
#else |
||||
puts(" legacy\n"); |
||||
#endif |
||||
puts(has_external_debug_serial ? " real serial\n" : " USB serial\n"); |
||||
puts(is_giant_panda ? " GIANTpanda detected\n" : " not GIANTpanda\n"); |
||||
puts(is_entering_bootmode ? " ESP wants bootmode\n" : " no bootmode\n"); |
||||
gpio_init(); |
||||
|
||||
// enable main uart if it's connected
|
||||
if (has_external_debug_serial) { |
||||
// WEIRDNESS: without this gate around the UART, it would "crash", but only if the ESP is enabled
|
||||
// assuming it's because the lines were left floating and spurious noise was on them
|
||||
uart_init(USART2, 115200); |
||||
} |
||||
|
||||
#ifdef PANDA |
||||
// enable ESP uart
|
||||
uart_init(USART1, 115200); |
||||
|
||||
// enable LIN
|
||||
uart_init(UART5, 10400); |
||||
UART5->CR2 |= USART_CR2_LINEN; |
||||
uart_init(USART3, 10400); |
||||
USART3->CR2 |= USART_CR2_LINEN; |
||||
#endif |
||||
|
||||
// init microsecond system timer
|
||||
// increments 1000000 times per second
|
||||
// generate an update to set the prescaler
|
||||
TIM2->PSC = 48-1; |
||||
TIM2->CR1 = TIM_CR1_CEN; |
||||
TIM2->EGR = TIM_EGR_UG; |
||||
// use TIM2->CNT to read
|
||||
|
||||
// enable USB
|
||||
usb_init(); |
||||
|
||||
// default to silent mode to prevent issues with Ford
|
||||
safety_set_mode(SAFETY_NOOUTPUT); |
||||
can_silent = ALL_CAN_SILENT; |
||||
can_init_all(); |
||||
|
||||
adc_init(); |
||||
|
||||
#ifdef PANDA |
||||
spi_init(); |
||||
#endif |
||||
|
||||
// set PWM
|
||||
fan_init(); |
||||
fan_set_speed(0); |
||||
|
||||
puts("**** INTERRUPTS ON ****\n"); |
||||
|
||||
__enable_irq(); |
||||
|
||||
// LED should keep on blinking all the time
|
||||
uint64_t cnt = 0; |
||||
|
||||
#ifdef PANDA |
||||
uint64_t marker = 0; |
||||
#define CURRENT_THRESHOLD 0xF00 |
||||
#define CLICKS 8 |
||||
#endif |
||||
|
||||
for (cnt=0;;cnt++) { |
||||
can_live = pending_can_live; |
||||
|
||||
#ifdef PANDA |
||||
int current = adc_get(ADCCHAN_CURRENT); |
||||
|
||||
switch (usb_power_mode) { |
||||
case USB_POWER_CLIENT: |
||||
if ((cnt-marker) >= CLICKS) { |
||||
if (!is_enumerated) { |
||||
puts("USBP: didn't enumerate, switching to CDP mode\n"); |
||||
// switch to CDP
|
||||
set_usb_power_mode(USB_POWER_CDP); |
||||
marker = cnt; |
||||
} |
||||
} |
||||
// keep resetting the timer if it's enumerated
|
||||
if (is_enumerated) { |
||||
marker = cnt; |
||||
} |
||||
break; |
||||
case USB_POWER_CDP: |
||||
// been CLICKS clicks since we switched to CDP
|
||||
if ((cnt-marker) >= CLICKS) { |
||||
// measure current draw, if positive and no enumeration, switch to DCP
|
||||
if (!is_enumerated && current < CURRENT_THRESHOLD) { |
||||
puts("USBP: no enumeration with current draw, switching to DCP mode\n"); |
||||
set_usb_power_mode(USB_POWER_DCP); |
||||
marker = cnt; |
||||
} |
||||
} |
||||
// keep resetting the timer if there's no current draw in CDP
|
||||
if (current >= CURRENT_THRESHOLD) { |
||||
marker = cnt; |
||||
} |
||||
break; |
||||
case USB_POWER_DCP: |
||||
// been at least CLICKS clicks since we switched to DCP
|
||||
if ((cnt-marker) >= CLICKS) { |
||||
// if no current draw, switch back to CDP
|
||||
if (current >= CURRENT_THRESHOLD) { |
||||
puts("USBP: no current draw, switching back to CDP mode\n"); |
||||
set_usb_power_mode(USB_POWER_CDP); |
||||
marker = cnt; |
||||
} |
||||
} |
||||
// keep resetting the timer if there's current draw in DCP
|
||||
if (current < CURRENT_THRESHOLD) { |
||||
marker = cnt; |
||||
} |
||||
break; |
||||
} |
||||
|
||||
// ~0x9a = 500 ma
|
||||
/*puth(current);
|
||||
puts("\n");*/ |
||||
#endif |
||||
|
||||
// reset this every 16th pass
|
||||
if ((cnt&0xF) == 0) pending_can_live = 0; |
||||
|
||||
#ifdef DEBUG |
||||
puts("** blink "); |
||||
puth(can_rx_q.r_ptr); puts(" "); puth(can_rx_q.w_ptr); puts(" "); |
||||
puth(can_tx1_q.r_ptr); puts(" "); puth(can_tx1_q.w_ptr); puts(" "); |
||||
puth(can_tx2_q.r_ptr); puts(" "); puth(can_tx2_q.w_ptr); puts("\n"); |
||||
#endif |
||||
|
||||
// set green LED to be controls allowed
|
||||
set_led(LED_GREEN, controls_allowed); |
||||
|
||||
// blink the red LED
|
||||
int div_mode = ((usb_power_mode == USB_POWER_DCP) ? 4 : 1); |
||||
|
||||
for (int div_mode_loop = 0; div_mode_loop < div_mode; div_mode_loop++) { |
||||
for (int fade = 0; fade < 1024; fade += 8) { |
||||
for (int i = 0; i < 128/div_mode; i++) { |
||||
set_led(LED_RED, 0); |
||||
if (fade < 512) { delay(512-fade); } else { delay(fade-512); } |
||||
set_led(LED_RED, 1); |
||||
if (fade < 512) { delay(fade); } else { delay(1024-fade); } |
||||
} |
||||
} |
||||
} |
||||
|
||||
// turn off the blue LED, turned on by CAN
|
||||
#ifdef PANDA |
||||
set_led(LED_BLUE, 0); |
||||
#endif |
||||
} |
||||
|
||||
return 0; |
||||
} |
@ -0,0 +1,13 @@ |
||||
#define PROVISION_CHUNK_LEN 0x20 |
||||
|
||||
// WiFi SSID = 0x0 - 0x10
|
||||
// WiFi password = 0x10 - 0x1C
|
||||
// SHA1 checksum = 0x1C - 0x20
|
||||
|
||||
void get_provision_chunk(uint8_t *resp) { |
||||
memcpy(resp, (void *)0x1fff79e0, PROVISION_CHUNK_LEN); |
||||
if (memcmp(resp, "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff", 0x20) == 0) { |
||||
memcpy(resp, "unprovisioned\x00\x00\x00testing123\x00\x00\xa3\xa6\x99\xec", 0x20); |
||||
} |
||||
} |
||||
|
@ -0,0 +1,73 @@ |
||||
void safety_rx_hook(CAN_FIFOMailBox_TypeDef *to_push); |
||||
int safety_tx_hook(CAN_FIFOMailBox_TypeDef *to_send); |
||||
int safety_tx_lin_hook(int lin_num, uint8_t *data, int len); |
||||
|
||||
typedef void (*safety_hook_init)(); |
||||
typedef void (*rx_hook)(CAN_FIFOMailBox_TypeDef *to_push); |
||||
typedef int (*tx_hook)(CAN_FIFOMailBox_TypeDef *to_send); |
||||
typedef int (*tx_lin_hook)(int lin_num, uint8_t *data, int len); |
||||
|
||||
typedef struct { |
||||
safety_hook_init init; |
||||
rx_hook rx; |
||||
tx_hook tx; |
||||
tx_lin_hook tx_lin; |
||||
} safety_hooks; |
||||
|
||||
// This can be set by the safety hooks.
|
||||
int controls_allowed = 0; |
||||
|
||||
// Include the actual safety policies.
|
||||
#include "safety/safety_defaults.h" |
||||
#include "safety/safety_honda.h" |
||||
#include "safety/safety_toyota.h" |
||||
#include "safety/safety_elm327.h" |
||||
|
||||
const safety_hooks *current_hooks = &nooutput_hooks; |
||||
|
||||
void safety_rx_hook(CAN_FIFOMailBox_TypeDef *to_push){ |
||||
current_hooks->rx(to_push); |
||||
} |
||||
|
||||
int safety_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) { |
||||
return current_hooks->tx(to_send); |
||||
} |
||||
|
||||
int safety_tx_lin_hook(int lin_num, uint8_t *data, int len){ |
||||
return current_hooks->tx_lin(lin_num, data, len); |
||||
} |
||||
|
||||
typedef struct { |
||||
uint16_t id; |
||||
const safety_hooks *hooks; |
||||
} safety_hook_config; |
||||
|
||||
#define SAFETY_NOOUTPUT 0 |
||||
#define SAFETY_HONDA 1 |
||||
#define SAFETY_TOYOTA 2 |
||||
#define SAFETY_TOYOTA_NOLIMITS 0x1336 |
||||
#define SAFETY_ALLOUTPUT 0x1337 |
||||
#define SAFETY_ELM327 0xE327 |
||||
|
||||
const safety_hook_config safety_hook_registry[] = { |
||||
{SAFETY_NOOUTPUT, &nooutput_hooks}, |
||||
{SAFETY_HONDA, &honda_hooks}, |
||||
{SAFETY_TOYOTA, &toyota_hooks}, |
||||
{SAFETY_TOYOTA_NOLIMITS, &toyota_nolimits_hooks}, |
||||
{SAFETY_ALLOUTPUT, &alloutput_hooks}, |
||||
{SAFETY_ELM327, &elm327_hooks}, |
||||
}; |
||||
|
||||
#define HOOK_CONFIG_COUNT (sizeof(safety_hook_registry)/sizeof(safety_hook_config)) |
||||
|
||||
int safety_set_mode(uint16_t mode) { |
||||
for (int i = 0; i < HOOK_CONFIG_COUNT; i++) { |
||||
if (safety_hook_registry[i].id == mode) { |
||||
current_hooks = safety_hook_registry[i].hooks; |
||||
if (current_hooks->init) current_hooks->init(); |
||||
return 0; |
||||
} |
||||
} |
||||
return -1; |
||||
} |
||||
|
@ -0,0 +1,44 @@ |
||||
void default_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {} |
||||
|
||||
// *** no output safety mode ***
|
||||
|
||||
static void nooutput_init() { |
||||
controls_allowed = 0; |
||||
} |
||||
|
||||
static int nooutput_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) { |
||||
return false; |
||||
} |
||||
|
||||
static int nooutput_tx_lin_hook(int lin_num, uint8_t *data, int len) { |
||||
return false; |
||||
} |
||||
|
||||
const safety_hooks nooutput_hooks = { |
||||
.init = nooutput_init, |
||||
.rx = default_rx_hook, |
||||
.tx = nooutput_tx_hook, |
||||
.tx_lin = nooutput_tx_lin_hook, |
||||
}; |
||||
|
||||
// *** all output safety mode ***
|
||||
|
||||
static void alloutput_init() { |
||||
controls_allowed = 1; |
||||
} |
||||
|
||||
static int alloutput_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) { |
||||
return true; |
||||
} |
||||
|
||||
static int alloutput_tx_lin_hook(int lin_num, uint8_t *data, int len) { |
||||
return true; |
||||
} |
||||
|
||||
const safety_hooks alloutput_hooks = { |
||||
.init = alloutput_init, |
||||
.rx = default_rx_hook, |
||||
.tx = alloutput_tx_hook, |
||||
.tx_lin = alloutput_tx_lin_hook, |
||||
}; |
||||
|
@ -0,0 +1,39 @@ |
||||
static void elm327_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {} |
||||
|
||||
static int elm327_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) { |
||||
//All ELM traffic must appear on CAN0
|
||||
if(((to_send->RDTR >> 4) & 0xf) != 0) return 0; |
||||
//All ISO 15765-4 messages must be 8 bytes long
|
||||
if((to_send->RDTR & 0xf) != 8) return 0; |
||||
|
||||
if(to_send->RIR & 4){ |
||||
uint32_t addr = to_send->RIR >> 3; |
||||
//Check valid 29 bit send addresses for ISO 15765-4
|
||||
if(!(addr == 0x18DB33F1 || (addr & 0x1FFF00FF) == 0x18DA00F1)) return 0; |
||||
} else { |
||||
uint32_t addr = to_send->RIR >> 21; |
||||
//Check valid 11 bit send addresses for ISO 15765-4
|
||||
if(!(addr == 0x7DF || (addr & 0x7F8) == 0x7E0)) return 0; |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
static int elm327_tx_lin_hook(int lin_num, uint8_t *data, int len) { |
||||
if(lin_num != 0) return false; //Only operate on LIN 0, aka serial 2
|
||||
if(len < 5 || len > 11) return false; //Valid KWP size
|
||||
if(!((data[0] & 0xF8) == 0xC0 && (data[0] & 0x07) > 0 && |
||||
data[1] == 0x33 && data[2] == 0xF1)) return false; //Bad msg
|
||||
return true; |
||||
} |
||||
|
||||
static void elm327_init() { |
||||
controls_allowed = 1; |
||||
} |
||||
|
||||
const safety_hooks elm327_hooks = { |
||||
.init = elm327_init, |
||||
.rx = elm327_rx_hook, |
||||
.tx = elm327_tx_hook, |
||||
.tx_lin = elm327_tx_lin_hook, |
||||
}; |
@ -0,0 +1,128 @@ |
||||
// board enforces
|
||||
// in-state
|
||||
// accel set/resume
|
||||
// out-state
|
||||
// cancel button
|
||||
// accel rising edge
|
||||
// brake rising edge
|
||||
// brake > 0mph
|
||||
|
||||
// these are set in the Honda safety hooks...this is the wrong place
|
||||
int gas_interceptor_detected = 0; |
||||
int brake_prev = 0; |
||||
int gas_prev = 0; |
||||
int gas_interceptor_prev = 0; |
||||
int ego_speed = 0; |
||||
|
||||
static void honda_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) { |
||||
|
||||
// sample speed
|
||||
if ((to_push->RIR>>21) == 0x158) { |
||||
// first 2 bytes
|
||||
ego_speed = to_push->RDLR & 0xFFFF; |
||||
} |
||||
|
||||
// state machine to enter and exit controls
|
||||
// 0x1A6 for the ILX, 0x296 for the Civic Touring
|
||||
if ((to_push->RIR>>21) == 0x1A6 || (to_push->RIR>>21) == 0x296) { |
||||
int buttons = (to_push->RDLR & 0xE0) >> 5; |
||||
if (buttons == 4 || buttons == 3) { |
||||
controls_allowed = 1; |
||||
} else if (buttons == 2) { |
||||
controls_allowed = 0; |
||||
} |
||||
} |
||||
|
||||
// exit controls on rising edge of brake press or on brake press when
|
||||
// speed > 0
|
||||
if ((to_push->RIR>>21) == 0x17C) { |
||||
// bit 53
|
||||
int brake = to_push->RDHR & 0x200000; |
||||
if (brake && (!(brake_prev) || ego_speed)) { |
||||
controls_allowed = 0; |
||||
} |
||||
brake_prev = brake; |
||||
} |
||||
|
||||
// exit controls on rising edge of gas press if interceptor
|
||||
if ((to_push->RIR>>21) == 0x201) { |
||||
gas_interceptor_detected = 1; |
||||
int gas_interceptor = ((to_push->RDLR & 0xFF) << 8) | ((to_push->RDLR & 0xFF00) >> 8); |
||||
if ((gas_interceptor > 328) && (gas_interceptor_prev <= 328)) { |
||||
controls_allowed = 0; |
||||
} |
||||
gas_interceptor_prev = gas_interceptor; |
||||
} |
||||
|
||||
// exit controls on rising edge of gas press if no interceptor
|
||||
if (!gas_interceptor_detected) { |
||||
if ((to_push->RIR>>21) == 0x17C) { |
||||
int gas = to_push->RDLR & 0xFF; |
||||
if (gas && !(gas_prev)) { |
||||
controls_allowed = 0; |
||||
} |
||||
gas_prev = gas; |
||||
} |
||||
} |
||||
} |
||||
|
||||
// all commands: gas, brake and steering
|
||||
// if controls_allowed and no pedals pressed
|
||||
// allow all commands up to limit
|
||||
// else
|
||||
// block all commands that produce actuation
|
||||
|
||||
static int honda_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) { |
||||
|
||||
// disallow actuator commands if gas or brake (with vehicle moving) are pressed
|
||||
// and the the latching controls_allowed flag is True
|
||||
int pedal_pressed = gas_prev || gas_interceptor_prev || (brake_prev && ego_speed); |
||||
int current_controls_allowed = controls_allowed && !(pedal_pressed); |
||||
|
||||
// BRAKE: safety check
|
||||
if ((to_send->RIR>>21) == 0x1FA) { |
||||
if (current_controls_allowed) { |
||||
if ((to_send->RDLR & 0xFFFFFF3F) != to_send->RDLR) return 0; |
||||
} else { |
||||
if ((to_send->RDLR & 0xFFFF0000) != to_send->RDLR) return 0; |
||||
} |
||||
} |
||||
|
||||
// STEER: safety check
|
||||
if ((to_send->RIR>>21) == 0xE4 || (to_send->RIR>>21) == 0x194) { |
||||
if (current_controls_allowed) { |
||||
// all messages are fine here
|
||||
} else { |
||||
if ((to_send->RDLR & 0xFFFF0000) != to_send->RDLR) return 0; |
||||
} |
||||
} |
||||
|
||||
// GAS: safety check
|
||||
if ((to_send->RIR>>21) == 0x200) { |
||||
if (current_controls_allowed) { |
||||
// all messages are fine here
|
||||
} else { |
||||
if ((to_send->RDLR & 0xFFFF0000) != to_send->RDLR) return 0; |
||||
} |
||||
} |
||||
|
||||
// 1 allows the message through
|
||||
return true; |
||||
} |
||||
|
||||
static int honda_tx_lin_hook(int lin_num, uint8_t *data, int len) { |
||||
// TODO: add safety if using LIN
|
||||
return true; |
||||
} |
||||
|
||||
static void honda_init() { |
||||
controls_allowed = 0; |
||||
} |
||||
|
||||
const safety_hooks honda_hooks = { |
||||
.init = honda_init, |
||||
.rx = honda_rx_hook, |
||||
.tx = honda_tx_hook, |
||||
.tx_lin = honda_tx_lin_hook, |
||||
}; |
||||
|
@ -0,0 +1,179 @@ |
||||
// track the torque measured for limiting
|
||||
int16_t torque_meas[3] = {0, 0, 0}; // last 3 motor torques produced by the eps
|
||||
int16_t torque_meas_min = 0, torque_meas_max = 0; |
||||
|
||||
// global torque limit
|
||||
const int32_t MAX_TORQUE = 1500; // max torque cmd allowed ever
|
||||
|
||||
// rate based torque limit + stay within actually applied
|
||||
// packet is sent at 100hz, so this limit is 1000/sec
|
||||
const int32_t MAX_RATE_UP = 10; // ramp up slow
|
||||
const int32_t MAX_RATE_DOWN = 25; // ramp down fast
|
||||
const int32_t MAX_TORQUE_ERROR = 500; // max torque cmd in excess of torque motor
|
||||
|
||||
// real time torque limit to prevent controls spamming
|
||||
// the real time limit is 1500/sec
|
||||
const int32_t MAX_RT_DELTA = 375; // max delta torque allowed for real time checks
|
||||
const int32_t RT_INTERVAL = 250000; // 250ms between real time checks
|
||||
|
||||
// longitudinal limits
|
||||
const int16_t MAX_ACCEL = 1500; // 1.5 m/s2
|
||||
const int16_t MIN_ACCEL = -3000; // 3.0 m/s2
|
||||
|
||||
// global actuation limit state
|
||||
int actuation_limits = 1; // by default steer limits are imposed
|
||||
|
||||
// state of torque limits
|
||||
int16_t desired_torque_last = 0; // last desired steer torque
|
||||
int16_t rt_torque_last = 0; // last desired torque for real time check
|
||||
uint32_t ts_last = 0; |
||||
|
||||
static void toyota_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) { |
||||
// get eps motor torque (0.66 factor in dbc)
|
||||
if ((to_push->RIR>>21) == 0x260) { |
||||
int16_t torque_meas_new = (((to_push->RDHR) & 0xFF00) | ((to_push->RDHR >> 16) & 0xFF)); |
||||
|
||||
// increase torque_meas by 1 to be conservative on rounding
|
||||
torque_meas_new = (torque_meas_new / 3 + (torque_meas_new > 0 ? 1 : -1)) * 2; |
||||
|
||||
// shift the array
|
||||
for (int i = sizeof(torque_meas)/sizeof(torque_meas[0]) - 1; i > 0; i--) { |
||||
torque_meas[i] = torque_meas[i-1]; |
||||
} |
||||
torque_meas[0] = torque_meas_new; |
||||
|
||||
// get the minimum and maximum measured torque over the last 3 frames
|
||||
torque_meas_min = torque_meas_max = torque_meas[0]; |
||||
for (int i = 1; i < sizeof(torque_meas)/sizeof(torque_meas[0]); i++) { |
||||
if (torque_meas[i] < torque_meas_min) torque_meas_min = torque_meas[i]; |
||||
if (torque_meas[i] > torque_meas_max) torque_meas_max = torque_meas[i]; |
||||
} |
||||
} |
||||
|
||||
// exit controls on ACC off
|
||||
if ((to_push->RIR>>21) == 0x1D2) { |
||||
// 4 bits: 55-52
|
||||
if (to_push->RDHR & 0xF00000) { |
||||
controls_allowed = 1; |
||||
} else { |
||||
controls_allowed = 0; |
||||
} |
||||
} |
||||
} |
||||
|
||||
static int toyota_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) { |
||||
|
||||
// Check if msg is sent on BUS 0
|
||||
if (((to_send->RDTR >> 4) & 0xF) == 0) { |
||||
|
||||
// ACCEL: safety check on byte 1-2
|
||||
if ((to_send->RIR>>21) == 0x343) { |
||||
int16_t desired_accel = ((to_send->RDLR & 0xFF) << 8) | ((to_send->RDLR >> 8) & 0xFF); |
||||
if (controls_allowed && actuation_limits) { |
||||
if ((desired_accel > MAX_ACCEL) || (desired_accel < MIN_ACCEL)) { |
||||
return 0; |
||||
} |
||||
} else if (!controls_allowed && (desired_accel != 0)) { |
||||
return 0; |
||||
} |
||||
} |
||||
|
||||
// STEER: safety check on bytes 2-3
|
||||
if ((to_send->RIR>>21) == 0x2E4) { |
||||
int16_t desired_torque = (to_send->RDLR & 0xFF00) | ((to_send->RDLR >> 16) & 0xFF); |
||||
int16_t violation = 0; |
||||
|
||||
uint32_t ts = TIM2->CNT; |
||||
|
||||
// only check if controls are allowed and actuation_limits are imposed
|
||||
if (controls_allowed && actuation_limits) { |
||||
|
||||
// *** global torque limit check ***
|
||||
if (desired_torque < -MAX_TORQUE) violation = 1; |
||||
if (desired_torque > MAX_TORQUE) violation = 1; |
||||
|
||||
|
||||
// *** torque rate limit check ***
|
||||
int16_t highest_allowed_torque = max(desired_torque_last, 0) + MAX_RATE_UP; |
||||
int16_t lowest_allowed_torque = min(desired_torque_last, 0) - MAX_RATE_UP; |
||||
|
||||
// if we've exceeded the applied torque, we must start moving toward 0
|
||||
highest_allowed_torque = min(highest_allowed_torque, max(desired_torque_last - MAX_RATE_DOWN, max(torque_meas_max, 0) + MAX_TORQUE_ERROR)); |
||||
lowest_allowed_torque = max(lowest_allowed_torque, min(desired_torque_last + MAX_RATE_DOWN, min(torque_meas_min, 0) - MAX_TORQUE_ERROR)); |
||||
|
||||
// check for violation
|
||||
if ((desired_torque < lowest_allowed_torque) || (desired_torque > highest_allowed_torque)) { |
||||
violation = 1; |
||||
} |
||||
|
||||
// used next time
|
||||
desired_torque_last = desired_torque; |
||||
|
||||
|
||||
// *** torque real time rate limit check ***
|
||||
int16_t highest_rt_torque = max(rt_torque_last, 0) + MAX_RT_DELTA; |
||||
int16_t lowest_rt_torque = min(rt_torque_last, 0) - MAX_RT_DELTA; |
||||
|
||||
// check for violation
|
||||
if ((desired_torque < lowest_rt_torque) || (desired_torque > highest_rt_torque)) { |
||||
violation = 1; |
||||
} |
||||
|
||||
// every RT_INTERVAL set the new limits
|
||||
uint32_t ts_elapsed = ts > ts_last ? ts - ts_last : (0xFFFFFFFF - ts_last) + 1 + ts; |
||||
if (ts_elapsed > RT_INTERVAL) { |
||||
rt_torque_last = desired_torque; |
||||
ts_last = ts; |
||||
} |
||||
} |
||||
|
||||
// no torque if controls is not allowed
|
||||
if (!controls_allowed && (desired_torque != 0)) { |
||||
violation = 1; |
||||
} |
||||
|
||||
// reset to 0 if either controls is not allowed or there's a violation
|
||||
if (violation || !controls_allowed) { |
||||
desired_torque_last = 0; |
||||
rt_torque_last = 0; |
||||
ts_last = ts; |
||||
} |
||||
|
||||
if (violation) { |
||||
return false; |
||||
} |
||||
} |
||||
} |
||||
|
||||
// 1 allows the message through
|
||||
return true; |
||||
} |
||||
|
||||
static int toyota_tx_lin_hook(int lin_num, uint8_t *data, int len) { |
||||
// TODO: add safety if using LIN
|
||||
return true; |
||||
} |
||||
|
||||
static void toyota_init() { |
||||
controls_allowed = 0; |
||||
actuation_limits = 1; |
||||
} |
||||
|
||||
const safety_hooks toyota_hooks = { |
||||
.init = toyota_init, |
||||
.rx = toyota_rx_hook, |
||||
.tx = toyota_tx_hook, |
||||
.tx_lin = toyota_tx_lin_hook, |
||||
}; |
||||
|
||||
static void toyota_nolimits_init() { |
||||
controls_allowed = 0; |
||||
actuation_limits = 0; |
||||
} |
||||
|
||||
const safety_hooks toyota_nolimits_hooks = { |
||||
.init = toyota_nolimits_init, |
||||
.rx = toyota_rx_hook, |
||||
.tx = toyota_tx_hook, |
||||
.tx_lin = toyota_tx_lin_hook, |
||||
}; |
@ -0,0 +1,186 @@ |
||||
// 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; |
||||
} |
||||
|
||||
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; |
||||
|
||||
// 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); |
||||
} |
||||
} |
||||
|
@ -0,0 +1,511 @@ |
||||
/** |
||||
****************************************************************************** |
||||
* @file startup_stm32f205xx.s
|
||||
* @author MCD Application Team
|
||||
* @version V2.1.2
|
||||
* @date 29-June-2016
|
||||
* @brief STM32F205xx Devices vector table for Atollic TrueSTUDIO toolchain.
|
||||
* This module performs: |
||||
* - Set the initial SP |
||||
* - Set the initial PC == Reset_Handler, |
||||
* - Set the vector table entries with the exceptions ISR address |
||||
* - Branches to main in the C library (which eventually |
||||
* calls main()). |
||||
* After Reset the Cortex-M3 processor is in Thread mode, |
||||
* priority is Privileged, and the Stack is set to Main. |
||||
****************************************************************************** |
||||
* @attention
|
||||
* |
||||
* <h2><center>© COPYRIGHT 2016 STMicroelectronics</center></h2>
|
||||
* |
||||
* Redistribution and use in source and binary forms, with or without modification, |
||||
* are permitted provided that the following conditions are met: |
||||
* 1. Redistributions of source code must retain the above copyright notice, |
||||
* this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, |
||||
* this list of conditions and the following disclaimer in the documentation |
||||
* and/or other materials provided with the distribution. |
||||
* 3. Neither the name of STMicroelectronics nor the names of its contributors |
||||
* may be used to endorse or promote products derived from this software |
||||
* without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE |
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
* |
||||
****************************************************************************** |
||||
*/ |
||||
|
||||
.syntax unified
|
||||
.cpu cortex-m3 |
||||
.thumb |
||||
|
||||
.global g_pfnVectors
|
||||
.global Default_Handler
|
||||
|
||||
/* start address for the initialization values of the .data section.
|
||||
defined in linker script */ |
||||
.word _sidata
|
||||
/* start address for the .data section. defined in linker script */
|
||||
.word _sdata
|
||||
/* end address for the .data section. defined in linker script */ |
||||
.word _edata
|
||||
/* start address for the .bss section. defined in linker script */ |
||||
.word _sbss
|
||||
/* end address for the .bss section. defined in linker script */ |
||||
.word _ebss
|
||||
/* stack used for SystemInit_ExtMemCtl; always internal RAM used */ |
||||
|
||||
/** |
||||
* @brief This is the code that gets called when the processor first
|
||||
* starts execution following a reset event. Only the absolutely |
||||
* necessary set is performed, after which the application |
||||
* supplied main() routine is called.
|
||||
* @param None
|
||||
* @retval : None
|
||||
*/ |
||||
|
||||
.section .text.Reset_Handler |
||||
.weak Reset_Handler
|
||||
.type Reset_Handler, %function |
||||
Reset_Handler:
|
||||
ldr sp, =_estack /* set stack pointer */ |
||||
bl __initialize_hardware_early |
||||
|
||||
/* Copy the data segment initializers from flash to SRAM */ |
||||
movs r1, #0 |
||||
b LoopCopyDataInit |
||||
|
||||
CopyDataInit: |
||||
ldr r3, =_sidata |
||||
ldr r3, [r3, r1] |
||||
str r3, [r0, r1] |
||||
adds r1, r1, #4 |
||||
|
||||
LoopCopyDataInit: |
||||
ldr r0, =_sdata |
||||
ldr r3, =_edata |
||||
adds r2, r0, r1 |
||||
cmp r2, r3 |
||||
bcc CopyDataInit |
||||
ldr r2, =_sbss |
||||
b LoopFillZerobss |
||||
/* Zero fill the bss segment. */ |
||||
FillZerobss: |
||||
movs r3, #0 |
||||
str r3, [r2], #4 |
||||
|
||||
LoopFillZerobss: |
||||
ldr r3, = _ebss |
||||
cmp r2, r3 |
||||
bcc FillZerobss |
||||
|
||||
/* Call the clock system initialization function.*/ |
||||
/*bl SystemInit */ |
||||
/* Call static constructors */ |
||||
/*bl __libc_init_array*/ |
||||
/* Call the application's entry point.*/ |
||||
bl main |
||||
bx lr
|
||||
.size Reset_Handler, .-Reset_Handler |
||||
|
||||
/** |
||||
* @brief This is the code that gets called when the processor receives an
|
||||
* unexpected interrupt. This simply enters an infinite loop, preserving |
||||
* the system state for examination by a debugger. |
||||
* @param None
|
||||
* @retval None
|
||||
*/ |
||||
.section .text.Default_Handler,"ax",%progbits |
||||
Default_Handler: |
||||
Infinite_Loop: |
||||
b Infinite_Loop |
||||
.size Default_Handler, .-Default_Handler |
||||
/****************************************************************************** |
||||
* |
||||
* The minimal vector table for a Cortex M3. Note that the proper constructs |
||||
* must be placed on this to ensure that it ends up at physical address |
||||
* 0x0000.0000. |
||||
*
|
||||
*******************************************************************************/ |
||||
.section .isr_vector,"a",%progbits |
||||
.type g_pfnVectors, %object |
||||
.size g_pfnVectors, .-g_pfnVectors |
||||
|
||||
|
||||
|
||||
g_pfnVectors: |
||||
.word _estack
|
||||
.word Reset_Handler
|
||||
|
||||
.word NMI_Handler
|
||||
.word HardFault_Handler
|
||||
.word MemManage_Handler
|
||||
.word BusFault_Handler
|
||||
.word UsageFault_Handler
|
||||
.word 0
|
||||
.word 0
|
||||
.word 0
|
||||
.word 0
|
||||
.word SVC_Handler
|
||||
.word DebugMon_Handler
|
||||
.word 0
|
||||
.word PendSV_Handler
|
||||
.word SysTick_Handler
|
||||
|
||||
/* External Interrupts */ |
||||
.word WWDG_IRQHandler /* Window WatchDog */ |
||||
.word PVD_IRQHandler /* PVD through EXTI Line detection */ |
||||
.word TAMP_STAMP_IRQHandler /* Tamper and TimeStamps through the EXTI line */ |
||||
.word RTC_WKUP_IRQHandler /* RTC Wakeup through the EXTI line */ |
||||
.word FLASH_IRQHandler /* FLASH */ |
||||
.word RCC_IRQHandler /* RCC */ |
||||
.word EXTI0_IRQHandler /* EXTI Line0 */ |
||||
.word EXTI1_IRQHandler /* EXTI Line1 */ |
||||
.word EXTI2_IRQHandler /* EXTI Line2 */ |
||||
.word EXTI3_IRQHandler /* EXTI Line3 */ |
||||
.word EXTI4_IRQHandler /* EXTI Line4 */ |
||||
.word DMA1_Stream0_IRQHandler /* DMA1 Stream 0 */ |
||||
.word DMA1_Stream1_IRQHandler /* DMA1 Stream 1 */ |
||||
.word DMA1_Stream2_IRQHandler /* DMA1 Stream 2 */ |
||||
.word DMA1_Stream3_IRQHandler /* DMA1 Stream 3 */ |
||||
.word DMA1_Stream4_IRQHandler /* DMA1 Stream 4 */ |
||||
.word DMA1_Stream5_IRQHandler /* DMA1 Stream 5 */ |
||||
.word DMA1_Stream6_IRQHandler /* DMA1 Stream 6 */ |
||||
.word ADC_IRQHandler /* ADC1, ADC2 and ADC3s */ |
||||
.word CAN1_TX_IRQHandler /* CAN1 TX */ |
||||
.word CAN1_RX0_IRQHandler /* CAN1 RX0 */ |
||||
.word CAN1_RX1_IRQHandler /* CAN1 RX1 */ |
||||
.word CAN1_SCE_IRQHandler /* CAN1 SCE */ |
||||
.word EXTI9_5_IRQHandler /* External Line[9:5]s */ |
||||
.word TIM1_BRK_TIM9_IRQHandler /* TIM1 Break and TIM9 */ |
||||
.word TIM1_UP_TIM10_IRQHandler /* TIM1 Update and TIM10 */ |
||||
.word TIM1_TRG_COM_TIM11_IRQHandler /* TIM1 Trigger and Commutation and TIM11 */ |
||||
.word TIM1_CC_IRQHandler /* TIM1 Capture Compare */ |
||||
.word TIM2_IRQHandler /* TIM2 */ |
||||
.word TIM3_IRQHandler /* TIM3 */ |
||||
.word TIM4_IRQHandler /* TIM4 */ |
||||
.word I2C1_EV_IRQHandler /* I2C1 Event */ |
||||
.word I2C1_ER_IRQHandler /* I2C1 Error */ |
||||
.word I2C2_EV_IRQHandler /* I2C2 Event */ |
||||
.word I2C2_ER_IRQHandler /* I2C2 Error */ |
||||
.word SPI1_IRQHandler /* SPI1 */ |
||||
.word SPI2_IRQHandler /* SPI2 */ |
||||
.word USART1_IRQHandler /* USART1 */ |
||||
.word USART2_IRQHandler /* USART2 */ |
||||
.word USART3_IRQHandler /* USART3 */ |
||||
.word EXTI15_10_IRQHandler /* External Line[15:10]s */ |
||||
.word RTC_Alarm_IRQHandler /* RTC Alarm (A and B) through EXTI Line */ |
||||
.word OTG_FS_WKUP_IRQHandler /* USB OTG FS Wakeup through EXTI line */ |
||||
.word TIM8_BRK_TIM12_IRQHandler /* TIM8 Break and TIM12 */ |
||||
.word TIM8_UP_TIM13_IRQHandler /* TIM8 Update and TIM13 */ |
||||
.word TIM8_TRG_COM_TIM14_IRQHandler /* TIM8 Trigger and Commutation and TIM14 */ |
||||
.word TIM8_CC_IRQHandler /* TIM8 Capture Compare */ |
||||
.word DMA1_Stream7_IRQHandler /* DMA1 Stream7 */ |
||||
.word FSMC_IRQHandler /* FSMC */ |
||||
.word SDIO_IRQHandler /* SDIO */ |
||||
.word TIM5_IRQHandler /* TIM5 */ |
||||
.word SPI3_IRQHandler /* SPI3 */ |
||||
.word UART4_IRQHandler /* UART4 */ |
||||
.word UART5_IRQHandler /* UART5 */ |
||||
.word TIM6_DAC_IRQHandler /* TIM6 and DAC1&2 underrun errors */ |
||||
.word TIM7_IRQHandler /* TIM7 */ |
||||
.word DMA2_Stream0_IRQHandler /* DMA2 Stream 0 */ |
||||
.word DMA2_Stream1_IRQHandler /* DMA2 Stream 1 */ |
||||
.word DMA2_Stream2_IRQHandler /* DMA2 Stream 2 */ |
||||
.word DMA2_Stream3_IRQHandler /* DMA2 Stream 3 */ |
||||
.word DMA2_Stream4_IRQHandler /* DMA2 Stream 4 */ |
||||
.word 0 /* Reserved */ |
||||
.word 0 /* Reserved */ |
||||
.word CAN2_TX_IRQHandler /* CAN2 TX */ |
||||
.word CAN2_RX0_IRQHandler /* CAN2 RX0 */ |
||||
.word CAN2_RX1_IRQHandler /* CAN2 RX1 */ |
||||
.word CAN2_SCE_IRQHandler /* CAN2 SCE */ |
||||
.word OTG_FS_IRQHandler /* USB OTG FS */ |
||||
.word DMA2_Stream5_IRQHandler /* DMA2 Stream 5 */ |
||||
.word DMA2_Stream6_IRQHandler /* DMA2 Stream 6 */ |
||||
.word DMA2_Stream7_IRQHandler /* DMA2 Stream 7 */ |
||||
.word USART6_IRQHandler /* USART6 */ |
||||
.word I2C3_EV_IRQHandler /* I2C3 event */ |
||||
.word I2C3_ER_IRQHandler /* I2C3 error */ |
||||
.word OTG_HS_EP1_OUT_IRQHandler /* USB OTG HS End Point 1 Out */ |
||||
.word OTG_HS_EP1_IN_IRQHandler /* USB OTG HS End Point 1 In */ |
||||
.word OTG_HS_WKUP_IRQHandler /* USB OTG HS Wakeup through EXTI */ |
||||
.word OTG_HS_IRQHandler /* USB OTG HS */ |
||||
.word 0 /* Reserved */ |
||||
.word 0 /* Reserved */ |
||||
.word HASH_RNG_IRQHandler /* Hash and Rng */ |
||||
|
||||
/******************************************************************************* |
||||
* |
||||
* Provide weak aliases for each Exception handler to the Default_Handler. |
||||
* As they are weak aliases, any function with the same name will override |
||||
* this definition. |
||||
*
|
||||
*******************************************************************************/ |
||||
.weak NMI_Handler
|
||||
.thumb_set NMI_Handler,Default_Handler |
||||
|
||||
.weak HardFault_Handler
|
||||
.thumb_set HardFault_Handler,Default_Handler |
||||
|
||||
.weak MemManage_Handler
|
||||
.thumb_set MemManage_Handler,Default_Handler |
||||
|
||||
.weak BusFault_Handler
|
||||
.thumb_set BusFault_Handler,Default_Handler |
||||
|
||||
.weak UsageFault_Handler
|
||||
.thumb_set UsageFault_Handler,Default_Handler |
||||
|
||||
.weak SVC_Handler
|
||||
.thumb_set SVC_Handler,Default_Handler |
||||
|
||||
.weak DebugMon_Handler
|
||||
.thumb_set DebugMon_Handler,Default_Handler |
||||
|
||||
.weak PendSV_Handler
|
||||
.thumb_set PendSV_Handler,Default_Handler |
||||
|
||||
.weak SysTick_Handler
|
||||
.thumb_set SysTick_Handler,Default_Handler |
||||
|
||||
.weak WWDG_IRQHandler
|
||||
.thumb_set WWDG_IRQHandler,Default_Handler |
||||
|
||||
.weak PVD_IRQHandler
|
||||
.thumb_set PVD_IRQHandler,Default_Handler |
||||
|
||||
.weak TAMP_STAMP_IRQHandler
|
||||
.thumb_set TAMP_STAMP_IRQHandler,Default_Handler |
||||
|
||||
.weak RTC_WKUP_IRQHandler
|
||||
.thumb_set RTC_WKUP_IRQHandler,Default_Handler |
||||
|
||||
.weak FLASH_IRQHandler
|
||||
.thumb_set FLASH_IRQHandler,Default_Handler |
||||
|
||||
.weak RCC_IRQHandler
|
||||
.thumb_set RCC_IRQHandler,Default_Handler |
||||
|
||||
.weak EXTI0_IRQHandler
|
||||
.thumb_set EXTI0_IRQHandler,Default_Handler |
||||
|
||||
.weak EXTI1_IRQHandler
|
||||
.thumb_set EXTI1_IRQHandler,Default_Handler |
||||
|
||||
.weak EXTI2_IRQHandler
|
||||
.thumb_set EXTI2_IRQHandler,Default_Handler
|
||||
|
||||
.weak EXTI3_IRQHandler
|
||||
.thumb_set EXTI3_IRQHandler,Default_Handler |
||||
|
||||
.weak EXTI4_IRQHandler
|
||||
.thumb_set EXTI4_IRQHandler,Default_Handler |
||||
|
||||
.weak DMA1_Stream0_IRQHandler
|
||||
.thumb_set DMA1_Stream0_IRQHandler,Default_Handler |
||||
|
||||
.weak DMA1_Stream1_IRQHandler
|
||||
.thumb_set DMA1_Stream1_IRQHandler,Default_Handler |
||||
|
||||
.weak DMA1_Stream2_IRQHandler
|
||||
.thumb_set DMA1_Stream2_IRQHandler,Default_Handler |
||||
|
||||
.weak DMA1_Stream3_IRQHandler
|
||||
.thumb_set DMA1_Stream3_IRQHandler,Default_Handler
|
||||
|
||||
.weak DMA1_Stream4_IRQHandler
|
||||
.thumb_set DMA1_Stream4_IRQHandler,Default_Handler |
||||
|
||||
.weak DMA1_Stream5_IRQHandler
|
||||
.thumb_set DMA1_Stream5_IRQHandler,Default_Handler |
||||
|
||||
.weak DMA1_Stream6_IRQHandler
|
||||
.thumb_set DMA1_Stream6_IRQHandler,Default_Handler |
||||
|
||||
.weak ADC_IRQHandler
|
||||
.thumb_set ADC_IRQHandler,Default_Handler |
||||
|
||||
.weak CAN1_TX_IRQHandler
|
||||
.thumb_set CAN1_TX_IRQHandler,Default_Handler |
||||
|
||||
.weak CAN1_RX0_IRQHandler
|
||||
.thumb_set CAN1_RX0_IRQHandler,Default_Handler |
||||
|
||||
.weak CAN1_RX1_IRQHandler
|
||||
.thumb_set CAN1_RX1_IRQHandler,Default_Handler |
||||
|
||||
.weak CAN1_SCE_IRQHandler
|
||||
.thumb_set CAN1_SCE_IRQHandler,Default_Handler |
||||
|
||||
.weak EXTI9_5_IRQHandler
|
||||
.thumb_set EXTI9_5_IRQHandler,Default_Handler |
||||
|
||||
.weak TIM1_BRK_TIM9_IRQHandler
|
||||
.thumb_set TIM1_BRK_TIM9_IRQHandler,Default_Handler |
||||
|
||||
.weak TIM1_UP_TIM10_IRQHandler
|
||||
.thumb_set TIM1_UP_TIM10_IRQHandler,Default_Handler |
||||
|
||||
.weak TIM1_TRG_COM_TIM11_IRQHandler
|
||||
.thumb_set TIM1_TRG_COM_TIM11_IRQHandler,Default_Handler |
||||
|
||||
.weak TIM1_CC_IRQHandler
|
||||
.thumb_set TIM1_CC_IRQHandler,Default_Handler |
||||
|
||||
.weak TIM2_IRQHandler
|
||||
.thumb_set TIM2_IRQHandler,Default_Handler |
||||
|
||||
.weak TIM3_IRQHandler
|
||||
.thumb_set TIM3_IRQHandler,Default_Handler |
||||
|
||||
.weak TIM4_IRQHandler
|
||||
.thumb_set TIM4_IRQHandler,Default_Handler |
||||
|
||||
.weak I2C1_EV_IRQHandler
|
||||
.thumb_set I2C1_EV_IRQHandler,Default_Handler |
||||
|
||||
.weak I2C1_ER_IRQHandler
|
||||
.thumb_set I2C1_ER_IRQHandler,Default_Handler |
||||
|
||||
.weak I2C2_EV_IRQHandler
|
||||
.thumb_set I2C2_EV_IRQHandler,Default_Handler |
||||
|
||||
.weak I2C2_ER_IRQHandler
|
||||
.thumb_set I2C2_ER_IRQHandler,Default_Handler |
||||
|
||||
.weak SPI1_IRQHandler
|
||||
.thumb_set SPI1_IRQHandler,Default_Handler |
||||
|
||||
.weak SPI2_IRQHandler
|
||||
.thumb_set SPI2_IRQHandler,Default_Handler |
||||
|
||||
.weak USART1_IRQHandler
|
||||
.thumb_set USART1_IRQHandler,Default_Handler |
||||
|
||||
.weak USART2_IRQHandler
|
||||
.thumb_set USART2_IRQHandler,Default_Handler |
||||
|
||||
.weak USART3_IRQHandler
|
||||
.thumb_set USART3_IRQHandler,Default_Handler |
||||
|
||||
.weak EXTI15_10_IRQHandler
|
||||
.thumb_set EXTI15_10_IRQHandler,Default_Handler |
||||
|
||||
.weak RTC_Alarm_IRQHandler
|
||||
.thumb_set RTC_Alarm_IRQHandler,Default_Handler |
||||
|
||||
.weak OTG_FS_WKUP_IRQHandler
|
||||
.thumb_set OTG_FS_WKUP_IRQHandler,Default_Handler |
||||
|
||||
.weak TIM8_BRK_TIM12_IRQHandler
|
||||
.thumb_set TIM8_BRK_TIM12_IRQHandler,Default_Handler |
||||
|
||||
.weak TIM8_UP_TIM13_IRQHandler
|
||||
.thumb_set TIM8_UP_TIM13_IRQHandler,Default_Handler |
||||
|
||||
.weak TIM8_TRG_COM_TIM14_IRQHandler
|
||||
.thumb_set TIM8_TRG_COM_TIM14_IRQHandler,Default_Handler |
||||
|
||||
.weak TIM8_CC_IRQHandler
|
||||
.thumb_set TIM8_CC_IRQHandler,Default_Handler |
||||
|
||||
.weak DMA1_Stream7_IRQHandler
|
||||
.thumb_set DMA1_Stream7_IRQHandler,Default_Handler |
||||
|
||||
.weak FSMC_IRQHandler
|
||||
.thumb_set FSMC_IRQHandler,Default_Handler |
||||
|
||||
.weak SDIO_IRQHandler
|
||||
.thumb_set SDIO_IRQHandler,Default_Handler |
||||
|
||||
.weak TIM5_IRQHandler
|
||||
.thumb_set TIM5_IRQHandler,Default_Handler |
||||
|
||||
.weak SPI3_IRQHandler
|
||||
.thumb_set SPI3_IRQHandler,Default_Handler |
||||
|
||||
.weak UART4_IRQHandler
|
||||
.thumb_set UART4_IRQHandler,Default_Handler |
||||
|
||||
.weak UART5_IRQHandler
|
||||
.thumb_set UART5_IRQHandler,Default_Handler |
||||
|
||||
.weak TIM6_DAC_IRQHandler
|
||||
.thumb_set TIM6_DAC_IRQHandler,Default_Handler |
||||
|
||||
.weak TIM7_IRQHandler
|
||||
.thumb_set TIM7_IRQHandler,Default_Handler |
||||
|
||||
.weak DMA2_Stream0_IRQHandler
|
||||
.thumb_set DMA2_Stream0_IRQHandler,Default_Handler |
||||
|
||||
.weak DMA2_Stream1_IRQHandler
|
||||
.thumb_set DMA2_Stream1_IRQHandler,Default_Handler |
||||
|
||||
.weak DMA2_Stream2_IRQHandler
|
||||
.thumb_set DMA2_Stream2_IRQHandler,Default_Handler |
||||
|
||||
.weak DMA2_Stream3_IRQHandler
|
||||
.thumb_set DMA2_Stream3_IRQHandler,Default_Handler |
||||
|
||||
.weak DMA2_Stream4_IRQHandler
|
||||
.thumb_set DMA2_Stream4_IRQHandler,Default_Handler |
||||
|
||||
.weak CAN2_TX_IRQHandler
|
||||
.thumb_set CAN2_TX_IRQHandler,Default_Handler |
||||
|
||||
.weak CAN2_RX0_IRQHandler
|
||||
.thumb_set CAN2_RX0_IRQHandler,Default_Handler |
||||
|
||||
.weak CAN2_RX1_IRQHandler
|
||||
.thumb_set CAN2_RX1_IRQHandler,Default_Handler |
||||
|
||||
.weak CAN2_SCE_IRQHandler
|
||||
.thumb_set CAN2_SCE_IRQHandler,Default_Handler |
||||
|
||||
.weak OTG_FS_IRQHandler
|
||||
.thumb_set OTG_FS_IRQHandler,Default_Handler |
||||
|
||||
.weak DMA2_Stream5_IRQHandler
|
||||
.thumb_set DMA2_Stream5_IRQHandler,Default_Handler |
||||
|
||||
.weak DMA2_Stream6_IRQHandler
|
||||
.thumb_set DMA2_Stream6_IRQHandler,Default_Handler |
||||
|
||||
.weak DMA2_Stream7_IRQHandler
|
||||
.thumb_set DMA2_Stream7_IRQHandler,Default_Handler |
||||
|
||||
.weak USART6_IRQHandler
|
||||
.thumb_set USART6_IRQHandler,Default_Handler |
||||
|
||||
.weak I2C3_EV_IRQHandler
|
||||
.thumb_set I2C3_EV_IRQHandler,Default_Handler |
||||
|
||||
.weak I2C3_ER_IRQHandler
|
||||
.thumb_set I2C3_ER_IRQHandler,Default_Handler |
||||
|
||||
.weak OTG_HS_EP1_OUT_IRQHandler
|
||||
.thumb_set OTG_HS_EP1_OUT_IRQHandler,Default_Handler |
||||
|
||||
.weak OTG_HS_EP1_IN_IRQHandler
|
||||
.thumb_set OTG_HS_EP1_IN_IRQHandler,Default_Handler |
||||
|
||||
.weak OTG_HS_WKUP_IRQHandler
|
||||
.thumb_set OTG_HS_WKUP_IRQHandler,Default_Handler |
||||
|
||||
.weak OTG_HS_IRQHandler
|
||||
.thumb_set OTG_HS_IRQHandler,Default_Handler |
||||
|
||||
.weak HASH_RNG_IRQHandler
|
||||
.thumb_set HASH_RNG_IRQHandler,Default_Handler |
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ |
@ -0,0 +1,583 @@ |
||||
/** |
||||
****************************************************************************** |
||||
* @file startup_stm32f413xx.s
|
||||
* @author MCD Application Team
|
||||
* @version V2.6.0
|
||||
* @date 04-November-2016
|
||||
* @brief STM32F413xx Devices vector table for GCC based toolchains.
|
||||
* This module performs: |
||||
* - Set the initial SP |
||||
* - Set the initial PC == Reset_Handler, |
||||
* - Set the vector table entries with the exceptions ISR address |
||||
* - Branches to main in the C library (which eventually |
||||
* calls main()). |
||||
* After Reset the Cortex-M4 processor is in Thread mode, |
||||
* priority is Privileged, and the Stack is set to Main. |
||||
****************************************************************************** |
||||
* @attention
|
||||
* |
||||
* <h2><center>© COPYRIGHT 2016 STMicroelectronics</center></h2>
|
||||
* |
||||
* Redistribution and use in source and binary forms, with or without modification, |
||||
* are permitted provided that the following conditions are met: |
||||
* 1. Redistributions of source code must retain the above copyright notice, |
||||
* this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, |
||||
* this list of conditions and the following disclaimer in the documentation |
||||
* and/or other materials provided with the distribution. |
||||
* 3. Neither the name of STMicroelectronics nor the names of its contributors |
||||
* may be used to endorse or promote products derived from this software |
||||
* without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE |
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
* |
||||
****************************************************************************** |
||||
*/ |
||||
|
||||
.syntax unified
|
||||
.cpu cortex-m4 |
||||
.fpu softvfp
|
||||
.thumb |
||||
|
||||
.global g_pfnVectors
|
||||
.global Default_Handler
|
||||
|
||||
/* start address for the initialization values of the .data section.
|
||||
defined in linker script */ |
||||
.word _sidata
|
||||
/* start address for the .data section. defined in linker script */ |
||||
.word _sdata
|
||||
/* end address for the .data section. defined in linker script */ |
||||
.word _edata
|
||||
/* start address for the .bss section. defined in linker script */ |
||||
.word _sbss
|
||||
/* end address for the .bss section. defined in linker script */ |
||||
.word _ebss
|
||||
/* stack used for SystemInit_ExtMemCtl; always internal RAM used */ |
||||
|
||||
/** |
||||
* @brief This is the code that gets called when the processor first
|
||||
* starts execution following a reset event. Only the absolutely |
||||
* necessary set is performed, after which the application |
||||
* supplied main() routine is called.
|
||||
* @param None
|
||||
* @retval : None
|
||||
*/ |
||||
|
||||
.section .text.Reset_Handler |
||||
.weak Reset_Handler
|
||||
.type Reset_Handler, %function |
||||
Reset_Handler:
|
||||
ldr sp, =_estack /* set stack pointer */ |
||||
bl __initialize_hardware_early |
||||
|
||||
/* Copy the data segment initializers from flash to SRAM */ |
||||
movs r1, #0 |
||||
b LoopCopyDataInit |
||||
|
||||
CopyDataInit: |
||||
ldr r3, =_sidata |
||||
ldr r3, [r3, r1] |
||||
str r3, [r0, r1] |
||||
adds r1, r1, #4 |
||||
|
||||
LoopCopyDataInit: |
||||
ldr r0, =_sdata |
||||
ldr r3, =_edata |
||||
adds r2, r0, r1 |
||||
cmp r2, r3 |
||||
bcc CopyDataInit |
||||
ldr r2, =_sbss |
||||
b LoopFillZerobss |
||||
/* Zero fill the bss segment. */ |
||||
FillZerobss: |
||||
movs r3, #0 |
||||
str r3, [r2], #4 |
||||
|
||||
LoopFillZerobss: |
||||
ldr r3, = _ebss |
||||
cmp r2, r3 |
||||
bcc FillZerobss |
||||
|
||||
/* Call the clock system intitialization function.*/ |
||||
/* bl SystemInit */ |
||||
/* Call static constructors */ |
||||
/* bl __libc_init_array */ |
||||
/* Call the application's entry point.*/ |
||||
bl main |
||||
bx lr
|
||||
.size Reset_Handler, .-Reset_Handler |
||||
|
||||
/** |
||||
* @brief This is the code that gets called when the processor receives an
|
||||
* unexpected interrupt. This simply enters an infinite loop, preserving |
||||
* the system state for examination by a debugger. |
||||
* @param None
|
||||
* @retval None
|
||||
*/ |
||||
.section .text.Default_Handler,"ax",%progbits |
||||
Default_Handler: |
||||
Infinite_Loop: |
||||
b Infinite_Loop |
||||
.size Default_Handler, .-Default_Handler |
||||
/****************************************************************************** |
||||
* |
||||
* The minimal vector table for a Cortex M3. Note that the proper constructs |
||||
* must be placed on this to ensure that it ends up at physical address |
||||
* 0x0000.0000. |
||||
*
|
||||
*******************************************************************************/ |
||||
.section .isr_vector,"a",%progbits |
||||
.type g_pfnVectors, %object |
||||
.size g_pfnVectors, .-g_pfnVectors |
||||
|
||||
g_pfnVectors: |
||||
.word _estack
|
||||
.word Reset_Handler
|
||||
.word NMI_Handler
|
||||
.word HardFault_Handler
|
||||
.word MemManage_Handler
|
||||
.word BusFault_Handler
|
||||
.word UsageFault_Handler
|
||||
.word 0
|
||||
.word 0
|
||||
.word 0
|
||||
.word 0
|
||||
.word SVC_Handler
|
||||
.word DebugMon_Handler
|
||||
.word 0
|
||||
.word PendSV_Handler
|
||||
.word SysTick_Handler
|
||||
|
||||
/* External Interrupts */ |
||||
.word WWDG_IRQHandler /* Window WatchDog */ |
||||
.word PVD_IRQHandler /* PVD through EXTI Line detection */ |
||||
.word TAMP_STAMP_IRQHandler /* Tamper and TimeStamps through the EXTI line */ |
||||
.word RTC_WKUP_IRQHandler /* RTC Wakeup through the EXTI line */ |
||||
.word FLASH_IRQHandler /* FLASH */ |
||||
.word RCC_IRQHandler /* RCC */ |
||||
.word EXTI0_IRQHandler /* EXTI Line0 */ |
||||
.word EXTI1_IRQHandler /* EXTI Line1 */ |
||||
.word EXTI2_IRQHandler /* EXTI Line2 */ |
||||
.word EXTI3_IRQHandler /* EXTI Line3 */ |
||||
.word EXTI4_IRQHandler /* EXTI Line4 */ |
||||
.word DMA1_Stream0_IRQHandler /* DMA1 Stream 0 */ |
||||
.word DMA1_Stream1_IRQHandler /* DMA1 Stream 1 */ |
||||
.word DMA1_Stream2_IRQHandler /* DMA1 Stream 2 */ |
||||
.word DMA1_Stream3_IRQHandler /* DMA1 Stream 3 */ |
||||
.word DMA1_Stream4_IRQHandler /* DMA1 Stream 4 */ |
||||
.word DMA1_Stream5_IRQHandler /* DMA1 Stream 5 */ |
||||
.word DMA1_Stream6_IRQHandler /* DMA1 Stream 6 */ |
||||
.word ADC_IRQHandler /* ADC1, ADC2 and ADC3s */ |
||||
.word CAN1_TX_IRQHandler /* CAN1 TX */ |
||||
.word CAN1_RX0_IRQHandler /* CAN1 RX0 */ |
||||
.word CAN1_RX1_IRQHandler /* CAN1 RX1 */ |
||||
.word CAN1_SCE_IRQHandler /* CAN1 SCE */ |
||||
.word EXTI9_5_IRQHandler /* External Line[9:5]s */ |
||||
.word TIM1_BRK_TIM9_IRQHandler /* TIM1 Break and TIM9 */ |
||||
.word TIM1_UP_TIM10_IRQHandler /* TIM1 Update and TIM10 */ |
||||
.word TIM1_TRG_COM_TIM11_IRQHandler /* TIM1 Trigger and Commutation and TIM11 */ |
||||
.word TIM1_CC_IRQHandler /* TIM1 Capture Compare */ |
||||
.word TIM2_IRQHandler /* TIM2 */ |
||||
.word TIM3_IRQHandler /* TIM3 */ |
||||
.word TIM4_IRQHandler /* TIM4 */ |
||||
.word I2C1_EV_IRQHandler /* I2C1 Event */ |
||||
.word I2C1_ER_IRQHandler /* I2C1 Error */ |
||||
.word I2C2_EV_IRQHandler /* I2C2 Event */ |
||||
.word I2C2_ER_IRQHandler /* I2C2 Error */ |
||||
.word SPI1_IRQHandler /* SPI1 */ |
||||
.word SPI2_IRQHandler /* SPI2 */ |
||||
.word USART1_IRQHandler /* USART1 */ |
||||
.word USART2_IRQHandler /* USART2 */ |
||||
.word USART3_IRQHandler /* USART3 */ |
||||
.word EXTI15_10_IRQHandler /* External Line[15:10]s */ |
||||
.word RTC_Alarm_IRQHandler /* RTC Alarm (A and B) through EXTI Line */ |
||||
.word OTG_FS_WKUP_IRQHandler /* USB OTG FS Wakeup through EXTI line */ |
||||
.word TIM8_BRK_TIM12_IRQHandler /* TIM8 Break and TIM12 */ |
||||
.word TIM8_UP_TIM13_IRQHandler /* TIM8 Update and TIM13 */ |
||||
.word TIM8_TRG_COM_TIM14_IRQHandler /* TIM8 Trigger and Commutation and TIM14 */ |
||||
.word TIM8_CC_IRQHandler /* TIM8 Capture Compare */ |
||||
.word DMA1_Stream7_IRQHandler /* DMA1 Stream7 */ |
||||
.word FSMC_IRQHandler /* FSMC */ |
||||
.word SDIO_IRQHandler /* SDIO */ |
||||
.word TIM5_IRQHandler /* TIM5 */ |
||||
.word SPI3_IRQHandler /* SPI3 */ |
||||
.word UART4_IRQHandler /* UART4 */ |
||||
.word UART5_IRQHandler /* UART5 */ |
||||
.word TIM6_DAC_IRQHandler /* TIM6, DAC1 and DAC2 */ |
||||
.word TIM7_IRQHandler /* TIM7 */ |
||||
.word DMA2_Stream0_IRQHandler /* DMA2 Stream 0 */ |
||||
.word DMA2_Stream1_IRQHandler /* DMA2 Stream 1 */ |
||||
.word DMA2_Stream2_IRQHandler /* DMA2 Stream 2 */ |
||||
.word DMA2_Stream3_IRQHandler /* DMA2 Stream 3 */ |
||||
.word DMA2_Stream4_IRQHandler /* DMA2 Stream 4 */ |
||||
.word DFSDM1_FLT0_IRQHandler /* DFSDM1 Filter0 */ |
||||
.word DFSDM1_FLT1_IRQHandler /* DFSDM1 Filter1 */ |
||||
.word CAN2_TX_IRQHandler /* CAN2 TX */ |
||||
.word CAN2_RX0_IRQHandler /* CAN2 RX0 */ |
||||
.word CAN2_RX1_IRQHandler /* CAN2 RX1 */ |
||||
.word CAN2_SCE_IRQHandler /* CAN2 SCE */ |
||||
.word OTG_FS_IRQHandler /* USB OTG FS */ |
||||
.word DMA2_Stream5_IRQHandler /* DMA2 Stream 5 */ |
||||
.word DMA2_Stream6_IRQHandler /* DMA2 Stream 6 */ |
||||
.word DMA2_Stream7_IRQHandler /* DMA2 Stream 7 */ |
||||
.word USART6_IRQHandler /* USART6 */ |
||||
.word I2C3_EV_IRQHandler /* I2C3 event */ |
||||
.word I2C3_ER_IRQHandler /* I2C3 error */ |
||||
.word CAN3_TX_IRQHandler /* CAN3 TX */ |
||||
.word CAN3_RX0_IRQHandler /* CAN3 RX0 */ |
||||
.word CAN3_RX1_IRQHandler /* CAN3 RX1 */ |
||||
.word CAN3_SCE_IRQHandler /* CAN3 SCE */ |
||||
.word 0 /* Reserved */ |
||||
.word 0 /* Reserved */ |
||||
.word RNG_IRQHandler /* RNG */ |
||||
.word FPU_IRQHandler /* FPU */ |
||||
.word UART7_IRQHandler /* UART7 */ |
||||
.word UART8_IRQHandler /* UART8 */ |
||||
.word SPI4_IRQHandler /* SPI4 */ |
||||
.word SPI5_IRQHandler /* SPI5 */ |
||||
.word 0 /* Reserved */ |
||||
.word SAI1_IRQHandler /* SAI1 */ |
||||
.word UART9_IRQHandler /* UART9 */ |
||||
.word UART10_IRQHandler /* UART10 */ |
||||
.word 0 /* Reserved */ |
||||
.word 0 /* Reserved */ |
||||
.word QUADSPI_IRQHandler /* QuadSPI */ |
||||
.word 0 /* Reserved */ |
||||
.word 0 /* Reserved */ |
||||
.word FMPI2C1_EV_IRQHandler /* FMPI2C1 Event */ |
||||
.word FMPI2C1_ER_IRQHandler /* FMPI2C1 Error */ |
||||
.word LPTIM1_IRQHandler /* LPTIM1 */ |
||||
.word DFSDM2_FLT0_IRQHandler /* DFSDM2 Filter0 */ |
||||
.word DFSDM2_FLT1_IRQHandler /* DFSDM2 Filter1 */ |
||||
.word DFSDM2_FLT2_IRQHandler /* DFSDM2 Filter2 */ |
||||
.word DFSDM2_FLT3_IRQHandler /* DFSDM2 Filter3 */ |
||||
|
||||
/******************************************************************************* |
||||
* |
||||
* Provide weak aliases for each Exception handler to the Default_Handler.
|
||||
* As they are weak aliases, any function with the same name will override
|
||||
* this definition. |
||||
* |
||||
*******************************************************************************/ |
||||
.weak NMI_Handler
|
||||
.thumb_set NMI_Handler,Default_Handler |
||||
|
||||
.weak HardFault_Handler
|
||||
.thumb_set HardFault_Handler,Default_Handler |
||||
|
||||
.weak MemManage_Handler
|
||||
.thumb_set MemManage_Handler,Default_Handler |
||||
|
||||
.weak BusFault_Handler
|
||||
.thumb_set BusFault_Handler,Default_Handler |
||||
|
||||
.weak UsageFault_Handler
|
||||
.thumb_set UsageFault_Handler,Default_Handler |
||||
|
||||
.weak SVC_Handler
|
||||
.thumb_set SVC_Handler,Default_Handler |
||||
|
||||
.weak DebugMon_Handler
|
||||
.thumb_set DebugMon_Handler,Default_Handler |
||||
|
||||
.weak PendSV_Handler
|
||||
.thumb_set PendSV_Handler,Default_Handler |
||||
|
||||
.weak SysTick_Handler
|
||||
.thumb_set SysTick_Handler,Default_Handler |
||||
|
||||
.weak WWDG_IRQHandler
|
||||
.thumb_set WWDG_IRQHandler,Default_Handler |
||||
|
||||
.weak PVD_IRQHandler
|
||||
.thumb_set PVD_IRQHandler,Default_Handler |
||||
|
||||
.weak TAMP_STAMP_IRQHandler
|
||||
.thumb_set TAMP_STAMP_IRQHandler,Default_Handler |
||||
|
||||
.weak RTC_WKUP_IRQHandler
|
||||
.thumb_set RTC_WKUP_IRQHandler,Default_Handler |
||||
|
||||
.weak FLASH_IRQHandler
|
||||
.thumb_set FLASH_IRQHandler,Default_Handler |
||||
|
||||
.weak RCC_IRQHandler
|
||||
.thumb_set RCC_IRQHandler,Default_Handler |
||||
|
||||
.weak EXTI0_IRQHandler
|
||||
.thumb_set EXTI0_IRQHandler,Default_Handler |
||||
|
||||
.weak EXTI1_IRQHandler
|
||||
.thumb_set EXTI1_IRQHandler,Default_Handler |
||||
|
||||
.weak EXTI2_IRQHandler
|
||||
.thumb_set EXTI2_IRQHandler,Default_Handler
|
||||
|
||||
.weak EXTI3_IRQHandler
|
||||
.thumb_set EXTI3_IRQHandler,Default_Handler |
||||
|
||||
.weak EXTI4_IRQHandler
|
||||
.thumb_set EXTI4_IRQHandler,Default_Handler |
||||
|
||||
.weak DMA1_Stream0_IRQHandler
|
||||
.thumb_set DMA1_Stream0_IRQHandler,Default_Handler |
||||
|
||||
.weak DMA1_Stream1_IRQHandler
|
||||
.thumb_set DMA1_Stream1_IRQHandler,Default_Handler |
||||
|
||||
.weak DMA1_Stream2_IRQHandler
|
||||
.thumb_set DMA1_Stream2_IRQHandler,Default_Handler |
||||
|
||||
.weak DMA1_Stream3_IRQHandler
|
||||
.thumb_set DMA1_Stream3_IRQHandler,Default_Handler |
||||
|
||||
.weak DMA1_Stream4_IRQHandler
|
||||
.thumb_set DMA1_Stream4_IRQHandler,Default_Handler |
||||
|
||||
.weak DMA1_Stream5_IRQHandler
|
||||
.thumb_set DMA1_Stream5_IRQHandler,Default_Handler |
||||
|
||||
.weak DMA1_Stream6_IRQHandler
|
||||
.thumb_set DMA1_Stream6_IRQHandler,Default_Handler |
||||
|
||||
.weak ADC_IRQHandler
|
||||
.thumb_set ADC_IRQHandler,Default_Handler |
||||
|
||||
.weak CAN1_TX_IRQHandler
|
||||
.thumb_set CAN1_TX_IRQHandler,Default_Handler |
||||
|
||||
.weak CAN1_RX0_IRQHandler
|
||||
.thumb_set CAN1_RX0_IRQHandler,Default_Handler |
||||
|
||||
.weak CAN1_RX1_IRQHandler
|
||||
.thumb_set CAN1_RX1_IRQHandler,Default_Handler |
||||
|
||||
.weak CAN1_SCE_IRQHandler
|
||||
.thumb_set CAN1_SCE_IRQHandler,Default_Handler |
||||
|
||||
.weak EXTI9_5_IRQHandler
|
||||
.thumb_set EXTI9_5_IRQHandler,Default_Handler |
||||
|
||||
.weak TIM1_BRK_TIM9_IRQHandler
|
||||
.thumb_set TIM1_BRK_TIM9_IRQHandler,Default_Handler |
||||
|
||||
.weak TIM1_UP_TIM10_IRQHandler
|
||||
.thumb_set TIM1_UP_TIM10_IRQHandler,Default_Handler |
||||
|
||||
.weak TIM1_TRG_COM_TIM11_IRQHandler
|
||||
.thumb_set TIM1_TRG_COM_TIM11_IRQHandler,Default_Handler |
||||
|
||||
.weak TIM1_CC_IRQHandler
|
||||
.thumb_set TIM1_CC_IRQHandler,Default_Handler |
||||
|
||||
.weak TIM2_IRQHandler
|
||||
.thumb_set TIM2_IRQHandler,Default_Handler |
||||
|
||||
.weak TIM3_IRQHandler
|
||||
.thumb_set TIM3_IRQHandler,Default_Handler |
||||
|
||||
.weak TIM4_IRQHandler
|
||||
.thumb_set TIM4_IRQHandler,Default_Handler |
||||
|
||||
.weak I2C1_EV_IRQHandler
|
||||
.thumb_set I2C1_EV_IRQHandler,Default_Handler |
||||
|
||||
.weak I2C1_ER_IRQHandler
|
||||
.thumb_set I2C1_ER_IRQHandler,Default_Handler |
||||
|
||||
.weak I2C2_EV_IRQHandler
|
||||
.thumb_set I2C2_EV_IRQHandler,Default_Handler |
||||
|
||||
.weak I2C2_ER_IRQHandler
|
||||
.thumb_set I2C2_ER_IRQHandler,Default_Handler |
||||
|
||||
.weak SPI1_IRQHandler
|
||||
.thumb_set SPI1_IRQHandler,Default_Handler |
||||
|
||||
.weak SPI2_IRQHandler
|
||||
.thumb_set SPI2_IRQHandler,Default_Handler |
||||
|
||||
.weak USART1_IRQHandler
|
||||
.thumb_set USART1_IRQHandler,Default_Handler |
||||
|
||||
.weak USART2_IRQHandler
|
||||
.thumb_set USART2_IRQHandler,Default_Handler |
||||
|
||||
.weak USART3_IRQHandler
|
||||
.thumb_set USART3_IRQHandler,Default_Handler |
||||
|
||||
.weak EXTI15_10_IRQHandler
|
||||
.thumb_set EXTI15_10_IRQHandler,Default_Handler |
||||
|
||||
.weak RTC_Alarm_IRQHandler
|
||||
.thumb_set RTC_Alarm_IRQHandler,Default_Handler |
||||
|
||||
.weak OTG_FS_WKUP_IRQHandler
|
||||
.thumb_set OTG_FS_WKUP_IRQHandler,Default_Handler |
||||
|
||||
.weak TIM8_BRK_TIM12_IRQHandler
|
||||
.thumb_set TIM8_BRK_TIM12_IRQHandler,Default_Handler |
||||
|
||||
.weak TIM8_UP_TIM13_IRQHandler
|
||||
.thumb_set TIM8_UP_TIM13_IRQHandler,Default_Handler |
||||
|
||||
.weak TIM8_TRG_COM_TIM14_IRQHandler
|
||||
.thumb_set TIM8_TRG_COM_TIM14_IRQHandler,Default_Handler |
||||
|
||||
.weak TIM8_CC_IRQHandler
|
||||
.thumb_set TIM8_CC_IRQHandler,Default_Handler |
||||
|
||||
.weak DMA1_Stream7_IRQHandler
|
||||
.thumb_set DMA1_Stream7_IRQHandler,Default_Handler |
||||
|
||||
.weak FSMC_IRQHandler
|
||||
.thumb_set FSMC_IRQHandler,Default_Handler
|
||||
|
||||
.weak SDIO_IRQHandler
|
||||
.thumb_set SDIO_IRQHandler,Default_Handler |
||||
|
||||
.weak TIM5_IRQHandler
|
||||
.thumb_set TIM5_IRQHandler,Default_Handler |
||||
|
||||
.weak SPI3_IRQHandler
|
||||
.thumb_set SPI3_IRQHandler,Default_Handler |
||||
|
||||
.weak UART4_IRQHandler
|
||||
.thumb_set UART4_IRQHandler,Default_Handler |
||||
|
||||
.weak UART5_IRQHandler
|
||||
.thumb_set UART5_IRQHandler,Default_Handler
|
||||
|
||||
.weak TIM6_DAC_IRQHandler
|
||||
.thumb_set TIM6_DAC_IRQHandler,Default_Handler |
||||
|
||||
.weak TIM7_IRQHandler
|
||||
.thumb_set TIM7_IRQHandler,Default_Handler |
||||
|
||||
.weak DMA2_Stream0_IRQHandler
|
||||
.thumb_set DMA2_Stream0_IRQHandler,Default_Handler |
||||
|
||||
.weak DMA2_Stream1_IRQHandler
|
||||
.thumb_set DMA2_Stream1_IRQHandler,Default_Handler |
||||
|
||||
.weak DMA2_Stream2_IRQHandler
|
||||
.thumb_set DMA2_Stream2_IRQHandler,Default_Handler |
||||
|
||||
.weak DMA2_Stream3_IRQHandler
|
||||
.thumb_set DMA2_Stream3_IRQHandler,Default_Handler |
||||
|
||||
.weak DMA2_Stream4_IRQHandler
|
||||
.thumb_set DMA2_Stream4_IRQHandler,Default_Handler |
||||
|
||||
.weak DFSDM1_FLT0_IRQHandler
|
||||
.thumb_set DFSDM1_FLT0_IRQHandler,Default_Handler |
||||
|
||||
.weak DFSDM1_FLT1_IRQHandler
|
||||
.thumb_set DFSDM1_FLT1_IRQHandler,Default_Handler |
||||
|
||||
.weak CAN2_TX_IRQHandler
|
||||
.thumb_set CAN2_TX_IRQHandler,Default_Handler |
||||
|
||||
.weak CAN2_RX0_IRQHandler
|
||||
.thumb_set CAN2_RX0_IRQHandler,Default_Handler |
||||
|
||||
.weak CAN2_RX1_IRQHandler
|
||||
.thumb_set CAN2_RX1_IRQHandler,Default_Handler |
||||
|
||||
.weak CAN2_SCE_IRQHandler
|
||||
.thumb_set CAN2_SCE_IRQHandler,Default_Handler |
||||
|
||||
.weak OTG_FS_IRQHandler
|
||||
.thumb_set OTG_FS_IRQHandler,Default_Handler |
||||
|
||||
.weak DMA2_Stream5_IRQHandler
|
||||
.thumb_set DMA2_Stream5_IRQHandler,Default_Handler |
||||
|
||||
.weak DMA2_Stream6_IRQHandler
|
||||
.thumb_set DMA2_Stream6_IRQHandler,Default_Handler |
||||
|
||||
.weak DMA2_Stream7_IRQHandler
|
||||
.thumb_set DMA2_Stream7_IRQHandler,Default_Handler |
||||
|
||||
.weak USART6_IRQHandler
|
||||
.thumb_set USART6_IRQHandler,Default_Handler |
||||
|
||||
.weak I2C3_EV_IRQHandler
|
||||
.thumb_set I2C3_EV_IRQHandler,Default_Handler |
||||
|
||||
.weak I2C3_ER_IRQHandler
|
||||
.thumb_set I2C3_ER_IRQHandler,Default_Handler |
||||
|
||||
.weak CAN3_TX_IRQHandler
|
||||
.thumb_set CAN3_TX_IRQHandler,Default_Handler |
||||
|
||||
.weak CAN3_RX0_IRQHandler
|
||||
.thumb_set CAN3_RX0_IRQHandler,Default_Handler |
||||
|
||||
.weak CAN3_RX1_IRQHandler
|
||||
.thumb_set CAN3_RX1_IRQHandler,Default_Handler |
||||
|
||||
.weak CAN3_SCE_IRQHandler
|
||||
.thumb_set CAN3_SCE_IRQHandler,Default_Handler
|
||||
|
||||
.weak RNG_IRQHandler
|
||||
.thumb_set RNG_IRQHandler,Default_Handler |
||||
|
||||
.weak FPU_IRQHandler
|
||||
.thumb_set FPU_IRQHandler,Default_Handler |
||||
|
||||
.weak UART7_IRQHandler
|
||||
.thumb_set UART7_IRQHandler,Default_Handler |
||||
|
||||
.weak UART8_IRQHandler
|
||||
.thumb_set UART8_IRQHandler,Default_Handler
|
||||
|
||||
.weak SPI4_IRQHandler
|
||||
.thumb_set SPI4_IRQHandler,Default_Handler |
||||
|
||||
.weak SPI5_IRQHandler
|
||||
.thumb_set SPI5_IRQHandler,Default_Handler |
||||
|
||||
.weak SAI1_IRQHandler
|
||||
.thumb_set SAI1_IRQHandler,Default_Handler |
||||
|
||||
.weak UART9_IRQHandler
|
||||
.thumb_set UART9_IRQHandler,Default_Handler |
||||
|
||||
.weak UART10_IRQHandler
|
||||
.thumb_set UART10_IRQHandler,Default_Handler
|
||||
|
||||
.weak QUADSPI_IRQHandler
|
||||
.thumb_set QUADSPI_IRQHandler,Default_Handler |
||||
|
||||
.weak FMPI2C1_EV_IRQHandler
|
||||
.thumb_set FMPI2C1_EV_IRQHandler,Default_Handler |
||||
|
||||
.weak FMPI2C1_ER_IRQHandler
|
||||
.thumb_set FMPI2C1_ER_IRQHandler,Default_Handler |
||||
|
||||
.weak LPTIM1_IRQHandler
|
||||
.thumb_set LPTIM1_IRQHandler,Default_Handler |
||||
|
||||
.weak DFSDM2_FLT0_IRQHandler
|
||||
.thumb_set DFSDM2_FLT0_IRQHandler,Default_Handler |
||||
|
||||
.weak DFSDM2_FLT1_IRQHandler
|
||||
.thumb_set DFSDM2_FLT1_IRQHandler,Default_Handler |
||||
|
||||
.weak DFSDM2_FLT2_IRQHandler
|
||||
.thumb_set DFSDM2_FLT2_IRQHandler,Default_Handler |
||||
|
||||
.weak DFSDM2_FLT3_IRQHandler
|
||||
.thumb_set DFSDM2_FLT3_IRQHandler,Default_Handler |
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ |
@ -0,0 +1,165 @@ |
||||
/* |
||||
***************************************************************************** |
||||
** |
||||
** File : stm32_flash.ld |
||||
** |
||||
** Abstract : Linker script for STM32F407VG Device with |
||||
** 1024KByte FLASH, 192KByte RAM |
||||
** |
||||
** Set heap size, stack size and stack location according |
||||
** to application requirements. |
||||
** |
||||
** Set memory bank area and size if external memory is used. |
||||
** |
||||
** Target : STMicroelectronics STM32 |
||||
** |
||||
** Environment : Atollic TrueSTUDIO(R) |
||||
** |
||||
** Distribution: The file is distributed “as is,” without any warranty |
||||
** of any kind. |
||||
** |
||||
** (c)Copyright Atollic AB. |
||||
** You may use this file as-is or modify it according to the needs of your |
||||
** project. Distribution of this file (unmodified or modified) is not |
||||
** permitted. Atollic AB permit registered Atollic TrueSTUDIO(R) users the |
||||
** rights to distribute the assembled, compiled & linked contents of this |
||||
** file as part of an application binary file, provided that it is built |
||||
** using the Atollic TrueSTUDIO(R) toolchain. |
||||
** |
||||
***************************************************************************** |
||||
*/ |
||||
|
||||
/* Entry Point */ |
||||
ENTRY(Reset_Handler) |
||||
|
||||
/* Highest address of the user mode stack */ |
||||
enter_bootloader_mode = 0x2001FFFC; |
||||
_estack = 0x2001FFFC; /* end of 128K RAM on AHB bus*/ |
||||
_app_start = 0x08004000; /* Reserve 16K for bootloader */ |
||||
|
||||
/* Generate a link error if heap and stack don't fit into RAM */ |
||||
_Min_Heap_Size = 0; /* required amount of heap */ |
||||
_Min_Stack_Size = 0x400; /* required amount of stack */ |
||||
|
||||
/* Specify the memory areas */ |
||||
MEMORY |
||||
{ |
||||
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 128K |
||||
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K |
||||
MEMORY_B1 (rx) : ORIGIN = 0x60000000, LENGTH = 0K |
||||
} |
||||
|
||||
/* Define output sections */ |
||||
SECTIONS |
||||
{ |
||||
/* The startup code goes first into FLASH */ |
||||
.isr_vector : |
||||
{ |
||||
. = ALIGN(4); |
||||
KEEP(*(.isr_vector)) /* Startup code */ |
||||
. = ALIGN(4); |
||||
} >FLASH |
||||
|
||||
/* The program code and other data goes into FLASH */ |
||||
.text : |
||||
{ |
||||
. = ALIGN(4); |
||||
*(.text) /* .text sections (code) */ |
||||
*(.text*) /* .text* sections (code) */ |
||||
*(.rodata) /* .rodata sections (constants, strings, etc.) */ |
||||
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */ |
||||
*(.glue_7) /* glue arm to thumb code */ |
||||
*(.glue_7t) /* glue thumb to arm code */ |
||||
*(.eh_frame) |
||||
|
||||
KEEP (*(.init)) |
||||
KEEP (*(.fini)) |
||||
|
||||
. = ALIGN(4); |
||||
_etext = .; /* define a global symbols at end of code */ |
||||
_exit = .; |
||||
} >FLASH |
||||
|
||||
|
||||
.ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH |
||||
.ARM : { |
||||
__exidx_start = .; |
||||
*(.ARM.exidx*) |
||||
__exidx_end = .; |
||||
} >FLASH |
||||
|
||||
.preinit_array : |
||||
{ |
||||
PROVIDE_HIDDEN (__preinit_array_start = .); |
||||
KEEP (*(.preinit_array*)) |
||||
PROVIDE_HIDDEN (__preinit_array_end = .); |
||||
} >FLASH |
||||
.init_array : |
||||
{ |
||||
PROVIDE_HIDDEN (__init_array_start = .); |
||||
KEEP (*(SORT(.init_array.*))) |
||||
KEEP (*(.init_array*)) |
||||
PROVIDE_HIDDEN (__init_array_end = .); |
||||
} >FLASH |
||||
.fini_array : |
||||
{ |
||||
PROVIDE_HIDDEN (__fini_array_start = .); |
||||
KEEP (*(.fini_array*)) |
||||
KEEP (*(SORT(.fini_array.*))) |
||||
PROVIDE_HIDDEN (__fini_array_end = .); |
||||
} >FLASH |
||||
|
||||
/* used by the startup to initialize data */ |
||||
_sidata = .; |
||||
|
||||
/* Initialized data sections goes into RAM, load LMA copy after code */ |
||||
.data : AT ( _sidata ) |
||||
{ |
||||
. = ALIGN(4); |
||||
_sdata = .; /* create a global symbol at data start */ |
||||
*(.data) /* .data sections */ |
||||
*(.data*) /* .data* sections */ |
||||
|
||||
. = ALIGN(4); |
||||
_edata = .; /* define a global symbol at data end */ |
||||
} >RAM |
||||
|
||||
/* Uninitialized data section */ |
||||
. = ALIGN(4); |
||||
.bss : |
||||
{ |
||||
/* This is used by the startup in order to initialize the .bss secion */ |
||||
_sbss = .; /* define a global symbol at bss start */ |
||||
__bss_start__ = _sbss; |
||||
*(.bss) |
||||
*(.bss*) |
||||
*(COMMON) |
||||
|
||||
. = ALIGN(4); |
||||
_ebss = .; /* define a global symbol at bss end */ |
||||
__bss_end__ = _ebss; |
||||
} >RAM |
||||
|
||||
/* User_heap_stack section, used to check that there is enough RAM left */ |
||||
._user_heap_stack : |
||||
{ |
||||
. = ALIGN(4); |
||||
PROVIDE ( end = . ); |
||||
PROVIDE ( _end = . ); |
||||
. = . + _Min_Heap_Size; |
||||
. = . + _Min_Stack_Size; |
||||
. = ALIGN(4); |
||||
} >RAM |
||||
|
||||
/* MEMORY_bank1 section, code must be located here explicitly */ |
||||
/* Example: extern int foo(void) __attribute__ ((section (".mb1text"))); */ |
||||
.memory_b1_text : |
||||
{ |
||||
*(.mb1text) /* .mb1text sections (code) */ |
||||
*(.mb1text*) /* .mb1text* sections (code) */ |
||||
*(.mb1rodata) /* read-only data (constants) */ |
||||
*(.mb1rodata*) |
||||
} >MEMORY_B1 |
||||
|
||||
.ARM.attributes 0 : { *(.ARM.attributes) } |
||||
} |
@ -0,0 +1,35 @@ |
||||
/*
|
||||
gcc -DTEST_RSA test_rsa.c ../crypto/rsa.c ../crypto/sha.c && ./a.out |
||||
*/ |
||||
|
||||
#include <stdio.h> |
||||
#include <stdlib.h> |
||||
|
||||
#define MAX_LEN 0x40000 |
||||
char buf[MAX_LEN]; |
||||
|
||||
#include "../crypto/sha.h" |
||||
#include "../crypto/rsa.h" |
||||
#include "../obj/cert.h" |
||||
|
||||
int main() { |
||||
FILE *f = fopen("../obj/panda.bin", "rb"); |
||||
int tlen = fread(buf, 1, MAX_LEN, f); |
||||
fclose(f); |
||||
printf("read %d\n", tlen); |
||||
uint32_t *_app_start = (uint32_t *)buf; |
||||
|
||||
int len = _app_start[0]; |
||||
char digest[SHA_DIGEST_SIZE]; |
||||
SHA_hash(&_app_start[1], len-4, digest); |
||||
printf("SHA hash done\n"); |
||||
|
||||
if (!RSA_verify(&rsa_key, ((void*)&_app_start[0]) + len, RSANUMBYTES, digest, SHA_DIGEST_SIZE)) { |
||||
printf("RSA fail\n"); |
||||
} else { |
||||
printf("RSA match!!!\n"); |
||||
} |
||||
|
||||
return 0; |
||||
} |
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,33 @@ |
||||
#!/usr/bin/env python |
||||
from __future__ import print_function |
||||
|
||||
import sys |
||||
import time |
||||
import usb1 |
||||
|
||||
def enter_download_mode(device): |
||||
handle = device.open() |
||||
handle.claimInterface(0) |
||||
|
||||
try: |
||||
handle.controlWrite(usb1.TYPE_VENDOR | usb1.RECIPIENT_DEVICE, 0xd1, 0, 0, b'') |
||||
except (usb1.USBErrorIO, usb1.USBErrorPipe) as e: |
||||
print("Device download mode enabled.") |
||||
time.sleep(1) |
||||
else: |
||||
print("Device failed to enter download mode.") |
||||
sys.exit(1) |
||||
|
||||
def find_first_panda(context=None): |
||||
context = context or usb1.USBContext() |
||||
for device in context.getDeviceList(skip_on_error=True): |
||||
if device.getVendorID() == 0xbbaa and device.getProductID()&0xFF00 == 0xdd00: |
||||
return device |
||||
|
||||
if __name__ == "__main__": |
||||
panda_dev = find_first_panda() |
||||
if panda_dev == None: |
||||
print("no device found") |
||||
sys.exit(0) |
||||
print("found device") |
||||
enter_download_mode(panda_dev) |
@ -0,0 +1,8 @@ |
||||
proxy |
||||
*.bin |
||||
esp-open-sdk |
||||
a.out |
||||
cert.h |
||||
gitversion.h |
||||
esp-open-sdk.dmg |
||||
obj/* |
@ -0,0 +1,101 @@ |
||||
ELM327 support for panda |
||||
====== |
||||
The panda now has basic ELM327 support. |
||||
|
||||
### What is ELM327? |
||||
|
||||
ELM327 is a command protocol for interfacing with cars using an OBD-II |
||||
port to read [list](standard vehicle diagnostic codes). ELM327 |
||||
originally referred to a line of programmable microcontrollers that |
||||
implemented the ELM327 command protocol, and are still being |
||||
developed. |
||||
|
||||
ELM327 devices present a shell and commands are sent via a UART. The |
||||
official ELM327 chips only support raw UART communication, but most |
||||
devices built with the ELM327 devices (official or clones) expose the |
||||
UART in a more modern way (Wifi, USB, etc). |
||||
|
||||
Mechanics use ELM to diagnose vehicles, and reset fault codes in the |
||||
car's computer after fixing the issue (turning off the dreaded check |
||||
engine light). Car owners can use ELM devices to perform the same |
||||
diagnostics in their garage using either a raw terminal to send |
||||
commands to the ELM device directly, or using a GUI (like one of |
||||
several popular smart phone apps) to translate the OBD error codes |
||||
into readable messages. These GUIs also often allow monitoring of the |
||||
performance of the car's speed, engine rpm, etc. |
||||
|
||||
The panda natively supports sending all the important OBD diagnostic |
||||
messages, but ELM327 support removes the need for the user to manually |
||||
craft CAN or LIN packets using the native panda API, and grants |
||||
compatibility with many existing tools. |
||||
|
||||
[Wikipedia](https://en.wikipedia.org/wiki/ELM327) can provide |
||||
additional information. |
||||
|
||||
### OBD Protocols? |
||||
|
||||
While the commands that the OBD standard describe are in fact |
||||
standard, there are several different protocols that those messages |
||||
can be sent and received with. All cars after 1991 support one of |
||||
these protocols. Which one depends on the car's year and country, as |
||||
legal requirements change over the years. |
||||
|
||||
The panda supports the most popular/modern of these protocols, and all |
||||
but two can be added as needed. Below is a chart of the OBD-II |
||||
protocols supported by the panda. |
||||
|
||||
| Protocol | Support Status | |
||||
| --- | --- | |
||||
| SAE J1850 PWM (41.6 kbit/s) | Never/Obsolete | |
||||
| SAE J1850 VPW (10.4 kbit/s) | Never/Obsolete | |
||||
| ISO 9141-2 (5 baud init, 10.4 kbit/s) | Unsupported | |
||||
| ISO 14230-4 KWP (5 baud init, 10.4 kbit/s) | Unsupported | |
||||
| ISO 14230-4 KWP (fast init, 10.4 kbit/s) | Supported | |
||||
| ISO 15765-4 CAN (11 bit ID, 500 kbit/s) | Supported | |
||||
| ISO 15765-4 CAN (29 bit ID, 500 kbit/s) | Supported | |
||||
| ISO 15765-4 CAN (11 bit ID, 250 kbit/s) | Supported | |
||||
| ISO 15765-4 CAN (29 bit ID, 250 kbit/s) | Supported | |
||||
| SAE J1939 (250kbps) | Unsupported | |
||||
|
||||
### The Implementation |
||||
|
||||
The panda ELM327 implementation is not a full implementation of all |
||||
the features of the official ELM327 microcontroller. Like most ELM327 |
||||
clones, the panda reports its ELM version as the unreleased version |
||||
1.5, despite only implementing commands from protocol version 1.0. |
||||
|
||||
|
||||
### Testing |
||||
|
||||
These tests require two pandas. One to be tested, and the second to |
||||
simulate the vehicle. |
||||
|
||||
The panda used to simulate the vehicle must be plugged into a USB port |
||||
of the testing computer. |
||||
|
||||
The computer running the tests must be connected to the panda being |
||||
tested's wifi network. |
||||
|
||||
The following command will run the tests (nosetest should work fine |
||||
instead of pytest if you still prefer using that). The CANSIMSERIAL |
||||
environment variable will force the car simulator to use the correct |
||||
panda as the simulator if multiple pandas are attached via usb to the |
||||
host computer. |
||||
|
||||
``` |
||||
CANSIMSERIAL=car_sim_panda_serial pytest tests/automated/elm_wifi.py |
||||
``` |
||||
|
||||
A single test can be run by putting the test name after the file name |
||||
and two colons, like so: |
||||
|
||||
``` |
||||
CANSIMSERIAL=car_sim_panda_serial pytest tests/automated/elm_wifi.py::test_important_thing |
||||
``` |
||||
|
||||
For more detail, provide the -s (show output) and the -vv (very |
||||
verbose) flags. |
||||
|
||||
``` |
||||
CANSIMSERIAL=car_sim_panda_serial pytest -s -vv tests/automated/elm_wifi.py |
||||
``` |
@ -0,0 +1,74 @@ |
||||
PATH := esp-open-sdk/xtensa-lx106-elf/bin:$(PATH)
|
||||
CC = esp-open-sdk/xtensa-lx106-elf/bin/xtensa-lx106-elf-gcc
|
||||
CFLAGS = -Iinclude/ -I. -I../ -mlongcalls -Iesp-open-sdk/ESP8266_NONOS_SDK_V1.5.4_16_05_20/driver_lib/include -std=c99 -DICACHE_FLASH
|
||||
LDLIBS = -nostdlib -Wl,--start-group -lmain -lnet80211 -lwpa -llwip -lpp -lphy -Wl,--end-group -lgcc -ldriver -Wl,--gc-sections
|
||||
LDFLAGS = -Teagle.app.v6.ld
|
||||
OBJCP = esp-open-sdk/xtensa-lx106-elf/bin/xtensa-lx106-elf-objcopy
|
||||
SDK_BASE = esp-open-sdk/ESP8266_NONOS_SDK_V1.5.4_16_05_20
|
||||
|
||||
ifeq ($(RELEASE),1) |
||||
CERT = ../../pandaextra/certs/releaseesp
|
||||
else |
||||
CERT = ../certs/debugesp
|
||||
CFLAGS += "-DALLOW_DEBUG"
|
||||
endif |
||||
|
||||
flashall: user1.bin user2.bin |
||||
../python/esptool.py write_flash 0 $(SDK_BASE)/bin/boot_v1.5.bin 0x01000 user1.bin 0x81000 user2.bin 0x3FE000 $(SDK_BASE)/bin/blank.bin
|
||||
|
||||
proxy-0x00000.bin: proxy |
||||
../python/esptool.py elf2image $^
|
||||
|
||||
proxy: proxy.o elm327.o webserver.o sha.o |
||||
|
||||
obj/proxy.o: proxy.c |
||||
$(CC) $(CFLAGS) -c $^ -o $@
|
||||
|
||||
obj/elm327.o: elm327.c |
||||
$(CC) $(CFLAGS) -c $^ -o $@
|
||||
|
||||
obj/webserver.o: webserver.c obj/cert.h obj/gitversion.h |
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
obj/cert.h: ../crypto/getcertheader.py |
||||
../crypto/getcertheader.py ../certs/debugesp.pub ../certs/releaseesp.pub > obj/cert.h
|
||||
|
||||
include ../common/version.mk |
||||
|
||||
obj/sha.o: ../crypto/sha.c |
||||
$(CC) $(CFLAGS) -c $^ -o $@
|
||||
|
||||
obj/rsa.o: ../crypto/rsa.c |
||||
$(CC) $(CFLAGS) -c $^ -o $@
|
||||
|
||||
oldflash: proxy-0x00000.bin |
||||
../python/esptool.py write_flash 0 proxy-0x00000.bin 0x40000 proxy-0x40000.bin
|
||||
|
||||
user1.bin: obj/proxy.o obj/elm327.o obj/webserver.o obj/sha.o obj/rsa.o |
||||
$(CC) $(CFLAGS) $^ -o a.out -L$(SDK_BASE)/ld -T$(SDK_BASE)/ld/eagle.app.v6.new.1024.app1.ld $(LDLIBS)
|
||||
$(OBJCP) --only-section .text -O binary a.out eagle.app.v6.text.bin
|
||||
$(OBJCP) --only-section .data -O binary a.out eagle.app.v6.data.bin
|
||||
$(OBJCP) --only-section .rodata -O binary a.out eagle.app.v6.rodata.bin
|
||||
$(OBJCP) --only-section .irom0.text -O binary a.out eagle.app.v6.irom0text.bin
|
||||
COMPILE=gcc python ./esp-open-sdk/ESP8266_NONOS_SDK_V1.5.4_16_05_20/tools/gen_appbin.py a.out 2 0 32 4 0
|
||||
rm -f eagle.app.v6.*.bin
|
||||
mv eagle.app.flash.bin $@
|
||||
../crypto/sign.py $@ $@ $(CERT)
|
||||
|
||||
user2.bin: obj/proxy.o obj/elm327.o obj/webserver.o obj/sha.o obj/rsa.o |
||||
$(CC) $(CFLAGS) $^ -o a.out -L$(SDK_BASE)/ld -T$(SDK_BASE)/ld/eagle.app.v6.new.1024.app2.ld $(LDLIBS)
|
||||
$(OBJCP) --only-section .text -O binary a.out eagle.app.v6.text.bin
|
||||
$(OBJCP) --only-section .data -O binary a.out eagle.app.v6.data.bin
|
||||
$(OBJCP) --only-section .rodata -O binary a.out eagle.app.v6.rodata.bin
|
||||
$(OBJCP) --only-section .irom0.text -O binary a.out eagle.app.v6.irom0text.bin
|
||||
COMPILE=gcc python ./esp-open-sdk/ESP8266_NONOS_SDK_V1.5.4_16_05_20/tools/gen_appbin.py a.out 2 0 32 4 0
|
||||
rm -f eagle.app.v6.*.bin
|
||||
mv eagle.app.flash.bin $@
|
||||
../crypto/sign.py $@ $@ $(CERT)
|
||||
|
||||
ota: user1.bin user2.bin |
||||
curl http://192.168.0.10/espupdate1 --upload-file user1.bin
|
||||
curl http://192.168.0.10/espupdate2 --upload-file user2.bin
|
||||
|
||||
clean: |
||||
rm -f proxy proxy.o proxy-0x00000.bin proxy-0x40000.bin eagle.app.* user1.bin user2.bin a.out obj/*
|
@ -0,0 +1,22 @@ |
||||
|
||||
Dependencies |
||||
----- |
||||
|
||||
**Mac** |
||||
|
||||
``` |
||||
./get_sdk.sh |
||||
``` |
||||
|
||||
**Debian / Ubuntu** |
||||
|
||||
``` |
||||
./get_sdk_mac.sh |
||||
``` |
||||
|
||||
Programming |
||||
----- |
||||
|
||||
``` |
||||
make |
||||
``` |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,12 @@ |
||||
#!/bin/bash |
||||
sudo apt-get install make unrar-free autoconf automake libtool gcc g++ gperf \ |
||||
flex bison texinfo gawk ncurses-dev libexpat-dev python-dev python python-serial \ |
||||
sed git unzip bash help2man wget bzip2 |
||||
# huh? |
||||
sudo apt-get install libtool |
||||
sudo apt-get install libtool-bin |
||||
git clone --recursive https://github.com/pfalcon/esp-open-sdk.git |
||||
cd esp-open-sdk |
||||
git checkout 03f5e898a059451ec5f3de30e7feff30455f7cec |
||||
LD_LIBRARY_PATH="" make STANDALONE=y |
||||
|
@ -0,0 +1,32 @@ |
||||
#!/bin/bash |
||||
|
||||
# from http://www.esp8266.com/wiki/doku.php?id=setup-osx-compiler-esp8266 |
||||
|
||||
brew install gnu-sed --with-default-names |
||||
brew tap homebrew/dupes |
||||
brew install gperf |
||||
brew install grep |
||||
brew install autoconf |
||||
brew install binutils |
||||
brew install gawk |
||||
brew install wget |
||||
brew install automake |
||||
brew install libtool |
||||
brew install help2man |
||||
|
||||
brew uninstall gperf |
||||
|
||||
hdiutil create esp-open-sdk.dmg -volname "esp-open-sdk" -size 10g -fs "Case-sensitive HFS+" |
||||
hdiutil mount esp-open-sdk.dmg |
||||
ln -s /Volumes/esp-open-sdk esp-open-sdk |
||||
cd esp-open-sdk |
||||
|
||||
git init |
||||
git remote add origin https://github.com/pfalcon/esp-open-sdk.git |
||||
git fetch origin |
||||
git checkout 03f5e898a059451ec5f3de30e7feff30455f7cec |
||||
git submodule init |
||||
git submodule update --recursive |
||||
|
||||
make STANDALONE=y |
||||
|
@ -0,0 +1,78 @@ |
||||
#ifndef ESPMISSINGINCLUDES_H |
||||
#define ESPMISSINGINCLUDES_H |
||||
|
||||
#include <stdint.h> |
||||
#include <c_types.h> |
||||
#include <os_type.h> |
||||
|
||||
|
||||
int strcasecmp(const char *a, const char *b); |
||||
#ifndef FREERTOS |
||||
#include <eagle_soc.h> |
||||
#include <ets_sys.h> |
||||
//Missing function prototypes in include folders. Gcc will warn on these if we don't define 'em anywhere.
|
||||
//MOST OF THESE ARE GUESSED! but they seem to swork and shut up the compiler.
|
||||
typedef struct espconn espconn; |
||||
|
||||
int atoi(const char *nptr); |
||||
void ets_install_putc1(void *routine); |
||||
void ets_isr_attach(int intr, void *handler, void *arg); |
||||
void ets_isr_mask(unsigned intr); |
||||
void ets_isr_unmask(unsigned intr); |
||||
int ets_memcmp(const void *s1, const void *s2, size_t n); |
||||
void *ets_memcpy(void *dest, const void *src, size_t n); |
||||
void *ets_memset(void *s, int c, size_t n); |
||||
int ets_sprintf(char *str, const char *format, ...) __attribute__ ((format (printf, 2, 3))); |
||||
int ets_str2macaddr(void *, void *); |
||||
int ets_strcmp(const char *s1, const char *s2); |
||||
char *ets_strcpy(char *dest, const char *src); |
||||
size_t ets_strlen(const char *s); |
||||
int ets_strncmp(const char *s1, const char *s2, int len); |
||||
char *ets_strncpy(char *dest, const char *src, size_t n); |
||||
char *ets_strstr(const char *haystack, const char *needle); |
||||
void ets_timer_arm_new(os_timer_t *a, int b, int c, int isMstimer); |
||||
void ets_timer_disarm(os_timer_t *a); |
||||
void ets_timer_setfn(os_timer_t *t, ETSTimerFunc *fn, void *parg); |
||||
void ets_update_cpu_frequency(int freqmhz); |
||||
void *os_memmove(void *dest, const void *src, size_t n); |
||||
int os_printf(const char *format, ...) __attribute__ ((format (printf, 1, 2))); |
||||
int os_snprintf(char *str, size_t size, const char *format, ...) __attribute__ ((format (printf, 3, 4))); |
||||
int os_printf_plus(const char *format, ...) __attribute__ ((format (printf, 1, 2))); |
||||
void uart_div_modify(int no, unsigned int freq); |
||||
uint8 wifi_get_opmode(void); |
||||
uint32 system_get_time(); |
||||
int rand(void); |
||||
void ets_bzero(void *s, size_t n); |
||||
void ets_delay_us(int ms); |
||||
|
||||
//Hack: this is defined in SDK 1.4.0 and undefined in 1.3.0. It's only used for this, the symbol itself
|
||||
//has no meaning here.
|
||||
#ifndef RC_LIMIT_P2P_11N |
||||
//Defs for SDK <1.4.0
|
||||
void *pvPortMalloc(size_t xWantedSize); |
||||
void *pvPortZalloc(size_t); |
||||
void vPortFree(void *ptr); |
||||
void *vPortMalloc(size_t xWantedSize); |
||||
void pvPortFree(void *ptr); |
||||
#else |
||||
void *pvPortMalloc(size_t xWantedSize, const char *file, int line); |
||||
void *pvPortZalloc(size_t, const char *file, int line); |
||||
void vPortFree(void *ptr, const char *file, int line); |
||||
void *vPortMalloc(size_t xWantedSize, const char *file, int line); |
||||
void pvPortFree(void *ptr, const char *file, int line); |
||||
#endif |
||||
|
||||
//Standard PIN_FUNC_SELECT gives a warning. Replace by a non-warning one.
|
||||
#ifdef PIN_FUNC_SELECT |
||||
#undef PIN_FUNC_SELECT |
||||
#define PIN_FUNC_SELECT(PIN_NAME, FUNC) do { \ |
||||
WRITE_PERI_REG(PIN_NAME, \
|
||||
(READ_PERI_REG(PIN_NAME) \
|
||||
& (~(PERIPHS_IO_MUX_FUNC<<PERIPHS_IO_MUX_FUNC_S))) \
|
||||
|( (((FUNC&BIT2)<<2)|(FUNC&0x3))<<PERIPHS_IO_MUX_FUNC_S) ); \
|
||||
} while (0) |
||||
#endif |
||||
|
||||
#endif |
||||
|
||||
#endif |
@ -0,0 +1,361 @@ |
||||
#include "ets_sys.h" |
||||
#include "osapi.h" |
||||
#include "gpio.h" |
||||
#include "os_type.h" |
||||
#include "user_interface.h" |
||||
#include "espconn.h" |
||||
|
||||
#include "driver/spi_interface.h" |
||||
#include "driver/uart.h" |
||||
#include "crypto/sha.h" |
||||
|
||||
#define min(a,b) \ |
||||
({ __typeof__ (a) _a = (a); \
|
||||
__typeof__ (b) _b = (b); \
|
||||
_a < _b ? _a : _b; }) |
||||
|
||||
#define max(a,b) \ |
||||
({ __typeof__ (a) _a = (a); \
|
||||
__typeof__ (b) _b = (b); \
|
||||
_a > _b ? _a : _b; }) |
||||
|
||||
char ssid[32]; |
||||
static const int pin = 2; |
||||
|
||||
// Structure holding the TCP connection information.
|
||||
struct espconn tcp_conn; |
||||
// TCP specific protocol structure.
|
||||
esp_tcp tcp_proto; |
||||
|
||||
// interrupt communication on port 1338, UDP!
|
||||
struct espconn inter_conn; |
||||
esp_udp inter_proto; |
||||
|
||||
uint32_t sendData[0x14] = {0}; |
||||
uint32_t recvData[0x40] = {0}; |
||||
|
||||
static int ICACHE_FLASH_ATTR __spi_comm(char *dat, int len, uint32_t *recvData, int recvDataLen) { |
||||
unsigned int length = 0; |
||||
|
||||
SpiData spiData; |
||||
|
||||
spiData.cmd = 2; |
||||
spiData.cmdLen = 0; |
||||
spiData.addr = NULL; |
||||
spiData.addrLen = 0; |
||||
|
||||
// float boot pin
|
||||
gpio_output_set(0, 0, 0, (1 << 4)); |
||||
|
||||
// manual CS pin
|
||||
gpio_output_set(0, (1 << 5), 0, 0); |
||||
memset(sendData, 0xCC, 0x14); |
||||
|
||||
// wait for ST to respond to CS interrupt
|
||||
os_delay_us(50); |
||||
|
||||
// send request
|
||||
memcpy(((void*)sendData), dat, len); |
||||
spiData.data = sendData; |
||||
spiData.dataLen = 0x14; |
||||
SPIMasterSendData(SpiNum_HSPI, &spiData); |
||||
|
||||
#define SPI_TIMEOUT 50000 |
||||
// give the ST time to be ready, up to 500ms
|
||||
int i; |
||||
for (i = 0; (gpio_input_get() & (1 << 4)) && i < SPI_TIMEOUT; i++) { |
||||
os_delay_us(10); |
||||
system_soft_wdt_feed(); |
||||
} |
||||
|
||||
// TODO: handle this better
|
||||
if (i == SPI_TIMEOUT) { |
||||
os_printf("ERROR: SPI receive failed\n"); |
||||
goto fail; |
||||
} |
||||
|
||||
// blank out recvData
|
||||
memset(recvData, 0x00, 0x44); |
||||
|
||||
// receive the length
|
||||
spiData.data = recvData; |
||||
spiData.dataLen = 4; |
||||
if(SPIMasterRecvData(SpiNum_HSPI, &spiData) == -1) { |
||||
// TODO: Handle gracefully. Maybe fail if len read fails?
|
||||
os_printf("SPI: Failed to recv length\n"); |
||||
goto fail; |
||||
} |
||||
|
||||
length = recvData[0]; |
||||
if (length > 0x40) { |
||||
os_printf("SPI: BAD LENGTH RECEIVED %x\n", length); |
||||
length = 0; |
||||
goto fail; |
||||
} |
||||
|
||||
// got response, 0x40 works, 0x44 does not
|
||||
spiData.data = recvData+1; |
||||
spiData.dataLen = (length+3)&(~3); // recvDataLen;
|
||||
if(SPIMasterRecvData(SpiNum_HSPI, &spiData) == -1) { |
||||
// TODO: Handle gracefully. Maybe retry if payload failed.
|
||||
os_printf("SPI: Failed to recv payload\n"); |
||||
length = 0; |
||||
goto fail; |
||||
} |
||||
|
||||
fail: |
||||
// clear CS
|
||||
gpio_output_set((1 << 5), 0, 0, 0); |
||||
|
||||
// set boot pin back
|
||||
gpio_output_set((1 << 4), 0, (1 << 4), 0); |
||||
|
||||
return length; |
||||
} |
||||
|
||||
int ICACHE_FLASH_ATTR spi_comm(char *dat, int len, uint32_t *recvData, int recvDataLen) { |
||||
// blink the led during SPI comm
|
||||
if (GPIO_REG_READ(GPIO_OUT_ADDRESS) & (1 << pin)) { |
||||
// set gpio low
|
||||
gpio_output_set(0, (1 << pin), 0, 0); |
||||
} else { |
||||
// set gpio high
|
||||
gpio_output_set((1 << pin), 0, 0, 0); |
||||
} |
||||
|
||||
return __spi_comm(dat, len, recvData, recvDataLen); |
||||
} |
||||
|
||||
static void ICACHE_FLASH_ATTR tcp_rx_cb(void *arg, char *data, uint16_t len) { |
||||
// nothing too big
|
||||
if (len > 0x14) return; |
||||
|
||||
// do the SPI comm
|
||||
spi_comm(data, len, recvData, 0x40); |
||||
|
||||
espconn_send(&tcp_conn, recvData, 0x44); |
||||
} |
||||
|
||||
void ICACHE_FLASH_ATTR tcp_connect_cb(void *arg) { |
||||
struct espconn *conn = (struct espconn *)arg; |
||||
espconn_set_opt(&tcp_conn, ESPCONN_NODELAY); |
||||
espconn_regist_recvcb(conn, tcp_rx_cb); |
||||
} |
||||
|
||||
// must be 0x44, because we can fit 4 more
|
||||
uint8_t buf[0x44*0x10]; |
||||
int queue_send_len = -1; |
||||
|
||||
void ICACHE_FLASH_ATTR poll_can(void *arg) { |
||||
uint8_t timerRecvData[0x44] = {0}; |
||||
int i = 0; |
||||
int j; |
||||
|
||||
while (i < 0x40) { |
||||
int len = spi_comm("\x01\x00\x00\x00", 4, timerRecvData, 0x40); |
||||
if (len == 0) break; |
||||
if (len > 0x40) { os_printf("SPI LENGTH ERROR!"); break; } |
||||
|
||||
// if it sends it, assume it's valid CAN
|
||||
for (j = 0; j < len; j += 0x10) { |
||||
memcpy(buf + i*0x10, (timerRecvData+4)+j, 0x10); |
||||
i++; |
||||
} |
||||
} |
||||
|
||||
if (i != 0) { |
||||
int ret = espconn_sendto(&inter_conn, buf, i*0x10); |
||||
if (ret != 0) { |
||||
os_printf("send failed: %d\n", ret); |
||||
queue_send_len = i*0x10; |
||||
} else { |
||||
queue_send_len = -1; |
||||
} |
||||
} |
||||
} |
||||
|
||||
int udp_countdown = 0; |
||||
|
||||
static volatile os_timer_t udp_callback; |
||||
void ICACHE_FLASH_ATTR udp_callback_func(void *arg) { |
||||
if (queue_send_len == -1) { |
||||
poll_can(NULL); |
||||
} else { |
||||
int ret = espconn_sendto(&inter_conn, buf, queue_send_len); |
||||
if (ret == 0) { |
||||
queue_send_len = -1; |
||||
} |
||||
} |
||||
if (udp_countdown > 0) { |
||||
os_timer_arm(&udp_callback, 5, 0); |
||||
udp_countdown--; |
||||
} else { |
||||
os_printf("UDP timeout\n"); |
||||
} |
||||
} |
||||
|
||||
void ICACHE_FLASH_ATTR inter_recv_cb(void *arg, char *pusrdata, unsigned short length) { |
||||
remot_info *premot = NULL; |
||||
if (espconn_get_connection_info(&inter_conn,&premot,0) == ESPCONN_OK) { |
||||
inter_conn.proto.udp->remote_port = premot->remote_port; |
||||
inter_conn.proto.udp->remote_ip[0] = premot->remote_ip[0]; |
||||
inter_conn.proto.udp->remote_ip[1] = premot->remote_ip[1]; |
||||
inter_conn.proto.udp->remote_ip[2] = premot->remote_ip[2]; |
||||
inter_conn.proto.udp->remote_ip[3] = premot->remote_ip[3]; |
||||
|
||||
|
||||
if (udp_countdown == 0) { |
||||
os_printf("UDP recv\n"); |
||||
udp_countdown = 200*5; |
||||
|
||||
// start 5 second timer
|
||||
os_timer_disarm(&udp_callback); |
||||
os_timer_setfn(&udp_callback, (os_timer_func_t *)udp_callback_func, NULL); |
||||
os_timer_arm(&udp_callback, 5, 0); |
||||
} else { |
||||
udp_countdown = 200*5; |
||||
} |
||||
} |
||||
} |
||||
|
||||
void ICACHE_FLASH_ATTR wifi_init() { |
||||
// default ssid and password
|
||||
memset(ssid, 0, 32); |
||||
os_sprintf(ssid, "panda-%08x-BROKEN", system_get_chip_id());
|
||||
char password[] = "testing123"; |
||||
|
||||
// fetch secure ssid and password
|
||||
// update, try 3 times
|
||||
for (int i = 0; i < 3; i++) { |
||||
uint8_t digest[SHA_DIGEST_SIZE]; |
||||
char resp[0x20]; |
||||
__spi_comm("\x00\x00\x00\x00\x40\xD0\x00\x00\x00\x00\x20\x00", 0xC, recvData, 0x40); |
||||
memcpy(resp, recvData+1, 0x20); |
||||
|
||||
SHA_hash(resp, 0x1C, digest); |
||||
if (memcmp(digest, resp+0x1C, 4) == 0) { |
||||
// OTP is valid
|
||||
memcpy(ssid+6, resp, 0x10); |
||||
memcpy(password, resp+0x10, 10); |
||||
break; |
||||
} |
||||
os_delay_us(50000); |
||||
} |
||||
|
||||
// start wifi AP
|
||||
wifi_set_opmode(SOFTAP_MODE); |
||||
struct softap_config config; |
||||
wifi_softap_get_config(&config); |
||||
strcpy(config.ssid, ssid);
|
||||
strcpy(config.password, password); |
||||
config.ssid_len = strlen(ssid); |
||||
config.authmode = AUTH_WPA2_PSK; |
||||
config.beacon_interval = 100; |
||||
config.max_connection = 10; |
||||
wifi_softap_set_config(&config); |
||||
|
||||
//set IP
|
||||
wifi_softap_dhcps_stop(); //stop DHCP before setting static IP
|
||||
struct ip_info ip_config; |
||||
IP4_ADDR(&ip_config.ip, 192, 168, 0, 10); |
||||
IP4_ADDR(&ip_config.gw, 0, 0, 0, 0); |
||||
IP4_ADDR(&ip_config.netmask, 255, 255, 255, 0); |
||||
wifi_set_ip_info(SOFTAP_IF, &ip_config); |
||||
int stupid_gateway = 0; |
||||
wifi_softap_set_dhcps_offer_option(OFFER_ROUTER, &stupid_gateway); |
||||
wifi_softap_dhcps_start(); |
||||
|
||||
// setup tcp server
|
||||
tcp_proto.local_port = 1337; |
||||
tcp_conn.type = ESPCONN_TCP; |
||||
tcp_conn.state = ESPCONN_NONE; |
||||
tcp_conn.proto.tcp = &tcp_proto; |
||||
espconn_regist_connectcb(&tcp_conn, tcp_connect_cb); |
||||
espconn_accept(&tcp_conn); |
||||
espconn_regist_time(&tcp_conn, 60, 0); // 60s timeout for all connections
|
||||
|
||||
// setup inter server
|
||||
inter_proto.local_port = 1338; |
||||
const char udp_remote_ip[4] = {255, 255, 255, 255}; |
||||
os_memcpy(inter_proto.remote_ip, udp_remote_ip, 4); |
||||
inter_proto.remote_port = 1338; |
||||
|
||||
inter_conn.type = ESPCONN_UDP; |
||||
inter_conn.proto.udp = &inter_proto; |
||||
|
||||
espconn_regist_recvcb(&inter_conn, inter_recv_cb); |
||||
|
||||
espconn_create(&inter_conn); |
||||
} |
||||
|
||||
#define LOOP_PRIO 2 |
||||
#define QUEUE_SIZE 1 |
||||
static os_event_t my_queue[QUEUE_SIZE]; |
||||
void loop(); |
||||
|
||||
void ICACHE_FLASH_ATTR web_init(); |
||||
void ICACHE_FLASH_ATTR elm327_init(); |
||||
|
||||
void ICACHE_FLASH_ATTR user_init() { |
||||
// init gpio subsystem
|
||||
gpio_init(); |
||||
|
||||
// configure UART TXD to be GPIO1, set as output
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_GPIO1);
|
||||
gpio_output_set(0, 0, (1 << pin), 0); |
||||
|
||||
// configure SPI
|
||||
SpiAttr hSpiAttr; |
||||
hSpiAttr.bitOrder = SpiBitOrder_MSBFirst; |
||||
hSpiAttr.speed = SpiSpeed_10MHz; |
||||
hSpiAttr.mode = SpiMode_Master; |
||||
hSpiAttr.subMode = SpiSubMode_0; |
||||
|
||||
// TODO: is one of these CS?
|
||||
WRITE_PERI_REG(PERIPHS_IO_MUX, 0x105); |
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, 2); // configure io to spi mode
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, 2); // configure io to spi mode
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, 2); // configure io to spi mode
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, 2); // configure io to spi mode
|
||||
SPIInit(SpiNum_HSPI, &hSpiAttr); |
||||
//SPICsPinSelect(SpiNum_HSPI, SpiPinCS_1);
|
||||
|
||||
// configure UART TXD to be GPIO1, set as output
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO5_U, FUNC_GPIO5);
|
||||
gpio_output_set(0, 0, (1 << 5), 0); |
||||
gpio_output_set((1 << 5), 0, 0, 0); |
||||
|
||||
// uart init
|
||||
uart_init(BIT_RATE_115200, BIT_RATE_115200); |
||||
|
||||
// led init
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_GPIO2); |
||||
gpio_output_set(0, (1 << pin), (1 << pin), 0); |
||||
|
||||
os_printf("hello\n"); |
||||
|
||||
// needs SPI
|
||||
wifi_init(); |
||||
|
||||
// support ota upgrades
|
||||
elm327_init(); |
||||
web_init(); |
||||
|
||||
// set gpio high, so LED is off by default
|
||||
for (int i = 0; i < 5; i++) { |
||||
gpio_output_set(0, (1 << pin), 0, 0); |
||||
os_delay_us(50000); |
||||
gpio_output_set((1 << pin), 0, 0, 0); |
||||
os_delay_us(50000); |
||||
} |
||||
|
||||
// jump to OS
|
||||
system_os_task(loop, LOOP_PRIO, my_queue, QUEUE_SIZE); |
||||
system_os_post(LOOP_PRIO, 0, 0); |
||||
} |
||||
|
||||
|
||||
void ICACHE_FLASH_ATTR loop(os_event_t *events) { |
||||
system_os_post(LOOP_PRIO, 0, 0); |
||||
} |
||||
|
@ -0,0 +1,373 @@ |
||||
#include "stdlib.h" |
||||
#include "ets_sys.h" |
||||
#include "osapi.h" |
||||
#include "gpio.h" |
||||
#include "mem.h" |
||||
#include "os_type.h" |
||||
#include "user_interface.h" |
||||
#include "espconn.h" |
||||
#include "upgrade.h" |
||||
|
||||
#include "crypto/rsa.h" |
||||
#include "crypto/sha.h" |
||||
|
||||
#include "obj/gitversion.h" |
||||
#include "obj/cert.h" |
||||
|
||||
#define max(a,b) ((a) > (b) ? (a) : (b)) |
||||
#define min(a,b) ((a) < (b) ? (a) : (b)) |
||||
#define espconn_send_string(conn, x) espconn_send(conn, x, strlen(x)) |
||||
|
||||
#define MAX_RESP 0x800 |
||||
char resp[MAX_RESP]; |
||||
char pageheader[] = "HTTP/1.0 200 OK\nContent-Type: text/html\n\n" |
||||
"<!DOCTYPE html>\n" |
||||
"<html>\n" |
||||
"<head>\n" |
||||
"<title>Panda</title>\n" |
||||
"</head>\n" |
||||
"<body>\n" |
||||
"<pre>This is your comma.ai panda\n\n" |
||||
"It's open source. Find the code <a href=\"https://github.com/commaai/panda\">here</a>\n" |
||||
"Designed to work with our dashcam, <a href=\"http://chffr.comma.ai\">chffr</a>\n"; |
||||
|
||||
char pagefooter[] = "</pre>\n" |
||||
"</body>\n" |
||||
"</html>\n"; |
||||
|
||||
char OK_header[] = "HTTP/1.0 200 OK\nContent-Type: text/html\n\n"; |
||||
|
||||
static struct espconn web_conn; |
||||
static esp_tcp web_proto; |
||||
extern char ssid[]; |
||||
|
||||
char *st_firmware; |
||||
int real_content_length, content_length = 0; |
||||
char *st_firmware_ptr; |
||||
LOCAL os_timer_t ota_reboot_timer; |
||||
|
||||
#define FIRMWARE_SIZE 503808 |
||||
|
||||
typedef struct { |
||||
uint16_t ep; |
||||
uint16_t extra_len; |
||||
union { |
||||
struct { |
||||
uint8_t request_type; |
||||
uint8_t request; |
||||
uint16_t value; |
||||
uint16_t index; |
||||
uint16_t length; |
||||
} control; |
||||
uint8_t data[0x10]; |
||||
} u; |
||||
} usb_msg; |
||||
|
||||
int ICACHE_FLASH_ATTR usb_cmd(int ep, int len, int request, |
||||
int value, int index, char *data) { |
||||
usb_msg usb = {0}; |
||||
|
||||
usb.ep = ep; |
||||
usb.extra_len = (ep == 0) ? 0 : len; |
||||
if (ep == 0) { |
||||
usb.u.control.request_type = 0xc0; |
||||
usb.u.control.request = request; |
||||
usb.u.control.value = value; |
||||
usb.u.control.index = index; |
||||
} else { |
||||
memcpy(&usb.u.data, data, usb.extra_len); |
||||
} |
||||
|
||||
uint32_t recv[0x44/4]; |
||||
spi_comm(&usb, sizeof(usb), recv, 0x40); |
||||
|
||||
return recv[0]; |
||||
} |
||||
|
||||
|
||||
void ICACHE_FLASH_ATTR st_flash() { |
||||
if (st_firmware != NULL) { |
||||
// boot mode
|
||||
os_printf("st_flash: enter boot mode\n"); |
||||
st_set_boot_mode(1); |
||||
|
||||
// echo
|
||||
os_printf("st_flash: wait for echo\n"); |
||||
for (int i = 0; i < 10; i++) { |
||||
os_printf(" attempt: %d\n", i); |
||||
if (usb_cmd(0, 0, 0xb0, 0, 0, NULL) > 0) break; |
||||
} |
||||
|
||||
// unlock flash
|
||||
os_printf("st_flash: unlock flash\n"); |
||||
usb_cmd(0, 0, 0xb1, 0, 0, NULL); |
||||
|
||||
// erase sector 1
|
||||
os_printf("st_flash: erase sector 1\n"); |
||||
usb_cmd(0, 0, 0xb2, 1, 0, NULL); |
||||
|
||||
if (real_content_length >= 16384) { |
||||
// erase sector 2
|
||||
os_printf("st_flash: erase sector 2\n"); |
||||
usb_cmd(0, 0, 0xb2, 2, 0, NULL); |
||||
} |
||||
|
||||
// real content length will always be 0x10 aligned
|
||||
os_printf("st_flash: flashing\n"); |
||||
for (int i = 0; i < real_content_length; i += 0x10) { |
||||
int rl = min(0x10, real_content_length-i); |
||||
usb_cmd(2, rl, 0, 0, 0, &st_firmware[i]); |
||||
system_soft_wdt_feed(); |
||||
} |
||||
|
||||
// reboot into normal mode
|
||||
os_printf("st_flash: rebooting\n"); |
||||
usb_cmd(0, 0, 0xd8, 0, 0, NULL); |
||||
|
||||
// done with this
|
||||
os_free(st_firmware); |
||||
st_firmware = NULL; |
||||
} |
||||
} |
||||
|
||||
typedef enum { |
||||
NOT_STARTED, |
||||
CONNECTION_ESTABLISHED, |
||||
RECEIVING_HEADER, |
||||
RECEIVING_ST_FIRMWARE, |
||||
RECEIVING_ESP_FIRMWARE, |
||||
REBOOTING, |
||||
ERROR |
||||
} web_state_t; |
||||
|
||||
web_state_t state = NOT_STARTED; |
||||
int esp_address, esp_address_erase_limit, start_address; |
||||
|
||||
void ICACHE_FLASH_ATTR hexdump(char *data, int len) { |
||||
int i; |
||||
for (i=0;i<len;i++) { |
||||
if (i!=0 && (i%0x10)==0) os_printf("\n"); |
||||
os_printf("%02X ", data[i]); |
||||
} |
||||
os_printf("\n"); |
||||
} |
||||
|
||||
void ICACHE_FLASH_ATTR st_reset() { |
||||
// reset the ST
|
||||
gpio16_output_conf(); |
||||
gpio16_output_set(0); |
||||
os_delay_us(1000); |
||||
gpio16_output_set(1); |
||||
os_delay_us(10000); |
||||
} |
||||
|
||||
void ICACHE_FLASH_ATTR st_set_boot_mode(int boot_mode) { |
||||
if (boot_mode) { |
||||
// boot mode (pull low)
|
||||
gpio_output_set(0, (1 << 4), (1 << 4), 0); |
||||
st_reset(); |
||||
} else { |
||||
// no boot mode (pull high)
|
||||
gpio_output_set((1 << 4), 0, (1 << 4), 0); |
||||
st_reset(); |
||||
} |
||||
|
||||
// float boot pin
|
||||
gpio_output_set(0, 0, 0, (1 << 4)); |
||||
} |
||||
|
||||
static void ICACHE_FLASH_ATTR web_rx_cb(void *arg, char *data, uint16_t len) { |
||||
int i; |
||||
struct espconn *conn = (struct espconn *)arg; |
||||
if (state == CONNECTION_ESTABLISHED) { |
||||
state = RECEIVING_HEADER; |
||||
os_printf("%s %d\n", data, len); |
||||
|
||||
// index
|
||||
if (memcmp(data, "GET / ", 6) == 0) { |
||||
memset(resp, 0, MAX_RESP); |
||||
|
||||
strcpy(resp, pageheader); |
||||
ets_strcat(resp, "\nssid: "); |
||||
ets_strcat(resp, ssid); |
||||
ets_strcat(resp, "\n"); |
||||
|
||||
ets_strcat(resp, "\nst version: "); |
||||
uint32_t recvData[0x11]; |
||||
int len = spi_comm("\x00\x00\x00\x00\x40\xD6\x00\x00\x00\x00\x40\x00", 0xC, recvData, 0x40); |
||||
ets_memcpy(resp+strlen(resp), recvData+1, len); |
||||
|
||||
ets_strcat(resp, "\nesp version: "); |
||||
ets_strcat(resp, gitversion); |
||||
uint8_t current = system_upgrade_userbin_check(); |
||||
if (current == UPGRADE_FW_BIN1) { |
||||
ets_strcat(resp, "\nesp flash file: user2.bin"); |
||||
} else { |
||||
ets_strcat(resp, "\nesp flash file: user1.bin"); |
||||
} |
||||
|
||||
ets_strcat(resp,"\nSet USB Mode:" |
||||
"<button onclick=\"var xhr = new XMLHttpRequest(); xhr.open('GET', 'set_property?usb_mode=0'); xhr.send()\" type='button'>Client</button>" |
||||
"<button onclick=\"var xhr = new XMLHttpRequest(); xhr.open('GET', 'set_property?usb_mode=1'); xhr.send()\" type='button'>CDP</button>" |
||||
"<button onclick=\"var xhr = new XMLHttpRequest(); xhr.open('GET', 'set_property?usb_mode=2'); xhr.send()\" type='button'>DCP</button>\n"); |
||||
|
||||
ets_strcat(resp, pagefooter); |
||||
|
||||
espconn_send_string(&web_conn, resp); |
||||
espconn_disconnect(conn); |
||||
|
||||
} else if (memcmp(data, "GET /set_property?usb_mode=", 27) == 0) { |
||||
char mode_value = data[27] - '0'; |
||||
if (mode_value >= '\x00' && mode_value <= '\x02') { |
||||
memset(resp, 0, MAX_RESP); |
||||
char set_usb_mode_packet[] = "\x00\x00\x00\x00\x40\xE6\x00\x00\x00\x00\x40\x00"; |
||||
set_usb_mode_packet[6] = mode_value; |
||||
uint32_t recvData[1]; |
||||
spi_comm(set_usb_mode_packet, 0xC, recvData, 0); |
||||
os_sprintf(resp, "%sUSB Mode set to %02x\n\n", OK_header, mode_value); |
||||
espconn_send_string(&web_conn, resp); |
||||
espconn_disconnect(conn); |
||||
}
|
||||
} else if (memcmp(data, "PUT /stupdate ", 14) == 0) { |
||||
os_printf("init st firmware\n"); |
||||
char *cl = strstr(data, "Content-Length: "); |
||||
if (cl != NULL) { |
||||
// get content length
|
||||
cl += strlen("Content-Length: "); |
||||
content_length = skip_atoi(&cl); |
||||
os_printf("with content length %d\n", content_length); |
||||
|
||||
// should be small enough to fit in RAM
|
||||
real_content_length = (content_length+0xF)&(~0xF); |
||||
st_firmware_ptr = st_firmware = os_malloc(real_content_length); |
||||
memset(st_firmware, 0, real_content_length); |
||||
state = RECEIVING_ST_FIRMWARE; |
||||
} |
||||
|
||||
} else if ((memcmp(data, "PUT /espupdate1 ", 16) == 0) || |
||||
(memcmp(data, "PUT /espupdate2 ", 16) == 0)) { |
||||
// 0x1000 = user1.bin
|
||||
// 0x81000 = user2.bin
|
||||
// 0x3FE000 = blank.bin
|
||||
os_printf("init esp firmware\n"); |
||||
char *cl = strstr(data, "Content-Length: "); |
||||
if (cl != NULL) { |
||||
// get content length
|
||||
cl += strlen("Content-Length: "); |
||||
content_length = skip_atoi(&cl); |
||||
os_printf("with content length %d\n", content_length); |
||||
|
||||
// setup flashing
|
||||
uint8_t current = system_upgrade_userbin_check(); |
||||
if (data[14] == '2' && current == UPGRADE_FW_BIN1) { |
||||
os_printf("flashing boot2.bin\n"); |
||||
state = RECEIVING_ESP_FIRMWARE; |
||||
esp_address = 4*1024 + FIRMWARE_SIZE + 16*1024 + 4*1024; |
||||
} else if (data[14] == '1' && current == UPGRADE_FW_BIN2) { |
||||
os_printf("flashing boot1.bin\n"); |
||||
state = RECEIVING_ESP_FIRMWARE; |
||||
esp_address = 4*1024; |
||||
} else { |
||||
espconn_send_string(&web_conn, "HTTP/1.0 404 Not Found\nContent-Type: text/html\n\nwrong!\n"); |
||||
espconn_disconnect(conn); |
||||
} |
||||
esp_address_erase_limit = esp_address; |
||||
start_address = esp_address; |
||||
} |
||||
} else { |
||||
espconn_send_string(&web_conn, "HTTP/1.0 404 Not Found\nContent-Type: text/html\n\n404 Not Found!\n"); |
||||
espconn_disconnect(conn); |
||||
} |
||||
} else if (state == RECEIVING_ST_FIRMWARE) { |
||||
os_printf("receiving st firmware: %d/%d\n", len, content_length); |
||||
memcpy(st_firmware_ptr, data, min(content_length, len)); |
||||
st_firmware_ptr += len; |
||||
content_length -= len; |
||||
|
||||
if (content_length <= 0 && real_content_length > 1000) { |
||||
state = NOT_STARTED; |
||||
os_printf("done!\n"); |
||||
espconn_send_string(&web_conn, "HTTP/1.0 200 OK\nContent-Type: text/html\n\nsuccess!\n"); |
||||
espconn_disconnect(conn); |
||||
|
||||
// reboot
|
||||
os_printf("Scheduling st_flash in 100ms.\n"); |
||||
os_timer_disarm(&ota_reboot_timer); |
||||
os_timer_setfn(&ota_reboot_timer, (os_timer_func_t *)st_flash, NULL); |
||||
os_timer_arm(&ota_reboot_timer, 100, 0); |
||||
} |
||||
} else if (state == RECEIVING_ESP_FIRMWARE) { |
||||
if ((esp_address+len) < (start_address + FIRMWARE_SIZE)) { |
||||
os_printf("receiving esp firmware: %d/%d -- 0x%x - 0x%x\n", len, content_length, |
||||
esp_address, esp_address_erase_limit); |
||||
content_length -= len; |
||||
while (esp_address_erase_limit < (esp_address + len)) { |
||||
os_printf("erasing 0x%X\n", esp_address_erase_limit); |
||||
spi_flash_erase_sector(esp_address_erase_limit / SPI_FLASH_SEC_SIZE); |
||||
esp_address_erase_limit += SPI_FLASH_SEC_SIZE; |
||||
} |
||||
SpiFlashOpResult res = spi_flash_write(esp_address, data, len); |
||||
if (res != SPI_FLASH_RESULT_OK) { |
||||
os_printf("flash fail @ 0x%x\n", esp_address); |
||||
} |
||||
esp_address += len; |
||||
|
||||
if (content_length == 0) { |
||||
|
||||
char digest[SHA_DIGEST_SIZE]; |
||||
uint32_t rsa[RSANUMBYTES/4]; |
||||
uint32_t dat[0x80/4]; |
||||
int ll; |
||||
spi_flash_read(esp_address-RSANUMBYTES, rsa, RSANUMBYTES); |
||||
|
||||
// 32-bit aligned accesses only
|
||||
SHA_CTX ctx; |
||||
SHA_init(&ctx); |
||||
for (ll = start_address; ll < esp_address-RSANUMBYTES; ll += 0x80) { |
||||
spi_flash_read(ll, dat, 0x80); |
||||
SHA_update(&ctx, dat, min((esp_address-RSANUMBYTES)-ll, 0x80)); |
||||
} |
||||
memcpy(digest, SHA_final(&ctx), SHA_DIGEST_SIZE); |
||||
|
||||
if (RSA_verify(&releaseesp_rsa_key, rsa, RSANUMBYTES, digest, SHA_DIGEST_SIZE) || |
||||
#ifdef ALLOW_DEBUG |
||||
RSA_verify(&debugesp_rsa_key, rsa, RSANUMBYTES, digest, SHA_DIGEST_SIZE) |
||||
#else |
||||
false |
||||
#endif |
||||
) { |
||||
os_printf("RSA verify success!\n"); |
||||
espconn_send_string(&web_conn, "HTTP/1.0 200 OK\nContent-Type: text/html\n\nsuccess!\n"); |
||||
system_upgrade_flag_set(UPGRADE_FLAG_FINISH); |
||||
|
||||
// reboot
|
||||
os_printf("Scheduling reboot.\n"); |
||||
os_timer_disarm(&ota_reboot_timer); |
||||
os_timer_setfn(&ota_reboot_timer, (os_timer_func_t *)system_upgrade_reboot, NULL); |
||||
os_timer_arm(&ota_reboot_timer, 2000, 0); |
||||
} else { |
||||
os_printf("RSA verify FAILURE\n"); |
||||
espconn_send_string(&web_conn, "HTTP/1.0 500 Internal Server Error\nContent-Type: text/html\n\nrsa verify fail\n"); |
||||
} |
||||
espconn_disconnect(conn); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
void ICACHE_FLASH_ATTR web_tcp_connect_cb(void *arg) { |
||||
state = CONNECTION_ESTABLISHED; |
||||
struct espconn *conn = (struct espconn *)arg; |
||||
espconn_set_opt(&web_conn, ESPCONN_NODELAY); |
||||
espconn_regist_recvcb(conn, web_rx_cb); |
||||
} |
||||
|
||||
void ICACHE_FLASH_ATTR web_init() { |
||||
web_proto.local_port = 80; |
||||
web_conn.type = ESPCONN_TCP; |
||||
web_conn.state = ESPCONN_NONE; |
||||
web_conn.proto.tcp = &web_proto; |
||||
espconn_regist_connectcb(&web_conn, web_tcp_connect_cb); |
||||
espconn_accept(&web_conn); |
||||
} |
||||
|
After Width: | Height: | Size: 4.0 KiB |
@ -0,0 +1,15 @@ |
||||
-----BEGIN RSA PRIVATE KEY----- |
||||
MIICXQIBAAKBgQC948lnRo4x44Rd7Y8bQAML4aKDC4XRx958fHV8K6+FbCaP1Z42 |
||||
U2kX0yygak0LjoDutpgObmGHZA+Iz3HeUD6VGjr/teN24vPk+A95cRsjt8rgmGQ9 |
||||
6HNjaNgjR+gl1F9XxFimMzir82Xpl1ekTueJNXa7ia5HVH1nFdiksOKHGQIDAQAB |
||||
AoGAQuPw2I6EHJLW1/eNB75e1FqhUqRGeYV8nEGDaUBCTi+wzc4kM2LijF/5QnDv |
||||
vvht9qkfm0XK2VSoHDtnEzcVM/l1ksb68n4R/1nUooAWY6cQI7dCSk/A6yS1EJFg |
||||
BXsgGbT/65khw9pzBW2zVtMVcVNWFayqfCO1I9WcDdA1x1kCQQDfrhoZTZNoDEUE |
||||
JKM4fiUdWr1h3Aw8KLJFFexSWeGDwo+qqnujYcKWkHa9qaH1RG5x8Kir9s9Oi4Js |
||||
mzKwov8fAkEA2VPJPWxJ4vVQpXle6wC1nyoL7s739yxMWFcabvkzDDhlIVBNdVJd |
||||
gZKsFWV7QnVNdDMjn9D27FwKu3i2D+kKxwJBANp1SMojqO765MEKI1t+YDNONx6H |
||||
cm+i85Fjuv4nCIjOEdCGVuCYDxtMFpxgO2y3HAMuHx5sm8XDnWsDHLvFRdMCQD7V |
||||
XqWHnYUk8AAnqy2+ssQl3/VXmZG5GQmhhV74Za3u0C5ljT+SZL6FrYMyKAT67T3f |
||||
WzllrT6BDglNyTWoZxkCQQCt0XSoGM3603GGYNt6AUlGSgtXSo/2Px7odGUtQoKA |
||||
FH9q6FVMYpQJ38spZxIGufZJmLP8LLg6YIWJj1F+akxr |
||||
-----END RSA PRIVATE KEY----- |
@ -0,0 +1 @@ |
||||
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC948lnRo4x44Rd7Y8bQAML4aKDC4XRx958fHV8K6+FbCaP1Z42U2kX0yygak0LjoDutpgObmGHZA+Iz3HeUD6VGjr/teN24vPk+A95cRsjt8rgmGQ96HNjaNgjR+gl1F9XxFimMzir82Xpl1ekTueJNXa7ia5HVH1nFdiksOKHGQ== batman@y840 |
@ -0,0 +1,15 @@ |
||||
-----BEGIN RSA PRIVATE KEY----- |
||||
MIICXAIBAAKBgQCjIHvrSCWN0Nec6ozbImYik30PIF7JSWgdwDKTxSJ05RM3pj5E |
||||
LQEGt3qcaVrTokO68tpt5Gu1p6ZsNqWg7iVTW9M7Qj7IH45YDzQP/PSRjgSosQA6 |
||||
6f5Gokba5QrW38myqimvj+0p+YH+CNGCBRlTUQGCO8uLCspMZneRSLPW9QIDAQAB |
||||
AoGADaUn+HRef9BaWMvd4G6uMHI54cwJYbj8NpDfKjExQqnuw5bqWnWRQmiSnwbJ |
||||
DC7kj3zE/LBAuj890ot3q1CAWqh47ZICZfoX9Qbi5TpvIHFCGy6YkOliF6iIQhR2 |
||||
4+zNKTAA0zNKskOM25PdI+grK1Ni/bEofSA6TrqvEwsmxnkCQQDVp9FUUor2Bo/h |
||||
/3oAIP51LTw7vfpztYbJr+BDV63czV2DLXzSwzeNrwH4sA3oy1mjUgMBBgAarNGE |
||||
DYlc4H5jAkEAw3UCHzzXPlxkw2QGp7nBly5y3p80Uqc31NuYz8rdX/U8KTngi2No |
||||
Ft/SGCEXNpeYbToj+WK3RJJ2Ey0mK8+IxwJAcpGd/5CPsaQNLcw4WK9Yo+8Q2Jxk |
||||
G/4gfDCSmqn+smNxnLEcuUwzkwdgkEGgA9BfjeOhdsAH+EXpx90WZrZ/LwJBAK0k |
||||
jq+rTqUQZbZsejTEKYjJ/bnV4BzDwoKN0Q1pkLc7X4LJoW74rTFuLgdv8MdMfRtt |
||||
IIb/eoeFEpGkMicnHesCQHgR7BTUGBM6Uxam7RCdsgVsxoHBma21E/44ivWUMZzN |
||||
3oVt0mPnjS4speOlqwED5pCJ7yw7jwLPFMs8kNxuIKU= |
||||
-----END RSA PRIVATE KEY----- |
@ -0,0 +1 @@ |
||||
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQCjIHvrSCWN0Nec6ozbImYik30PIF7JSWgdwDKTxSJ05RM3pj5ELQEGt3qcaVrTokO68tpt5Gu1p6ZsNqWg7iVTW9M7Qj7IH45YDzQP/PSRjgSosQA66f5Gokba5QrW38myqimvj+0p+YH+CNGCBRlTUQGCO8uLCspMZneRSLPW9Q== batman@y840 |
@ -0,0 +1 @@ |
||||
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDGN9GU2nOc0kKq6vdZI5qUMzHt234ngqofrgCFFxL0D2Whex0zACp9gar0HZp+bvtpoSgU/Ev8wexNKr+A9QTradljiuxi5ctrOra9k+wxqNj63Wrcu4+wU5UnJEVf/buV4jCOFffMT8z3PO4imt8LzHuEIC/m/ASKVYyvuvBRQQ== batman@y840 |
@ -0,0 +1 @@ |
||||
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDN4pVyGuJJSde1l3Fjay8qPxog09DsAJZtYPk+armoYO1L6YKReUTcMNyHQYZZMZFmhCdgjCgTIF2QYWMoP4KSe8l6JF04YPP51dIgefc6UXjtlSI8Pyutr0v9xXjSfsVm3RAJxDSHgzs9AoMsluKCL+LhAR1nd7cuHXITJ80O4w== batman@y840 |
@ -0,0 +1,18 @@ |
||||
ifeq ($(RELEASE),1) |
||||
BUILD_TYPE = "RELEASE"
|
||||
else |
||||
BUILD_TYPE = "DEBUG"
|
||||
endif |
||||
|
||||
ifneq ($(wildcard ../.git/HEAD),) |
||||
obj/gitversion.h: ../VERSION ../.git/HEAD ../.git/index |
||||
echo "const uint8_t gitversion[] = \"$(shell cat ../VERSION)-$(shell git rev-parse --short=8 HEAD)-$(BUILD_TYPE)\";" > $@
|
||||
else |
||||
ifneq ($(wildcard ../../.git/modules/panda/HEAD),) |
||||
obj/gitversion.h: ../VERSION ../../.git/modules/panda/HEAD ../../.git/modules/panda/index |
||||
echo "const uint8_t gitversion[] = \"$(shell cat ../VERSION)-$(shell git rev-parse --short=8 HEAD)-$(BUILD_TYPE)\";" > $@
|
||||
else |
||||
obj/gitversion.h: ../VERSION |
||||
echo "const uint8_t gitversion[] = \"$(shell cat ../VERSION)-unknown-$(BUILD_TYPE)\";" > $@
|
||||
endif |
||||
endif |
@ -0,0 +1,46 @@ |
||||
#!/usr/bin/env python |
||||
import sys |
||||
import struct |
||||
from Crypto.PublicKey import RSA |
||||
|
||||
def egcd(a, b): |
||||
if a == 0: |
||||
return (b, 0, 1) |
||||
else: |
||||
g, y, x = egcd(b % a, a) |
||||
return (g, x - (b // a) * y, y) |
||||
|
||||
def modinv(a, m): |
||||
g, x, y = egcd(a, m) |
||||
if g != 1: |
||||
raise Exception('modular inverse does not exist') |
||||
else: |
||||
return x % m |
||||
|
||||
def to_c_string(x): |
||||
mod = (hex(x)[2:-1].rjust(0x100, '0')) |
||||
hh = ''.join('\\x'+mod[i:i+2] for i in range(0, 0x100, 2)) |
||||
return hh |
||||
|
||||
def to_c_uint32(x): |
||||
nums = [] |
||||
for i in range(0x20): |
||||
nums.append(x%(2**32)) |
||||
x /= (2**32) |
||||
return "{"+'U,'.join(map(str, nums))+"U}" |
||||
|
||||
for fn in sys.argv[1:]: |
||||
rsa = RSA.importKey(open(fn).read()) |
||||
rr = pow(2**1024, 2, rsa.n) |
||||
n0inv = 2**32 - modinv(rsa.n, 2**32) |
||||
|
||||
cname = fn.split("/")[-1].split(".")[0] + "_rsa_key" |
||||
|
||||
print 'RSAPublicKey '+cname+' = {.len = 0x20,' |
||||
print ' .n0inv = %dU,' % n0inv |
||||
print ' .n = %s,' % to_c_uint32(rsa.n) |
||||
print ' .rr = %s,' % to_c_uint32(rr) |
||||
print ' .exponent = %d,' % rsa.e |
||||
print '};' |
||||
|
||||
|
@ -0,0 +1,63 @@ |
||||
/*
|
||||
* Copyright 2007 The Android Open Source Project |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions are met: |
||||
* * Redistributions of source code must retain the above copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* * Redistributions in binary form must reproduce the above copyright |
||||
* notice, this list of conditions and the following disclaimer in the |
||||
* documentation and/or other materials provided with the distribution. |
||||
* * Neither the name of Google Inc. nor the names of its contributors may |
||||
* be used to endorse or promote products derived from this software |
||||
* without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR |
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO |
||||
* EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; |
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
*/ |
||||
|
||||
#ifndef SYSTEM_CORE_INCLUDE_MINCRYPT_HASH_INTERNAL_H_ |
||||
#define SYSTEM_CORE_INCLUDE_MINCRYPT_HASH_INTERNAL_H_ |
||||
|
||||
#include "stdint.h" |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif // __cplusplus
|
||||
|
||||
struct HASH_CTX; // forward decl
|
||||
|
||||
typedef struct HASH_VTAB { |
||||
void (* const init)(struct HASH_CTX*); |
||||
void (* const update)(struct HASH_CTX*, const void*, int); |
||||
const uint8_t* (* const final)(struct HASH_CTX*); |
||||
const uint8_t* (* const hash)(const void*, int, uint8_t*); |
||||
int size; |
||||
} HASH_VTAB; |
||||
|
||||
typedef struct HASH_CTX { |
||||
const HASH_VTAB * f; |
||||
uint64_t count; |
||||
uint8_t buf[64]; |
||||
uint32_t state[8]; // upto SHA2
|
||||
} HASH_CTX; |
||||
|
||||
#define HASH_init(ctx) (ctx)->f->init(ctx) |
||||
#define HASH_update(ctx, data, len) (ctx)->f->update(ctx, data, len) |
||||
#define HASH_final(ctx) (ctx)->f->final(ctx) |
||||
#define HASH_hash(data, len, digest) (ctx)->f->hash(data, len, digest) |
||||
#define HASH_size(ctx) (ctx)->f->size |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif // __cplusplus
|
||||
|
||||
#endif // SYSTEM_CORE_INCLUDE_MINCRYPT_HASH_INTERNAL_H_
|
@ -0,0 +1,294 @@ |
||||
/* rsa.c
|
||||
** |
||||
** Copyright 2012, The Android Open Source Project |
||||
** |
||||
** Redistribution and use in source and binary forms, with or without |
||||
** modification, are permitted provided that the following conditions are met: |
||||
** * Redistributions of source code must retain the above copyright |
||||
** notice, this list of conditions and the following disclaimer. |
||||
** * Redistributions in binary form must reproduce the above copyright |
||||
** notice, this list of conditions and the following disclaimer in the |
||||
** documentation and/or other materials provided with the distribution. |
||||
** * Neither the name of Google Inc. nor the names of its contributors may |
||||
** be used to endorse or promote products derived from this software |
||||
** without specific prior written permission. |
||||
** |
||||
** THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR |
||||
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
||||
** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO |
||||
** EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
||||
** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; |
||||
** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
||||
** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
||||
** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
||||
** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
*/ |
||||
|
||||
#include "rsa.h" |
||||
#include "sha.h" |
||||
|
||||
// a[] -= mod
|
||||
static void subM(const RSAPublicKey* key, |
||||
uint32_t* a) { |
||||
int64_t A = 0; |
||||
int i; |
||||
for (i = 0; i < key->len; ++i) { |
||||
A += (uint64_t)a[i] - key->n[i]; |
||||
a[i] = (uint32_t)A; |
||||
A >>= 32; |
||||
} |
||||
} |
||||
|
||||
// return a[] >= mod
|
||||
static int geM(const RSAPublicKey* key, |
||||
const uint32_t* a) { |
||||
int i; |
||||
for (i = key->len; i;) { |
||||
--i; |
||||
if (a[i] < key->n[i]) return 0; |
||||
if (a[i] > key->n[i]) return 1; |
||||
} |
||||
return 1; // equal
|
||||
} |
||||
|
||||
// montgomery c[] += a * b[] / R % mod
|
||||
static void montMulAdd(const RSAPublicKey* key, |
||||
uint32_t* c, |
||||
const uint32_t a, |
||||
const uint32_t* b) { |
||||
uint64_t A = (uint64_t)a * b[0] + c[0]; |
||||
uint32_t d0 = (uint32_t)A * key->n0inv; |
||||
uint64_t B = (uint64_t)d0 * key->n[0] + (uint32_t)A; |
||||
int i; |
||||
|
||||
for (i = 1; i < key->len; ++i) { |
||||
A = (A >> 32) + (uint64_t)a * b[i] + c[i]; |
||||
B = (B >> 32) + (uint64_t)d0 * key->n[i] + (uint32_t)A; |
||||
c[i - 1] = (uint32_t)B; |
||||
} |
||||
|
||||
A = (A >> 32) + (B >> 32); |
||||
|
||||
c[i - 1] = (uint32_t)A; |
||||
|
||||
if (A >> 32) { |
||||
subM(key, c); |
||||
} |
||||
} |
||||
|
||||
// montgomery c[] = a[] * b[] / R % mod
|
||||
static void montMul(const RSAPublicKey* key, |
||||
uint32_t* c, |
||||
const uint32_t* a, |
||||
const uint32_t* b) { |
||||
int i; |
||||
for (i = 0; i < key->len; ++i) { |
||||
c[i] = 0; |
||||
} |
||||
for (i = 0; i < key->len; ++i) { |
||||
montMulAdd(key, c, a[i], b); |
||||
} |
||||
} |
||||
|
||||
// In-place public exponentiation.
|
||||
// Input and output big-endian byte array in inout.
|
||||
static void modpow(const RSAPublicKey* key, |
||||
uint8_t* inout) { |
||||
uint32_t a[RSANUMWORDS]; |
||||
uint32_t aR[RSANUMWORDS]; |
||||
uint32_t aaR[RSANUMWORDS]; |
||||
uint32_t* aaa = 0; |
||||
int i; |
||||
|
||||
// Convert from big endian byte array to little endian word array.
|
||||
for (i = 0; i < key->len; ++i) { |
||||
uint32_t tmp = |
||||
(inout[((key->len - 1 - i) * 4) + 0] << 24) | |
||||
(inout[((key->len - 1 - i) * 4) + 1] << 16) | |
||||
(inout[((key->len - 1 - i) * 4) + 2] << 8) | |
||||
(inout[((key->len - 1 - i) * 4) + 3] << 0); |
||||
a[i] = tmp; |
||||
} |
||||
|
||||
if (key->exponent == 65537) { |
||||
aaa = aaR; // Re-use location.
|
||||
montMul(key, aR, a, key->rr); // aR = a * RR / R mod M
|
||||
for (i = 0; i < 16; i += 2) { |
||||
montMul(key, aaR, aR, aR); // aaR = aR * aR / R mod M
|
||||
montMul(key, aR, aaR, aaR); // aR = aaR * aaR / R mod M
|
||||
} |
||||
montMul(key, aaa, aR, a); // aaa = aR * a / R mod M
|
||||
} else if (key->exponent == 3) { |
||||
aaa = aR; // Re-use location.
|
||||
montMul(key, aR, a, key->rr); /* aR = a * RR / R mod M */ |
||||
montMul(key, aaR, aR, aR); /* aaR = aR * aR / R mod M */ |
||||
montMul(key, aaa, aaR, a); /* aaa = aaR * a / R mod M */ |
||||
} |
||||
|
||||
// Make sure aaa < mod; aaa is at most 1x mod too large.
|
||||
if (geM(key, aaa)) { |
||||
subM(key, aaa); |
||||
} |
||||
|
||||
// Convert to bigendian byte array
|
||||
for (i = key->len - 1; i >= 0; --i) { |
||||
uint32_t tmp = aaa[i]; |
||||
*inout++ = tmp >> 24; |
||||
*inout++ = tmp >> 16; |
||||
*inout++ = tmp >> 8; |
||||
*inout++ = tmp >> 0; |
||||
} |
||||
} |
||||
|
||||
// Expected PKCS1.5 signature padding bytes, for a keytool RSA signature.
|
||||
// Has the 0-length optional parameter encoded in the ASN1 (as opposed to the
|
||||
// other flavor which omits the optional parameter entirely). This code does not
|
||||
// accept signatures without the optional parameter.
|
||||
|
||||
/*
|
||||
static const uint8_t sha_padding[RSANUMBYTES] = { |
||||
0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
||||
0xff, 0xff, 0xff, 0xff, 0x00, 0x30, 0x21, 0x30, |
||||
0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, |
||||
0x05, 0x00, 0x04, 0x14, |
||||
|
||||
// 20 bytes of hash go here.
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 |
||||
}; |
||||
*/ |
||||
|
||||
static const uint8_t sha_padding_1024[RSANUMBYTES] = { |
||||
0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
||||
0xff, 0xff, 0xff, 0x00, |
||||
|
||||
// 20 bytes of hash go here.
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 |
||||
}; |
||||
|
||||
// SHA-1 of PKCS1.5 signature sha_padding for 2048 bit, as above.
|
||||
// At the location of the bytes of the hash all 00 are hashed.
|
||||
/*static const uint8_t kExpectedPadShaRsa2048[SHA_DIGEST_SIZE] = {
|
||||
0xdc, 0xbd, 0xbe, 0x42, 0xd5, 0xf5, 0xa7, 0x2e, |
||||
0x6e, 0xfc, 0xf5, 0x5d, 0xaf, 0x9d, 0xea, 0x68, |
||||
0x7c, 0xfb, 0xf1, 0x67 |
||||
};*/ |
||||
|
||||
// Verify a 2048-bit RSA PKCS1.5 signature against an expected hash.
|
||||
// Both e=3 and e=65537 are supported. hash_len may be
|
||||
// SHA_DIGEST_SIZE (== 20) to indicate a SHA-1 hash, or
|
||||
// SHA256_DIGEST_SIZE (== 32) to indicate a SHA-256 hash. No other
|
||||
// values are supported.
|
||||
//
|
||||
// Returns 1 on successful verification, 0 on failure.
|
||||
int RSA_verify(const RSAPublicKey *key, |
||||
const uint8_t *signature, |
||||
const int len, |
||||
const uint8_t *hash, |
||||
const int hash_len) { |
||||
uint8_t buf[RSANUMBYTES]; |
||||
int i; |
||||
//const uint8_t* padding_hash;
|
||||
|
||||
if (key->len != RSANUMWORDS) { |
||||
return 0; // Wrong key passed in.
|
||||
} |
||||
|
||||
if (len != sizeof(buf)) { |
||||
return 0; // Wrong input length.
|
||||
} |
||||
|
||||
if (hash_len != SHA_DIGEST_SIZE) { |
||||
return 0; // Unsupported hash.
|
||||
} |
||||
|
||||
if (key->exponent != 3 && key->exponent != 65537) { |
||||
return 0; // Unsupported exponent.
|
||||
} |
||||
|
||||
for (i = 0; i < len; ++i) { // Copy input to local workspace.
|
||||
buf[i] = signature[i]; |
||||
} |
||||
|
||||
modpow(key, buf); // In-place exponentiation.
|
||||
|
||||
#ifdef TEST_RSA |
||||
printf("sig\n"); |
||||
for (i=0;i<len;i++) { if(i!=0 && i%0x10 == 0) printf("\n"); printf("%02X ", signature[i]); } printf("\n"); |
||||
printf("hash\n"); |
||||
for (i=0;i<hash_len;i++) { if(i!=0 && i%0x10 == 0) printf("\n"); printf("%02X ", hash[i]); } printf("\n"); |
||||
printf("out\n"); |
||||
for (i=0;i<RSANUMBYTES;i++) { if(i!=0 && i%0x10 == 0) printf("\n"); printf("%02X ", buf[i]); } printf("\n"); |
||||
printf("target\n"); |
||||
for (i=0;i<RSANUMBYTES;i++) { if(i!=0 && i%0x10 == 0) printf("\n"); printf("%02X ", sha_padding_1024[i]); } printf("\n"); |
||||
#endif |
||||
|
||||
// Xor sha portion, so it all becomes 00 iff equal.
|
||||
for (i = len - hash_len; i < len; ++i) { |
||||
buf[i] ^= *hash++; |
||||
} |
||||
|
||||
// Hash resulting buf, in-place.
|
||||
/*switch (hash_len) {
|
||||
case SHA_DIGEST_SIZE: |
||||
padding_hash = kExpectedPadShaRsa2048; |
||||
SHA_hash(buf, len, buf); |
||||
break; |
||||
default: |
||||
return 0; |
||||
} |
||||
|
||||
|
||||
// Compare against expected hash value.
|
||||
for (i = 0; i < hash_len; ++i) { |
||||
if (buf[i] != padding_hash[i]) { |
||||
return 0; |
||||
} |
||||
}*/ |
||||
|
||||
for (i = 0; i < RSANUMBYTES; ++i) { |
||||
if (buf[i] != sha_padding_1024[i]) { |
||||
return 0; |
||||
} |
||||
} |
||||
|
||||
return 1; // All checked out OK.
|
||||
} |
@ -0,0 +1,58 @@ |
||||
/* rsa.h
|
||||
** |
||||
** Copyright 2008, The Android Open Source Project |
||||
** |
||||
** Redistribution and use in source and binary forms, with or without |
||||
** modification, are permitted provided that the following conditions are met: |
||||
** * Redistributions of source code must retain the above copyright |
||||
** notice, this list of conditions and the following disclaimer. |
||||
** * Redistributions in binary form must reproduce the above copyright |
||||
** notice, this list of conditions and the following disclaimer in the |
||||
** documentation and/or other materials provided with the distribution. |
||||
** * Neither the name of Google Inc. nor the names of its contributors may |
||||
** be used to endorse or promote products derived from this software |
||||
** without specific prior written permission. |
||||
** |
||||
** THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR |
||||
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
||||
** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO |
||||
** EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
||||
** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; |
||||
** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
||||
** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
||||
** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
||||
** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
*/ |
||||
|
||||
#ifndef SYSTEM_CORE_INCLUDE_MINCRYPT_RSA_H_ |
||||
#define SYSTEM_CORE_INCLUDE_MINCRYPT_RSA_H_ |
||||
|
||||
#include "stdint.h" |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
#define RSANUMBYTES 128 /* 1024 bit key length */ |
||||
#define RSANUMWORDS (RSANUMBYTES / sizeof(uint32_t)) |
||||
|
||||
typedef struct RSAPublicKey { |
||||
int len; /* Length of n[] in number of uint32_t */ |
||||
uint32_t n0inv; /* -1 / n[0] mod 2^32 */ |
||||
uint32_t n[RSANUMWORDS]; /* modulus as little endian array */ |
||||
uint32_t rr[RSANUMWORDS]; /* R^2 as little endian array */ |
||||
int exponent; /* 3 or 65537 */ |
||||
} RSAPublicKey; |
||||
|
||||
int RSA_verify(const RSAPublicKey *key, |
||||
const uint8_t* signature, |
||||
const int len, |
||||
const uint8_t* hash, |
||||
const int hash_len); |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif // SYSTEM_CORE_INCLUDE_MINCRYPT_RSA_H_
|
@ -0,0 +1,153 @@ |
||||
/* sha.c
|
||||
** |
||||
** Copyright 2013, The Android Open Source Project |
||||
** |
||||
** Redistribution and use in source and binary forms, with or without |
||||
** modification, are permitted provided that the following conditions are met: |
||||
** * Redistributions of source code must retain the above copyright |
||||
** notice, this list of conditions and the following disclaimer. |
||||
** * Redistributions in binary form must reproduce the above copyright |
||||
** notice, this list of conditions and the following disclaimer in the |
||||
** documentation and/or other materials provided with the distribution. |
||||
** * Neither the name of Google Inc. nor the names of its contributors may |
||||
** be used to endorse or promote products derived from this software |
||||
** without specific prior written permission. |
||||
** |
||||
** THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR |
||||
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
||||
** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO |
||||
** EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
||||
** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; |
||||
** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
||||
** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
||||
** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
||||
** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
*/ |
||||
|
||||
// Optimized for minimal code size.
|
||||
|
||||
void *memcpy(void *str1, const void *str2, unsigned int n); |
||||
|
||||
#include "sha.h" |
||||
|
||||
#define rol(bits, value) (((value) << (bits)) | ((value) >> (32 - (bits)))) |
||||
|
||||
static void SHA1_Transform(SHA_CTX* ctx) { |
||||
uint32_t W[80]; |
||||
uint32_t A, B, C, D, E; |
||||
uint8_t* p = ctx->buf; |
||||
int t; |
||||
|
||||
for(t = 0; t < 16; ++t) { |
||||
uint32_t tmp = *p++ << 24; |
||||
tmp |= *p++ << 16; |
||||
tmp |= *p++ << 8; |
||||
tmp |= *p++; |
||||
W[t] = tmp; |
||||
} |
||||
|
||||
for(; t < 80; t++) { |
||||
W[t] = rol(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]); |
||||
} |
||||
|
||||
A = ctx->state[0]; |
||||
B = ctx->state[1]; |
||||
C = ctx->state[2]; |
||||
D = ctx->state[3]; |
||||
E = ctx->state[4]; |
||||
|
||||
for(t = 0; t < 80; t++) { |
||||
uint32_t tmp = rol(5,A) + E + W[t]; |
||||
|
||||
if (t < 20) |
||||
tmp += (D^(B&(C^D))) + 0x5A827999; |
||||
else if ( t < 40) |
||||
tmp += (B^C^D) + 0x6ED9EBA1; |
||||
else if ( t < 60) |
||||
tmp += ((B&C)|(D&(B|C))) + 0x8F1BBCDC; |
||||
else |
||||
tmp += (B^C^D) + 0xCA62C1D6; |
||||
|
||||
E = D; |
||||
D = C; |
||||
C = rol(30,B); |
||||
B = A; |
||||
A = tmp; |
||||
} |
||||
|
||||
ctx->state[0] += A; |
||||
ctx->state[1] += B; |
||||
ctx->state[2] += C; |
||||
ctx->state[3] += D; |
||||
ctx->state[4] += E; |
||||
} |
||||
|
||||
static const HASH_VTAB SHA_VTAB = { |
||||
SHA_init, |
||||
SHA_update, |
||||
SHA_final, |
||||
SHA_hash, |
||||
SHA_DIGEST_SIZE |
||||
}; |
||||
|
||||
void SHA_init(SHA_CTX* ctx) { |
||||
ctx->f = &SHA_VTAB; |
||||
ctx->state[0] = 0x67452301; |
||||
ctx->state[1] = 0xEFCDAB89; |
||||
ctx->state[2] = 0x98BADCFE; |
||||
ctx->state[3] = 0x10325476; |
||||
ctx->state[4] = 0xC3D2E1F0; |
||||
ctx->count = 0; |
||||
} |
||||
|
||||
|
||||
void SHA_update(SHA_CTX* ctx, const void* data, int len) { |
||||
int i = (int) (ctx->count & 63); |
||||
const uint8_t* p = (const uint8_t*)data; |
||||
|
||||
ctx->count += len; |
||||
|
||||
while (len--) { |
||||
ctx->buf[i++] = *p++; |
||||
if (i == 64) { |
||||
SHA1_Transform(ctx); |
||||
i = 0; |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
const uint8_t* SHA_final(SHA_CTX* ctx) { |
||||
uint8_t *p = ctx->buf; |
||||
uint64_t cnt = ctx->count * 8; |
||||
int i; |
||||
|
||||
SHA_update(ctx, (uint8_t*)"\x80", 1); |
||||
while ((ctx->count & 63) != 56) { |
||||
SHA_update(ctx, (uint8_t*)"\0", 1); |
||||
} |
||||
for (i = 0; i < 8; ++i) { |
||||
uint8_t tmp = (uint8_t) (cnt >> ((7 - i) * 8)); |
||||
SHA_update(ctx, &tmp, 1); |
||||
} |
||||
|
||||
for (i = 0; i < 5; i++) { |
||||
uint32_t tmp = ctx->state[i]; |
||||
*p++ = tmp >> 24; |
||||
*p++ = tmp >> 16; |
||||
*p++ = tmp >> 8; |
||||
*p++ = tmp >> 0; |
||||
} |
||||
|
||||
return ctx->buf; |
||||
} |
||||
|
||||
/* Convenience function */ |
||||
const uint8_t* SHA_hash(const void* data, int len, uint8_t* digest) { |
||||
SHA_CTX ctx; |
||||
SHA_init(&ctx); |
||||
SHA_update(&ctx, data, len); |
||||
memcpy(digest, SHA_final(&ctx), SHA_DIGEST_SIZE); |
||||
return digest; |
||||
} |
@ -0,0 +1,51 @@ |
||||
/*
|
||||
* Copyright 2005 The Android Open Source Project |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions are met: |
||||
* * Redistributions of source code must retain the above copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* * Redistributions in binary form must reproduce the above copyright |
||||
* notice, this list of conditions and the following disclaimer in the |
||||
* documentation and/or other materials provided with the distribution. |
||||
* * Neither the name of Google Inc. nor the names of its contributors may |
||||
* be used to endorse or promote products derived from this software |
||||
* without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR |
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO |
||||
* EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; |
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
*/ |
||||
#ifndef SYSTEM_CORE_INCLUDE_MINCRYPT_SHA1_H_ |
||||
#define SYSTEM_CORE_INCLUDE_MINCRYPT_SHA1_H_ |
||||
|
||||
#include "hash-internal.h" |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif // __cplusplus
|
||||
|
||||
typedef HASH_CTX SHA_CTX; |
||||
|
||||
void SHA_init(SHA_CTX* ctx); |
||||
void SHA_update(SHA_CTX* ctx, const void* data, int len); |
||||
const uint8_t* SHA_final(SHA_CTX* ctx); |
||||
|
||||
// Convenience method. Returns digest address.
|
||||
// NOTE: *digest needs to hold SHA_DIGEST_SIZE bytes.
|
||||
const uint8_t* SHA_hash(const void* data, int len, uint8_t* digest); |
||||
|
||||
#define SHA_DIGEST_SIZE 20 |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif // __cplusplus
|
||||
|
||||
#endif // SYSTEM_CORE_INCLUDE_MINCRYPT_SHA1_H_
|
@ -0,0 +1,29 @@ |
||||
#!/usr/bin/env python |
||||
import os |
||||
import sys |
||||
import struct |
||||
import hashlib |
||||
from Crypto.PublicKey import RSA |
||||
|
||||
rsa = RSA.importKey(open(sys.argv[3]).read()) |
||||
|
||||
with open(sys.argv[1]) as f: |
||||
dat = f.read() |
||||
|
||||
print "signing", len(dat), "bytes" |
||||
|
||||
with open(sys.argv[2], "wb") as f: |
||||
if os.getenv("SETLEN") is not None: |
||||
x = struct.pack("I", len(dat)) + dat[4:] |
||||
# mock signature of dat[4:] |
||||
dd = hashlib.sha1(dat[4:]).digest() |
||||
else: |
||||
x = dat |
||||
dd = hashlib.sha1(dat).digest() |
||||
print "hash:",dd.encode("hex") |
||||
dd = "\x00\x01" + "\xff"*0x69 + "\x00" + dd |
||||
rsa_out = pow(int(dd.encode("hex"), 16), rsa.d, rsa.n) |
||||
sig = (hex(rsa_out)[2:-1].rjust(0x100, '0')).decode("hex") |
||||
x += sig |
||||
f.write(x) |
||||
|
@ -0,0 +1,4 @@ |
||||
#define uint8_t unsigned char |
||||
#define uint32_t unsigned int |
||||
#define int64_t long long |
||||
#define uint64_t unsigned long long |
Binary file not shown.
@ -0,0 +1,6 @@ |
||||
.*.cmd |
||||
*.ko |
||||
.tmp_versions |
||||
Module.symvers |
||||
modules.order |
||||
*.mod.c |
@ -0,0 +1,18 @@ |
||||
VERSION=0.0.1
|
||||
obj-m+=panda.o
|
||||
|
||||
link: |
||||
sudo dkms add `pwd`
|
||||
|
||||
build: |
||||
sudo dkms build panda/$(VERSION)
|
||||
|
||||
install: |
||||
sudo dkms install panda/$(VERSION)
|
||||
|
||||
all: build install |
||||
|
||||
uninstall: |
||||
sudo dkms uninstall panda/$(VERSION)
|
||||
sudo dkms remove panda/$(VERSION) --all
|
||||
|
@ -0,0 +1,19 @@ |
||||
Installs the panda linux kernel driver using DKMS. |
||||
|
||||
This will allow the panda to work with tools such as `can-utils` |
||||
|
||||
prerequisites: |
||||
- `apt-get install dkms gcc linux-headers-$(uname -r) make sudo` |
||||
|
||||
installation: |
||||
- `make link` (only needed the first time. It will report an error on subsequent attempts to link) |
||||
- `make all` |
||||
- `make install` |
||||
|
||||
uninstall: |
||||
- `make uninstall` |
||||
|
||||
usage: |
||||
|
||||
You will need to bring it up using `sudo ifconfig can0 up` or |
||||
`sudo ip link set dev can0 up`, depending on your platform. |
@ -0,0 +1,6 @@ |
||||
PACKAGE_NAME="panda" |
||||
PACKAGE_VERSION="0.0.1" |
||||
BUILT_MODULE_NAME[0]="panda" |
||||
DEST_MODULE_LOCATION[0]="/kernel/drivers/net/panda/" |
||||
AUTOINSTALL="yes" |
||||
|
@ -0,0 +1,613 @@ |
||||
/**
|
||||
* @file panda.c |
||||
* @author Jessy Diamond Exum |
||||
* @date 16 June 2017 |
||||
* @version 0.1 |
||||
* @brief Driver for the Comma.ai Panda CAN adapter to allow it to be controlled via |
||||
* the Linux SocketCAN interface. |
||||
* @see https://github.com/commaai/panda for the full project.
|
||||
* @see Inspired by net/can/usb/mcba_usb.c from Linux Kernel 4.12-rc4. |
||||
*/ |
||||
|
||||
#include <linux/can.h> |
||||
#include <linux/can/dev.h> |
||||
#include <linux/can/error.h> |
||||
#include <linux/init.h> // Macros used to mark up functions e.g., __init __exit |
||||
#include <linux/kernel.h> // Contains types, macros, functions for the kernel |
||||
#include <linux/module.h> // Core header for loading LKMs into the kernel |
||||
#include <linux/netdevice.h> |
||||
#include <linux/usb.h> |
||||
|
||||
/* vendor and product id */ |
||||
#define PANDA_MODULE_NAME "panda" |
||||
#define PANDA_VENDOR_ID 0XBBAA |
||||
#define PANDA_PRODUCT_ID 0XDDCC |
||||
|
||||
#define PANDA_MAX_TX_URBS 20 |
||||
#define PANDA_CTX_FREE PANDA_MAX_TX_URBS |
||||
|
||||
#define PANDA_USB_RX_BUFF_SIZE 0x40 |
||||
#define PANDA_USB_TX_BUFF_SIZE (sizeof(struct panda_usb_can_msg)) |
||||
|
||||
#define PANDA_NUM_CAN_INTERFACES 3 |
||||
|
||||
#define PANDA_CAN_TRANSMIT 1 |
||||
#define PANDA_CAN_EXTENDED 4 |
||||
|
||||
#define PANDA_BITRATE 500000 |
||||
|
||||
#define PANDA_DLC_MASK 0x0F |
||||
|
||||
struct panda_usb_ctx { |
||||
struct panda_inf_priv *priv; |
||||
u32 ndx; |
||||
u8 dlc; |
||||
}; |
||||
|
||||
struct panda_dev_priv; |
||||
|
||||
struct panda_inf_priv { |
||||
struct can_priv can; |
||||
struct panda_usb_ctx tx_context[PANDA_MAX_TX_URBS]; |
||||
struct net_device *netdev; |
||||
struct usb_anchor tx_submitted; |
||||
atomic_t free_ctx_cnt; |
||||
u8 interface_num; |
||||
u8 mcu_can_ifnum; |
||||
struct panda_dev_priv *priv_dev; |
||||
}; |
||||
|
||||
struct panda_dev_priv { |
||||
struct usb_device *udev; |
||||
struct device *dev; |
||||
struct usb_anchor rx_submitted; |
||||
struct panda_inf_priv *interfaces[PANDA_NUM_CAN_INTERFACES]; |
||||
}; |
||||
|
||||
struct __packed panda_usb_can_msg { |
||||
u32 rir; |
||||
u32 bus_dat_len; |
||||
u8 data[8]; |
||||
}; |
||||
|
||||
static const struct usb_device_id panda_usb_table[] = { |
||||
{ USB_DEVICE(PANDA_VENDOR_ID, PANDA_PRODUCT_ID) }, |
||||
{} /* Terminating entry */ |
||||
}; |
||||
|
||||
MODULE_DEVICE_TABLE(usb, panda_usb_table); |
||||
|
||||
|
||||
// panda: CAN1 = 0 CAN2 = 1 CAN3 = 4
|
||||
const int can_numbering[] = {0,1,4}; |
||||
|
||||
struct panda_inf_priv * |
||||
panda_get_inf_from_bus_id(struct panda_dev_priv *priv_dev, int bus_id){ |
||||
int inf_num; |
||||
for(inf_num = 0; inf_num < PANDA_NUM_CAN_INTERFACES; inf_num++) |
||||
if(can_numbering[inf_num] == bus_id) |
||||
return priv_dev->interfaces[inf_num]; |
||||
return NULL; |
||||
} |
||||
|
||||
// CTX handling shamlessly ripped from mcba_usb.c linux driver
|
||||
static inline void panda_init_ctx(struct panda_inf_priv *priv) |
||||
{ |
||||
int i = 0; |
||||
|
||||
for (i = 0; i < PANDA_MAX_TX_URBS; i++) { |
||||
priv->tx_context[i].ndx = PANDA_CTX_FREE; |
||||
priv->tx_context[i].priv = priv; |
||||
} |
||||
|
||||
atomic_set(&priv->free_ctx_cnt, ARRAY_SIZE(priv->tx_context)); |
||||
} |
||||
|
||||
static inline struct panda_usb_ctx *panda_usb_get_free_ctx(struct panda_inf_priv *priv, |
||||
struct can_frame *cf) |
||||
{ |
||||
int i = 0; |
||||
struct panda_usb_ctx *ctx = NULL; |
||||
|
||||
for (i = 0; i < PANDA_MAX_TX_URBS; i++) { |
||||
if (priv->tx_context[i].ndx == PANDA_CTX_FREE) { |
||||
ctx = &priv->tx_context[i]; |
||||
ctx->ndx = i; |
||||
ctx->dlc = cf->can_dlc; |
||||
|
||||
atomic_dec(&priv->free_ctx_cnt); |
||||
break; |
||||
} |
||||
} |
||||
|
||||
printk("CTX num %d\n", atomic_read(&priv->free_ctx_cnt)); |
||||
if (!atomic_read(&priv->free_ctx_cnt)){ |
||||
/* That was the last free ctx. Slow down tx path */ |
||||
printk("SENDING TOO FAST\n"); |
||||
netif_stop_queue(priv->netdev); |
||||
} |
||||
|
||||
return ctx; |
||||
} |
||||
|
||||
/* panda_usb_free_ctx and panda_usb_get_free_ctx are executed by different
|
||||
* threads. The order of execution in below function is important. |
||||
*/ |
||||
static inline void panda_usb_free_ctx(struct panda_usb_ctx *ctx) |
||||
{ |
||||
/* Increase number of free ctxs before freeing ctx */ |
||||
atomic_inc(&ctx->priv->free_ctx_cnt); |
||||
|
||||
ctx->ndx = PANDA_CTX_FREE; |
||||
|
||||
/* Wake up the queue once ctx is marked free */ |
||||
netif_wake_queue(ctx->priv->netdev); |
||||
} |
||||
|
||||
|
||||
|
||||
static void panda_urb_unlink(struct panda_inf_priv *priv) |
||||
{ |
||||
usb_kill_anchored_urbs(&priv->priv_dev->rx_submitted); |
||||
usb_kill_anchored_urbs(&priv->tx_submitted); |
||||
} |
||||
|
||||
static int panda_set_output_enable(struct panda_inf_priv* priv, bool enable){ |
||||
return usb_control_msg(priv->priv_dev->udev, |
||||
usb_sndctrlpipe(priv->priv_dev->udev, 0), |
||||
0xDC, USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
||||
enable ? 0x1337 : 0, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); |
||||
} |
||||
|
||||
static void panda_usb_write_bulk_callback(struct urb *urb) |
||||
{ |
||||
struct panda_usb_ctx *ctx = urb->context; |
||||
struct net_device *netdev; |
||||
|
||||
WARN_ON(!ctx); |
||||
|
||||
netdev = ctx->priv->netdev; |
||||
|
||||
/* free up our allocated buffer */ |
||||
usb_free_coherent(urb->dev, urb->transfer_buffer_length, |
||||
urb->transfer_buffer, urb->transfer_dma); |
||||
|
||||
if (!netif_device_present(netdev)) |
||||
return; |
||||
|
||||
netdev->stats.tx_packets++; |
||||
netdev->stats.tx_bytes += ctx->dlc; |
||||
|
||||
can_get_echo_skb(netdev, ctx->ndx); |
||||
|
||||
if (urb->status) |
||||
netdev_info(netdev, "Tx URB aborted (%d)\n", urb->status); |
||||
|
||||
/* Release the context */ |
||||
panda_usb_free_ctx(ctx); |
||||
} |
||||
|
||||
|
||||
static netdev_tx_t panda_usb_xmit(struct panda_inf_priv *priv, |
||||
struct panda_usb_can_msg *usb_msg, |
||||
struct panda_usb_ctx *ctx) |
||||
{ |
||||
struct urb *urb; |
||||
u8 *buf; |
||||
int err; |
||||
|
||||
/* create a URB, and a buffer for it, and copy the data to the URB */ |
||||
urb = usb_alloc_urb(0, GFP_ATOMIC); |
||||
if (!urb) |
||||
return -ENOMEM; |
||||
|
||||
buf = usb_alloc_coherent(priv->priv_dev->udev, |
||||
PANDA_USB_TX_BUFF_SIZE, GFP_ATOMIC, |
||||
&urb->transfer_dma); |
||||
if (!buf) { |
||||
err = -ENOMEM; |
||||
goto nomembuf; |
||||
} |
||||
|
||||
memcpy(buf, usb_msg, PANDA_USB_TX_BUFF_SIZE); |
||||
|
||||
usb_fill_bulk_urb(urb, priv->priv_dev->udev, |
||||
usb_sndbulkpipe(priv->priv_dev->udev, 3), buf, |
||||
PANDA_USB_TX_BUFF_SIZE, panda_usb_write_bulk_callback, |
||||
ctx); |
||||
|
||||
urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; |
||||
usb_anchor_urb(urb, &priv->tx_submitted); |
||||
|
||||
err = usb_submit_urb(urb, GFP_ATOMIC); |
||||
if (unlikely(err)) |
||||
goto failed; |
||||
|
||||
/* Release our reference to this URB, the USB core will eventually free it entirely. */ |
||||
usb_free_urb(urb); |
||||
|
||||
return 0; |
||||
|
||||
failed: |
||||
usb_unanchor_urb(urb); |
||||
usb_free_coherent(priv->priv_dev->udev, PANDA_USB_TX_BUFF_SIZE, buf, urb->transfer_dma); |
||||
|
||||
if (err == -ENODEV) |
||||
netif_device_detach(priv->netdev); |
||||
else |
||||
netdev_warn(priv->netdev, "failed tx_urb %d\n", err); |
||||
|
||||
nomembuf: |
||||
usb_free_urb(urb); |
||||
|
||||
return err; |
||||
} |
||||
|
||||
static void panda_usb_process_can_rx(struct panda_dev_priv *priv_dev, |
||||
struct panda_usb_can_msg *msg) |
||||
{ |
||||
struct can_frame *cf; |
||||
struct sk_buff *skb; |
||||
int bus_num; |
||||
struct panda_inf_priv *priv_inf; |
||||
struct net_device_stats *stats; |
||||
|
||||
bus_num = (msg->bus_dat_len >> 4) & 0xf; |
||||
priv_inf = panda_get_inf_from_bus_id(priv_dev, bus_num); |
||||
if(!priv_inf){ |
||||
printk("Got something on an unused interface %d\n", bus_num); |
||||
return; |
||||
} |
||||
printk("Recv bus %d\n", bus_num); |
||||
|
||||
stats = &priv_inf->netdev->stats; |
||||
//u16 sid;
|
||||
|
||||
if (!netif_device_present(priv_inf->netdev)) |
||||
return; |
||||
|
||||
skb = alloc_can_skb(priv_inf->netdev, &cf); |
||||
if (!skb) |
||||
return; |
||||
|
||||
if(msg->rir & PANDA_CAN_EXTENDED){ |
||||
cf->can_id = (msg->rir >> 3) | CAN_EFF_FLAG; |
||||
}else{ |
||||
cf->can_id = (msg->rir >> 21); |
||||
} |
||||
|
||||
// TODO: Handle Remote Frames
|
||||
//if (msg->dlc & MCBA_DLC_RTR_MASK)
|
||||
// cf->can_id |= CAN_RTR_FLAG;
|
||||
|
||||
cf->can_dlc = get_can_dlc(msg->bus_dat_len & PANDA_DLC_MASK); |
||||
|
||||
memcpy(cf->data, msg->data, cf->can_dlc); |
||||
|
||||
stats->rx_packets++; |
||||
stats->rx_bytes += cf->can_dlc; |
||||
|
||||
netif_rx(skb); |
||||
} |
||||
|
||||
static void panda_usb_read_int_callback(struct urb *urb) |
||||
{ |
||||
struct panda_dev_priv *priv_dev = urb->context; |
||||
int retval; |
||||
int pos = 0; |
||||
int inf_num; |
||||
|
||||
switch (urb->status) { |
||||
case 0: /* success */ |
||||
break; |
||||
case -ENOENT: |
||||
case -ESHUTDOWN: |
||||
return; |
||||
default: |
||||
dev_info(priv_dev->dev, "Rx URB aborted (%d)\n", urb->status); |
||||
goto resubmit_urb; |
||||
} |
||||
|
||||
while (pos < urb->actual_length) { |
||||
struct panda_usb_can_msg *msg; |
||||
|
||||
if (pos + sizeof(struct panda_usb_can_msg) > urb->actual_length) { |
||||
dev_err(priv_dev->dev, "format error\n"); |
||||
break; |
||||
} |
||||
|
||||
msg = (struct panda_usb_can_msg *)(urb->transfer_buffer + pos); |
||||
|
||||
panda_usb_process_can_rx(priv_dev, msg); |
||||
|
||||
pos += sizeof(struct panda_usb_can_msg); |
||||
} |
||||
|
||||
resubmit_urb: |
||||
usb_fill_int_urb(urb, priv_dev->udev, |
||||
usb_rcvintpipe(priv_dev->udev, 1), |
||||
urb->transfer_buffer, PANDA_USB_RX_BUFF_SIZE, |
||||
panda_usb_read_int_callback, priv_dev, 5); |
||||
|
||||
retval = usb_submit_urb(urb, GFP_ATOMIC); |
||||
|
||||
if (retval == -ENODEV){ |
||||
for(inf_num = 0; inf_num < PANDA_NUM_CAN_INTERFACES; inf_num++) |
||||
if(priv_dev->interfaces[inf_num]) |
||||
netif_device_detach(priv_dev->interfaces[inf_num]->netdev); |
||||
}else if (retval) |
||||
dev_err(priv_dev->dev, "failed resubmitting read bulk urb: %d\n", retval); |
||||
} |
||||
|
||||
|
||||
static int panda_usb_start(struct panda_dev_priv *priv_dev) |
||||
{ |
||||
int err; |
||||
struct urb *urb = NULL; |
||||
u8 *buf; |
||||
int inf_num; |
||||
|
||||
for(inf_num = 0; inf_num < PANDA_NUM_CAN_INTERFACES; inf_num++) |
||||
panda_init_ctx(priv_dev->interfaces[inf_num]); |
||||
|
||||
err = usb_set_interface(priv_dev->udev, 0, 1); |
||||
if (err) { |
||||
dev_err(priv_dev->dev, "Can not set alternate setting to 1, error: %i", err); |
||||
return err; |
||||
} |
||||
|
||||
/* create a URB, and a buffer for it */ |
||||
urb = usb_alloc_urb(0, GFP_KERNEL); |
||||
if (!urb) { |
||||
return -ENOMEM; |
||||
} |
||||
|
||||
buf = usb_alloc_coherent(priv_dev->udev, PANDA_USB_RX_BUFF_SIZE, |
||||
GFP_KERNEL, &urb->transfer_dma); |
||||
if (!buf) { |
||||
dev_err(priv_dev->dev, "No memory left for USB buffer\n"); |
||||
usb_free_urb(urb); |
||||
return -ENOMEM; |
||||
} |
||||
|
||||
usb_fill_int_urb(urb, priv_dev->udev, |
||||
usb_rcvintpipe(priv_dev->udev, 1), |
||||
buf, PANDA_USB_RX_BUFF_SIZE, |
||||
panda_usb_read_int_callback, priv_dev, 5); |
||||
urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; |
||||
|
||||
usb_anchor_urb(urb, &priv_dev->rx_submitted); |
||||
|
||||
err = usb_submit_urb(urb, GFP_KERNEL); |
||||
if (err) { |
||||
usb_unanchor_urb(urb); |
||||
usb_free_coherent(priv_dev->udev, PANDA_USB_RX_BUFF_SIZE, |
||||
buf, urb->transfer_dma); |
||||
usb_free_urb(urb); |
||||
dev_err(priv_dev->dev, "Failed in start, while submitting urb.\n"); |
||||
return err; |
||||
} |
||||
|
||||
/* Drop reference, USB core will take care of freeing it */ |
||||
usb_free_urb(urb); |
||||
|
||||
|
||||
return 0; |
||||
} |
||||
|
||||
/* Open USB device */ |
||||
static int panda_usb_open(struct net_device *netdev) |
||||
{ |
||||
struct panda_inf_priv *priv = netdev_priv(netdev); |
||||
int err; |
||||
|
||||
/* common open */ |
||||
err = open_candev(netdev); |
||||
if (err) |
||||
return err; |
||||
|
||||
//priv->can_speed_check = true;
|
||||
priv->can.state = CAN_STATE_ERROR_ACTIVE; |
||||
|
||||
netif_start_queue(netdev); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
/* Close USB device */ |
||||
static int panda_usb_close(struct net_device *netdev) |
||||
{ |
||||
struct panda_inf_priv *priv = netdev_priv(netdev); |
||||
|
||||
priv->can.state = CAN_STATE_STOPPED; |
||||
|
||||
netif_stop_queue(netdev); |
||||
|
||||
/* Stop polling */ |
||||
panda_urb_unlink(priv); |
||||
|
||||
close_candev(netdev); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
static netdev_tx_t panda_usb_start_xmit(struct sk_buff *skb, |
||||
struct net_device *netdev) |
||||
{ |
||||
struct panda_inf_priv *priv_inf = netdev_priv(netdev); |
||||
struct can_frame *cf = (struct can_frame *)skb->data; |
||||
struct panda_usb_ctx *ctx = NULL; |
||||
struct net_device_stats *stats = &priv_inf->netdev->stats; |
||||
int err; |
||||
struct panda_usb_can_msg usb_msg = {}; |
||||
int bus = priv_inf->mcu_can_ifnum; |
||||
|
||||
if (can_dropped_invalid_skb(netdev, skb)){ |
||||
printk("Invalid CAN packet"); |
||||
return NETDEV_TX_OK; |
||||
} |
||||
|
||||
ctx = panda_usb_get_free_ctx(priv_inf, cf); |
||||
|
||||
//Warning: cargo cult. Can't tell what this is for, but it is
|
||||
//everywhere and encouraged in the documentation.
|
||||
can_put_echo_skb(skb, priv_inf->netdev, ctx->ndx); |
||||
|
||||
if(cf->can_id & CAN_EFF_FLAG){ |
||||
usb_msg.rir = cpu_to_le32(((cf->can_id & 0x1FFFFFFF) << 3) | |
||||
PANDA_CAN_TRANSMIT | PANDA_CAN_EXTENDED); |
||||
}else{ |
||||
usb_msg.rir = cpu_to_le32(((cf->can_id & 0x7FF) << 21) | PANDA_CAN_TRANSMIT); |
||||
} |
||||
usb_msg.bus_dat_len = cpu_to_le32((cf->can_dlc & 0x0F) | (bus << 4)); |
||||
|
||||
memcpy(usb_msg.data, cf->data, cf->can_dlc); |
||||
|
||||
//TODO Handle Remote Frames
|
||||
//if (cf->can_id & CAN_RTR_FLAG)
|
||||
// usb_msg.dlc |= PANDA_DLC_RTR_MASK;
|
||||
|
||||
netdev_err(netdev, "Received data from socket. canid: %x; len: %d\n", cf->can_id, cf->can_dlc); |
||||
|
||||
err = panda_usb_xmit(priv_inf, &usb_msg, ctx); |
||||
if (err) |
||||
goto xmit_failed; |
||||
|
||||
return NETDEV_TX_OK; |
||||
|
||||
xmit_failed: |
||||
can_free_echo_skb(priv_inf->netdev, ctx->ndx); |
||||
panda_usb_free_ctx(ctx); |
||||
dev_kfree_skb(skb); |
||||
stats->tx_dropped++; |
||||
|
||||
return NETDEV_TX_OK; |
||||
} |
||||
|
||||
static const struct net_device_ops panda_netdev_ops = { |
||||
.ndo_open = panda_usb_open, |
||||
.ndo_stop = panda_usb_close, |
||||
.ndo_start_xmit = panda_usb_start_xmit, |
||||
}; |
||||
|
||||
static int panda_usb_probe(struct usb_interface *intf, |
||||
const struct usb_device_id *id) |
||||
{ |
||||
struct net_device *netdev; |
||||
struct panda_inf_priv *priv_inf; |
||||
int err = -ENOMEM; |
||||
int inf_num; |
||||
struct panda_dev_priv *priv_dev; |
||||
struct usb_device *usbdev = interface_to_usbdev(intf); |
||||
|
||||
priv_dev = kzalloc(sizeof(struct panda_dev_priv), GFP_KERNEL); |
||||
if (!priv_dev) { |
||||
dev_err(&intf->dev, "Couldn't alloc priv_dev\n"); |
||||
return -ENOMEM; |
||||
} |
||||
priv_dev->udev = usbdev; |
||||
priv_dev->dev = &intf->dev; |
||||
usb_set_intfdata(intf, priv_dev); |
||||
|
||||
////// Interface privs
|
||||
for(inf_num = 0; inf_num < PANDA_NUM_CAN_INTERFACES; inf_num++){ |
||||
netdev = alloc_candev(sizeof(struct panda_inf_priv), PANDA_MAX_TX_URBS); |
||||
if (!netdev) { |
||||
dev_err(&intf->dev, "Couldn't alloc candev\n"); |
||||
goto cleanup_candev; |
||||
} |
||||
netdev->netdev_ops = &panda_netdev_ops; |
||||
netdev->flags |= IFF_ECHO; /* we support local echo */ |
||||
|
||||
priv_inf = netdev_priv(netdev); |
||||
priv_inf->netdev = netdev; |
||||
priv_inf->priv_dev = priv_dev; |
||||
priv_inf->interface_num = inf_num; |
||||
priv_inf->mcu_can_ifnum = can_numbering[inf_num]; |
||||
|
||||
init_usb_anchor(&priv_dev->rx_submitted); |
||||
init_usb_anchor(&priv_inf->tx_submitted); |
||||
|
||||
/* Init CAN device */ |
||||
priv_inf->can.state = CAN_STATE_STOPPED; |
||||
priv_inf->can.bittiming.bitrate = PANDA_BITRATE; |
||||
|
||||
SET_NETDEV_DEV(netdev, &intf->dev); |
||||
|
||||
err = register_candev(netdev); |
||||
if (err) { |
||||
netdev_err(netdev, "couldn't register PANDA CAN device: %d\n", err); |
||||
free_candev(priv_inf->netdev); |
||||
goto cleanup_candev; |
||||
} |
||||
|
||||
priv_dev->interfaces[inf_num] = priv_inf; |
||||
} |
||||
|
||||
err = panda_usb_start(priv_dev); |
||||
if (err) { |
||||
dev_err(&intf->dev, "Failed to initialize Comma.ai Panda CAN controller\n"); |
||||
goto cleanup_candev; |
||||
} |
||||
|
||||
err = panda_set_output_enable(priv_inf, true); |
||||
if (err) { |
||||
dev_info(&intf->dev, "Failed to initialize send enable message to Panda.\n"); |
||||
goto cleanup_candev; |
||||
} |
||||
|
||||
dev_info(&intf->dev, "Comma.ai Panda CAN controller connected\n"); |
||||
|
||||
return 0; |
||||
|
||||
cleanup_candev: |
||||
for(inf_num = 0; inf_num < PANDA_NUM_CAN_INTERFACES; inf_num++){ |
||||
priv_inf = priv_dev->interfaces[inf_num]; |
||||
if(priv_inf){ |
||||
unregister_candev(priv_inf->netdev); |
||||
free_candev(priv_inf->netdev); |
||||
}else |
||||
break; |
||||
} |
||||
|
||||
kfree(priv_dev); |
||||
|
||||
return err; |
||||
} |
||||
|
||||
/* Called by the usb core when driver is unloaded or device is removed */ |
||||
static void panda_usb_disconnect(struct usb_interface *intf) |
||||
{ |
||||
struct panda_dev_priv *priv_dev = usb_get_intfdata(intf); |
||||
struct panda_inf_priv *priv_inf; |
||||
int inf_num; |
||||
|
||||
usb_set_intfdata(intf, NULL); |
||||
|
||||
for(inf_num = 0; inf_num < PANDA_NUM_CAN_INTERFACES; inf_num++){ |
||||
priv_inf = priv_dev->interfaces[inf_num]; |
||||
if(priv_inf){ |
||||
netdev_info(priv_inf->netdev, "device disconnected\n"); |
||||
unregister_candev(priv_inf->netdev); |
||||
free_candev(priv_inf->netdev); |
||||
}else |
||||
break; |
||||
} |
||||
|
||||
panda_urb_unlink(priv_inf); |
||||
kfree(priv_dev); |
||||
} |
||||
|
||||
static struct usb_driver panda_usb_driver = { |
||||
.name = PANDA_MODULE_NAME, |
||||
.probe = panda_usb_probe, |
||||
.disconnect = panda_usb_disconnect, |
||||
.id_table = panda_usb_table, |
||||
}; |
||||
|
||||
module_usb_driver(panda_usb_driver); |
||||
|
||||
MODULE_LICENSE("GPL"); |
||||
MODULE_AUTHOR("Jessy Diamond Exum <jessy.diamondman@gmail.com>"); |
||||
MODULE_DESCRIPTION("SocketCAN driver for Comma.ai's Panda Adapter."); |
||||
MODULE_VERSION("0.1"); |
@ -0,0 +1,2 @@ |
||||
all: |
||||
gcc main.c -o cantest -pthread -lpthread
|
@ -0,0 +1,120 @@ |
||||
#include <stdio.h> |
||||
#include <stdlib.h> |
||||
#include <unistd.h> |
||||
#include <string.h> |
||||
#include <pthread.h> |
||||
|
||||
#include <net/if.h> |
||||
#include <sys/types.h> |
||||
#include <sys/socket.h> |
||||
#include <sys/ioctl.h> |
||||
|
||||
#include <linux/can.h> |
||||
#include <linux/can/raw.h> |
||||
|
||||
const char *ifname = "can0"; |
||||
|
||||
static unsigned char payload[] = {0xAA, 0xAA, 0xAA, 0xAA, 0x07, 0x00, 0x00, 0x00}; |
||||
int packet_len = 8; |
||||
int dir = 0; |
||||
|
||||
void *write_thread( void *dat ){ |
||||
int nbytes; |
||||
struct can_frame frame; |
||||
int s = *((int*) dat); |
||||
|
||||
while(1){ |
||||
for(int i = 0; i < 1; i ++){ |
||||
if(packet_len % 2){ |
||||
frame.can_id = 0x8AA | CAN_EFF_FLAG; |
||||
}else{ |
||||
frame.can_id = 0xAA; |
||||
} |
||||
|
||||
frame.can_dlc = packet_len; |
||||
memcpy(frame.data, payload, frame.can_dlc); |
||||
|
||||
nbytes = write(s, &frame, sizeof(struct can_frame)); |
||||
|
||||
printf("Wrote %d bytes; addr: %lx; datlen: %d\n", nbytes, frame.can_id, frame.can_dlc); |
||||
|
||||
if(dir){ |
||||
packet_len++; |
||||
if(packet_len >= 8) |
||||
dir = 0; |
||||
}else{ |
||||
packet_len--; |
||||
if(packet_len <= 0) |
||||
dir = 1; |
||||
} |
||||
} |
||||
sleep(2); |
||||
} |
||||
} |
||||
|
||||
|
||||
int main(void) |
||||
{ |
||||
pthread_t sndthread; |
||||
int err, s, nbytes; |
||||
struct sockaddr_can addr; |
||||
struct can_frame frame; |
||||
struct ifreq ifr; |
||||
|
||||
if((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) { |
||||
perror("Error while opening socket"); |
||||
return -1; |
||||
} |
||||
|
||||
strcpy(ifr.ifr_name, ifname); |
||||
ioctl(s, SIOCGIFINDEX, &ifr); |
||||
|
||||
addr.can_family = AF_CAN; |
||||
addr.can_ifindex = ifr.ifr_ifindex; |
||||
|
||||
printf("%s at index %d\n", ifname, ifr.ifr_ifindex); |
||||
|
||||
if(bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) { |
||||
perror("Error in socket bind"); |
||||
return -2; |
||||
} |
||||
|
||||
/////// Create Write Thread
|
||||
|
||||
err = pthread_create( &sndthread, NULL, write_thread, (void*) &s); |
||||
if(err){ |
||||
fprintf(stderr,"Error - pthread_create() return code: %d\n", err); |
||||
exit(EXIT_FAILURE); |
||||
} |
||||
|
||||
/////// Listen to socket
|
||||
while (1) { |
||||
struct can_frame framein; |
||||
|
||||
// Read in a CAN frame
|
||||
int numBytes = read(s, &framein, CANFD_MTU); |
||||
switch (numBytes) { |
||||
case CAN_MTU: |
||||
if(framein.can_id & 0x80000000) |
||||
printf("Received %u byte payload; canid 0x%lx (EXT)\n", |
||||
framein.can_dlc, framein.can_id & 0x7FFFFFFF); |
||||
else |
||||
printf("Received %u byte payload; canid 0x%lx\n", framein.can_dlc, framein.can_id); |
||||
break; |
||||
case CANFD_MTU: |
||||
// TODO: Should make an example for CAN FD
|
||||
break; |
||||
case -1: |
||||
// Check the signal value on interrupt
|
||||
//if (EINTR == errno)
|
||||
// continue;
|
||||
|
||||
// Delay before continuing
|
||||
sleep(1); |
||||
default: |
||||
continue; |
||||
} |
||||
} |
||||
|
||||
return 0; |
||||
} |
@ -0,0 +1,4 @@ |
||||
#!/usr/bin/env bash |
||||
sudo ifconfig can0 up |
||||
make |
||||
./cantest |
@ -0,0 +1,306 @@ |
||||
## Ignore Visual Studio temporary files, build results, and |
||||
## files generated by popular Visual Studio add-ons. |
||||
## |
||||
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore |
||||
|
||||
# User-specific files |
||||
*.suo |
||||
*.user |
||||
*.userosscache |
||||
*.sln.docstates |
||||
|
||||
# User-specific files (MonoDevelop/Xamarin Studio) |
||||
*.userprefs |
||||
|
||||
# Build results |
||||
Debug_x86/ |
||||
Debug_x64/ |
||||
Release_x86/ |
||||
Release_x64/ |
||||
[Dd]ebug/ |
||||
[Dd]ebugPublic/ |
||||
[Rr]elease/ |
||||
[Rr]eleases/ |
||||
x64/ |
||||
x86/ |
||||
bld/ |
||||
[Bb]in/ |
||||
[Oo]bj/ |
||||
[Ll]og/ |
||||
|
||||
# Visual Studio 2015 cache/options directory |
||||
.vs/ |
||||
# Uncomment if you have tasks that create the project's static files in wwwroot |
||||
#wwwroot/ |
||||
|
||||
# MSTest test Results |
||||
[Tt]est[Rr]esult*/ |
||||
[Bb]uild[Ll]og.* |
||||
|
||||
# NUNIT |
||||
*.VisualState.xml |
||||
TestResult.xml |
||||
|
||||
# Build Results of an ATL Project |
||||
[Dd]ebugPS/ |
||||
[Rr]eleasePS/ |
||||
dlldata.c |
||||
|
||||
# Benchmark Results |
||||
BenchmarkDotNet.Artifacts/ |
||||
|
||||
# .NET Core |
||||
project.lock.json |
||||
project.fragment.lock.json |
||||
artifacts/ |
||||
**/Properties/launchSettings.json |
||||
|
||||
*_i.c |
||||
*_p.c |
||||
*_i.h |
||||
*.ilk |
||||
*.meta |
||||
*.obj |
||||
*.pch |
||||
*.pdb |
||||
*.pgc |
||||
*.pgd |
||||
*.rsp |
||||
*.sbr |
||||
*.tlb |
||||
*.tli |
||||
*.tlh |
||||
*.tmp |
||||
*.tmp_proj |
||||
*.log |
||||
*.vspscc |
||||
*.vssscc |
||||
.builds |
||||
*.pidb |
||||
*.svclog |
||||
*.scc |
||||
|
||||
# Chutzpah Test files |
||||
_Chutzpah* |
||||
|
||||
# Visual C++ cache files |
||||
ipch/ |
||||
*.aps |
||||
*.ncb |
||||
*.opendb |
||||
*.opensdf |
||||
*.sdf |
||||
*.cachefile |
||||
*.VC.db |
||||
*.VC.VC.opendb |
||||
|
||||
# Visual Studio profiler |
||||
*.psess |
||||
*.vsp |
||||
*.vspx |
||||
*.sap |
||||
|
||||
# TFS 2012 Local Workspace |
||||
$tf/ |
||||
|
||||
# Guidance Automation Toolkit |
||||
*.gpState |
||||
|
||||
# ReSharper is a .NET coding add-in |
||||
_ReSharper*/ |
||||
*.[Rr]e[Ss]harper |
||||
*.DotSettings.user |
||||
|
||||
# JustCode is a .NET coding add-in |
||||
.JustCode |
||||
|
||||
# TeamCity is a build add-in |
||||
_TeamCity* |
||||
|
||||
# DotCover is a Code Coverage Tool |
||||
*.dotCover |
||||
|
||||
# AxoCover is a Code Coverage Tool |
||||
.axoCover/* |
||||
!.axoCover/settings.json |
||||
|
||||
# Visual Studio code coverage results |
||||
*.coverage |
||||
*.coveragexml |
||||
|
||||
# NCrunch |
||||
_NCrunch_* |
||||
.*crunch*.local.xml |
||||
nCrunchTemp_* |
||||
|
||||
# MightyMoose |
||||
*.mm.* |
||||
AutoTest.Net/ |
||||
|
||||
# Web workbench (sass) |
||||
.sass-cache/ |
||||
|
||||
# Installshield output folder |
||||
[Ee]xpress/ |
||||
|
||||
# DocProject is a documentation generator add-in |
||||
DocProject/buildhelp/ |
||||
DocProject/Help/*.HxT |
||||
DocProject/Help/*.HxC |
||||
DocProject/Help/*.hhc |
||||
DocProject/Help/*.hhk |
||||
DocProject/Help/*.hhp |
||||
DocProject/Help/Html2 |
||||
DocProject/Help/html |
||||
|
||||
# Click-Once directory |
||||
publish/ |
||||
|
||||
# Publish Web Output |
||||
*.[Pp]ublish.xml |
||||
*.azurePubxml |
||||
# Note: Comment the next line if you want to checkin your web deploy settings, |
||||
# but database connection strings (with potential passwords) will be unencrypted |
||||
*.pubxml |
||||
*.publishproj |
||||
|
||||
# Microsoft Azure Web App publish settings. Comment the next line if you want to |
||||
# checkin your Azure Web App publish settings, but sensitive information contained |
||||
# in these scripts will be unencrypted |
||||
PublishScripts/ |
||||
|
||||
# NuGet Packages |
||||
*.nupkg |
||||
# The packages folder can be ignored because of Package Restore |
||||
**/packages/* |
||||
# except build/, which is used as an MSBuild target. |
||||
!**/packages/build/ |
||||
# Uncomment if necessary however generally it will be regenerated when needed |
||||
#!**/packages/repositories.config |
||||
# NuGet v3's project.json files produces more ignorable files |
||||
*.nuget.props |
||||
*.nuget.targets |
||||
|
||||
# Microsoft Azure Build Output |
||||
csx/ |
||||
*.build.csdef |
||||
|
||||
# Microsoft Azure Emulator |
||||
ecf/ |
||||
rcf/ |
||||
|
||||
# Windows Store app package directories and files |
||||
AppPackages/ |
||||
BundleArtifacts/ |
||||
Package.StoreAssociation.xml |
||||
_pkginfo.txt |
||||
*.appx |
||||
|
||||
# Visual Studio cache files |
||||
# files ending in .cache can be ignored |
||||
*.[Cc]ache |
||||
# but keep track of directories ending in .cache |
||||
!*.[Cc]ache/ |
||||
|
||||
# Others |
||||
ClientBin/ |
||||
~$* |
||||
*~ |
||||
*.dbmdl |
||||
*.dbproj.schemaview |
||||
*.jfm |
||||
*.pfx |
||||
*.publishsettings |
||||
orleans.codegen.cs |
||||
|
||||
# Since there are multiple workflows, uncomment next line to ignore bower_components |
||||
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) |
||||
#bower_components/ |
||||
|
||||
# RIA/Silverlight projects |
||||
Generated_Code/ |
||||
|
||||
# Backup & report files from converting an old project file |
||||
# to a newer Visual Studio version. Backup files are not needed, |
||||
# because we have git ;-) |
||||
_UpgradeReport_Files/ |
||||
Backup*/ |
||||
UpgradeLog*.XML |
||||
UpgradeLog*.htm |
||||
|
||||
# SQL Server files |
||||
*.mdf |
||||
*.ldf |
||||
*.ndf |
||||
|
||||
# Business Intelligence projects |
||||
*.rdl.data |
||||
*.bim.layout |
||||
*.bim_*.settings |
||||
|
||||
# Microsoft Fakes |
||||
FakesAssemblies/ |
||||
|
||||
# GhostDoc plugin setting file |
||||
*.GhostDoc.xml |
||||
|
||||
# Node.js Tools for Visual Studio |
||||
.ntvs_analysis.dat |
||||
node_modules/ |
||||
|
||||
# Typescript v1 declaration files |
||||
typings/ |
||||
|
||||
# Visual Studio 6 build log |
||||
*.plg |
||||
|
||||
# Visual Studio 6 workspace options file |
||||
*.opt |
||||
|
||||
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) |
||||
*.vbw |
||||
|
||||
# Visual Studio LightSwitch build output |
||||
**/*.HTMLClient/GeneratedArtifacts |
||||
**/*.DesktopClient/GeneratedArtifacts |
||||
**/*.DesktopClient/ModelManifest.xml |
||||
**/*.Server/GeneratedArtifacts |
||||
**/*.Server/ModelManifest.xml |
||||
_Pvt_Extensions |
||||
|
||||
# Paket dependency manager |
||||
.paket/paket.exe |
||||
paket-files/ |
||||
|
||||
# FAKE - F# Make |
||||
.fake/ |
||||
|
||||
# JetBrains Rider |
||||
.idea/ |
||||
*.sln.iml |
||||
|
||||
# CodeRush |
||||
.cr/ |
||||
|
||||
# Python Tools for Visual Studio (PTVS) |
||||
__pycache__/ |
||||
*.pyc |
||||
|
||||
# Cake - Uncomment if you are using it |
||||
# tools/** |
||||
# !tools/packages.config |
||||
|
||||
# Tabs Studio |
||||
*.tss |
||||
|
||||
# Telerik's JustMock configuration file |
||||
*.jmconfig |
||||
|
||||
# BizTalk build output |
||||
*.btp.cs |
||||
*.btm.cs |
||||
*.odx.cs |
||||
*.xsd.cs |
||||
|
||||
# installer |
||||
*.exe |
@ -0,0 +1,38 @@ |
||||
// ECUsim CLI.cpp : Defines the entry point for the console application.
|
||||
//
|
||||
|
||||
#include "stdafx.h" |
||||
#include "ECUsim DLL\ECUsim.h" |
||||
|
||||
std::unique_ptr<ECUsim> sim; |
||||
|
||||
BOOL CtrlHandler(DWORD fdwCtrlType) |
||||
{ |
||||
if (fdwCtrlType != CTRL_C_EVENT) return FALSE; |
||||
|
||||
sim->stop(); |
||||
sim->join(); |
||||
|
||||
return(TRUE); |
||||
} |
||||
|
||||
int main(int argc, // Number of strings in array argv
|
||||
char *argv[], // Array of command-line argument strings
|
||||
char *envp[]) // Array of environment variable strings
|
||||
{ |
||||
|
||||
int count; |
||||
|
||||
// Display each command-line argument.
|
||||
std::cout << "\nCommand-line arguments:\n"; |
||||
for (count = 0; count < argc; count++) |
||||
std::cout << " argv[" << count << "] " << argv[count] << "\n"; |
||||
|
||||
SetConsoleCtrlHandler((PHANDLER_ROUTINE)CtrlHandler, TRUE); |
||||
|
||||
sim.reset(new ECUsim("", 500000)); |
||||
sim->join(); |
||||
|
||||
return 0; |
||||
} |
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue