mirror of https://github.com/commaai/panda.git
initial commit
This commit is contained in:
commit
e07f9b111e
|
@ -0,0 +1,4 @@
|
||||||
|
*.pyc
|
||||||
|
.*.swp
|
||||||
|
*.o
|
||||||
|
|
|
@ -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,41 @@
|
||||||
|
Welcome to panda
|
||||||
|
======
|
||||||
|
|
||||||
|
[panda](http://github.com/commaai/panda) is the nicest universal car interface you've ever seen.
|
||||||
|
|
||||||
|
It supports 3x CAN, 2x LIN, and 1x GMLAN.
|
||||||
|
|
||||||
|
It uses an [STM32F413](http://www.st.com/en/microcontrollers/stm32f413-423.html?querycriteria=productId=LN2004) for low level stuff and an [ESP8266](https://en.wikipedia.org/wiki/ESP8266) for wifi. They are connected over high speed SPI, so the panda is actually capable of dumping the full contents of the busses over wifi, unlike every other dongle on amazon. ELM327 is weak, panda is strong.
|
||||||
|
|
||||||
|
It is 2nd gen hardware, reusing code and parts from the [NEO](https://github.com/commaai/neo) interface board.
|
||||||
|
|
||||||
|
Directory structure
|
||||||
|
------
|
||||||
|
|
||||||
|
- board -- Code that runs on the STM32
|
||||||
|
- boardesp -- Code that runs on the ESP8266
|
||||||
|
- lib -- Python userspace library for interfacing with the panda
|
||||||
|
- tests -- Tests and helper programs for panda
|
||||||
|
|
||||||
|
Usage
|
||||||
|
------
|
||||||
|
|
||||||
|
Programming the STM32
|
||||||
|
```
|
||||||
|
cd board
|
||||||
|
./get_sdk.sh
|
||||||
|
make
|
||||||
|
```
|
||||||
|
|
||||||
|
Programming the ESP
|
||||||
|
```
|
||||||
|
cd boardesp
|
||||||
|
./get_sdk.sh
|
||||||
|
make
|
||||||
|
```
|
||||||
|
|
||||||
|
Licensing
|
||||||
|
------
|
||||||
|
|
||||||
|
panda software is released under the MIT license. See LICENSE
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
== Needed ==
|
||||||
|
* Change the SPI interface to support all USB commands
|
||||||
|
* Support panda lib abstractly connecting over wifi or USB
|
||||||
|
* Refactor the Honda safety code to be universal
|
||||||
|
|
||||||
|
== Wanted ==
|
||||||
|
* Change USB to use interrupt endpoint instead of bulk for can recv
|
||||||
|
* Write elm327 emulator in boardesp/elm327.c and make it work with Torque
|
||||||
|
* Write a kernel driver to support socketcan. Kline as serial interfaces?
|
||||||
|
* Write a Windows J2534 DLL to support windows tools
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
obj/*
|
|
@ -0,0 +1,10 @@
|
||||||
|
# :set noet
|
||||||
|
PROJ_NAME = panda
|
||||||
|
CFLAGS = -g -O0 -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 -O0 -Wall
|
||||||
|
|
||||||
|
CFLAGS += -mlittle-endian -mthumb -mcpu=cortex-m3
|
||||||
|
CFLAGS += -msoft-float -DSTM32F2 -DSTM32F205xx
|
||||||
|
STARTUP_FILE = startup_stm32f205xx
|
||||||
|
|
||||||
|
include build.mk
|
|
@ -0,0 +1,9 @@
|
||||||
|
== Building ==
|
||||||
|
|
||||||
|
./get_sdk.sh
|
||||||
|
|
||||||
|
dfu-util from
|
||||||
|
git@github.com:dsigma/dfu-util.git
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
// 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,22 @@
|
||||||
|
void *_origin = 0x8004000;
|
||||||
|
|
||||||
|
#ifdef STM32F4
|
||||||
|
#define PANDA
|
||||||
|
#include "stm32f4xx.h"
|
||||||
|
#else
|
||||||
|
#include "stm32f2xx.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "early.h"
|
||||||
|
|
||||||
|
void __initialize_hardware_early() {
|
||||||
|
early();
|
||||||
|
|
||||||
|
// jump to flash
|
||||||
|
((void(*)()) _app_start[1])();
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
CFLAGS += -I inc -nostdlib
|
||||||
|
CFLAGS += -Tstm32_flash.ld
|
||||||
|
|
||||||
|
CC = arm-none-eabi-gcc
|
||||||
|
OBJCOPY = arm-none-eabi-objcopy
|
||||||
|
OBJDUMP = arm-none-eabi-objdump
|
||||||
|
|
||||||
|
MACHINE = $(shell uname -m)
|
||||||
|
OS = $(shell uname -o)
|
||||||
|
|
||||||
|
ifeq ($(OS),GNU/Linux)
|
||||||
|
MACHINE := "$(MACHINE)-linux"
|
||||||
|
endif
|
||||||
|
|
||||||
|
# this pushes the unchangable bootstub too
|
||||||
|
all: obj/bootstub.$(PROJ_NAME).bin obj/$(PROJ_NAME).bin
|
||||||
|
./tools/enter_download_mode.py
|
||||||
|
./tools/dfu-util-$(MACHINE) -a 0 -s 0x08000000 -D obj/bootstub.$(PROJ_NAME).bin
|
||||||
|
./tools/dfu-util-$(MACHINE) -a 0 -s 0x08004000 -D obj/$(PROJ_NAME).bin
|
||||||
|
./tools/dfu-util-$(MACHINE) --reset-stm32 -a 0 -s 0x08000000
|
||||||
|
|
||||||
|
ota: obj/$(PROJ_NAME).bin
|
||||||
|
./tools/ota.py $<
|
||||||
|
|
||||||
|
ifneq ($(wildcard ../.git/HEAD),)
|
||||||
|
obj/gitversion.h: ../.git/HEAD ../.git/index
|
||||||
|
echo "const uint8_t gitversion[] = \"$(shell git rev-parse HEAD)\";" > $@
|
||||||
|
else
|
||||||
|
obj/gitversion.h:
|
||||||
|
echo "const uint8_t gitversion[] = \"RELEASE\";" > $@
|
||||||
|
endif
|
||||||
|
|
||||||
|
obj/bootstub.$(PROJ_NAME).o: bootstub.c early.h
|
||||||
|
$(CC) $(CFLAGS) -o $@ -c $<
|
||||||
|
|
||||||
|
obj/main.$(PROJ_NAME).o: main.c *.h obj/gitversion.h
|
||||||
|
$(CC) $(CFLAGS) -o $@ -c $<
|
||||||
|
|
||||||
|
obj/$(STARTUP_FILE).o: $(STARTUP_FILE).s
|
||||||
|
mkdir -p obj
|
||||||
|
$(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/bootstub.$(PROJ_NAME).bin: obj/$(STARTUP_FILE).o obj/bootstub.$(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,112 @@
|
||||||
|
void can_init(CAN_TypeDef *CAN) {
|
||||||
|
// enable CAN busses
|
||||||
|
if (CAN == CAN1) {
|
||||||
|
#ifdef PANDA
|
||||||
|
// CAN1_EN
|
||||||
|
GPIOC->ODR &= ~(1 << 1);
|
||||||
|
#else
|
||||||
|
// CAN1_EN
|
||||||
|
GPIOB->ODR |= (1 << 3);
|
||||||
|
#endif
|
||||||
|
} else if (CAN == CAN2) {
|
||||||
|
#ifdef PANDA
|
||||||
|
// CAN2_EN
|
||||||
|
GPIOC->ODR &= ~(1 << 13);
|
||||||
|
#else
|
||||||
|
// CAN2_EN
|
||||||
|
GPIOB->ODR |= (1 << 4);
|
||||||
|
#endif
|
||||||
|
#ifdef CAN3
|
||||||
|
} else if (CAN == CAN3) {
|
||||||
|
// CAN3_EN
|
||||||
|
GPIOA->ODR &= ~(1 << 0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
CAN->MCR = CAN_MCR_TTCM | CAN_MCR_INRQ;
|
||||||
|
while((CAN->MSR & CAN_MSR_INAK) != CAN_MSR_INAK);
|
||||||
|
|
||||||
|
// PCLK = 24000000, 500000 is 48 clocks
|
||||||
|
// from http://www.bittiming.can-wiki.ino/
|
||||||
|
CAN->BTR = 0x001c0002;
|
||||||
|
|
||||||
|
// loopback mode for debugging
|
||||||
|
#ifdef CAN_LOOPBACK_MODE
|
||||||
|
CAN->BTR |= CAN_BTR_SILM | CAN_BTR_LBKM;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// reset
|
||||||
|
CAN->MCR = CAN_MCR_TTCM;
|
||||||
|
|
||||||
|
#define CAN_TIMEOUT 1000000
|
||||||
|
int tmp = 0;
|
||||||
|
while((CAN->MSR & CAN_MSR_INAK) == CAN_MSR_INAK && tmp < CAN_TIMEOUT) tmp++;
|
||||||
|
|
||||||
|
if (tmp == CAN_TIMEOUT) {
|
||||||
|
set_led(LED_BLUE, 1);
|
||||||
|
puts("CAN init FAILED!!!!!\n");
|
||||||
|
} else {
|
||||||
|
puts("CAN init done\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// accept all filter
|
||||||
|
CAN->FMR |= CAN_FMR_FINIT;
|
||||||
|
|
||||||
|
// no mask
|
||||||
|
CAN->sFilterRegister[0].FR1 = 0;
|
||||||
|
CAN->sFilterRegister[0].FR2 = 0;
|
||||||
|
CAN->sFilterRegister[14].FR1 = 0;
|
||||||
|
CAN->sFilterRegister[14].FR2 = 0;
|
||||||
|
CAN->FA1R |= 1 | (1 << 14);
|
||||||
|
|
||||||
|
CAN->FMR &= ~(CAN_FMR_FINIT);
|
||||||
|
|
||||||
|
// enable all CAN interrupts
|
||||||
|
CAN->IER = 0xFFFFFFFF;
|
||||||
|
//CAN->IER = CAN_IER_TMEIE | CAN_IER_FMPIE0 | CAN_IER_FMPIE1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// CAN error
|
||||||
|
void can_sce(CAN_TypeDef *CAN) {
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (CAN==CAN1) puts("CAN1: ");
|
||||||
|
if (CAN==CAN2) puts("CAN2: ");
|
||||||
|
#ifdef CAN3
|
||||||
|
if (CAN==CAN3) puts("CAN3: ");
|
||||||
|
#endif
|
||||||
|
puts("MSR:");
|
||||||
|
puth(CAN->MSR);
|
||||||
|
puts(" TSR:");
|
||||||
|
puth(CAN->TSR);
|
||||||
|
puts(" RF0R:");
|
||||||
|
puth(CAN->RF0R);
|
||||||
|
puts(" RF1R:");
|
||||||
|
puth(CAN->RF1R);
|
||||||
|
puts(" ESR:");
|
||||||
|
puth(CAN->ESR);
|
||||||
|
puts("\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// clear
|
||||||
|
//CAN->sTxMailBox[0].TIR &= ~(CAN_TI0R_TXRQ);
|
||||||
|
CAN->TSR |= CAN_TSR_ABRQ0;
|
||||||
|
//CAN->ESR |= CAN_ESR_LEC;
|
||||||
|
//CAN->MSR &= ~(CAN_MSR_ERRI);
|
||||||
|
CAN->MSR = CAN->MSR;
|
||||||
|
}
|
||||||
|
|
||||||
|
int can_cksum(uint8_t *dat, int len, int addr, int idx) {
|
||||||
|
int i;
|
||||||
|
int s = 0;
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
s += (dat[i] >> 4);
|
||||||
|
s += dat[i] & 0xF;
|
||||||
|
}
|
||||||
|
s += (addr>>0)&0xF;
|
||||||
|
s += (addr>>4)&0xF;
|
||||||
|
s += (addr>>8)&0xF;
|
||||||
|
s += idx;
|
||||||
|
s = 8-s;
|
||||||
|
return s&0xF;
|
||||||
|
}
|
||||||
|
|
|
@ -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,84 @@
|
||||||
|
#define ENTER_BOOTLOADER_MAGIC 0xdeadbeef
|
||||||
|
extern uint32_t enter_bootloader_mode;
|
||||||
|
extern void *_app_start[];
|
||||||
|
void *g_pfnVectors;
|
||||||
|
|
||||||
|
int has_external_debug_serial = 0;
|
||||||
|
int is_giant_panda = 0;
|
||||||
|
|
||||||
|
// must call again from main because BSS is zeroed
|
||||||
|
inline void detect() {
|
||||||
|
// detect has_external_debug_serial
|
||||||
|
GPIOA->PUPDR |= GPIO_PUPDR_PUPDR3_1;
|
||||||
|
has_external_debug_serial = (GPIOA->IDR & (1 << 3)) == (1 << 3);
|
||||||
|
|
||||||
|
// detect is_giant_panda
|
||||||
|
is_giant_panda = 0;
|
||||||
|
#ifdef PANDA
|
||||||
|
GPIOB->PUPDR |= GPIO_PUPDR_PUPDR1_1;
|
||||||
|
is_giant_panda = (GPIOB->IDR & (1 << 1)) == (1 << 1);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void early() {
|
||||||
|
// if wrong chip, reboot
|
||||||
|
volatile unsigned int id = DBGMCU->IDCODE;
|
||||||
|
#ifdef STM32F4
|
||||||
|
if ((id&0xFFF) != 0x463) enter_bootloader_mode = ENTER_BOOTLOADER_MAGIC;
|
||||||
|
#else
|
||||||
|
if ((id&0xFFF) != 0x411) enter_bootloader_mode = ENTER_BOOTLOADER_MAGIC;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// setup interrupt table
|
||||||
|
SCB->VTOR = (uint32_t)&g_pfnVectors;
|
||||||
|
|
||||||
|
// early GPIOs
|
||||||
|
RCC->AHB1ENR = RCC_AHB1ENR_GPIOAEN | RCC_AHB1ENR_GPIOBEN | RCC_AHB1ENR_GPIOCEN;
|
||||||
|
GPIOA->MODER = 0; GPIOB->MODER = 0; GPIOC->MODER = 0;
|
||||||
|
GPIOA->ODR = 0; GPIOB->ODR = 0; GPIOC->ODR = 0;
|
||||||
|
GPIOA->PUPDR = 0; GPIOB->PUPDR = 0; GPIOC->PUPDR = 0;
|
||||||
|
|
||||||
|
detect();
|
||||||
|
|
||||||
|
#ifdef PANDA
|
||||||
|
// these are outputs to control the ESP
|
||||||
|
GPIOC->MODER = GPIO_MODER_MODER14_0 | GPIO_MODER_MODER5_0;
|
||||||
|
|
||||||
|
// enable the ESP, disable ESP boot mode
|
||||||
|
// unless we are on a giant panda, then there's no ESP
|
||||||
|
if (!is_giant_panda) {
|
||||||
|
GPIOC->ODR = (1 << 14) | (1 << 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if the ESP is trying to put me in boot mode
|
||||||
|
// enable pull up
|
||||||
|
GPIOB->PUPDR |= GPIO_PUPDR_PUPDR0_0;
|
||||||
|
// if it's driven low, jump to uart bootloader
|
||||||
|
if (!(GPIOB->IDR & 1)) {
|
||||||
|
enter_bootloader_mode = ENTER_BOOTLOADER_MAGIC;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (enter_bootloader_mode == ENTER_BOOTLOADER_MAGIC) {
|
||||||
|
// green LED on
|
||||||
|
// sadly, on the NEO board the bootloader turns it off
|
||||||
|
#ifdef PANDA
|
||||||
|
GPIOC->MODER |= GPIO_MODER_MODER7_0;
|
||||||
|
GPIOC->ODR &= ~(1 << (6 + 1));
|
||||||
|
#else
|
||||||
|
GPIOB->MODER |= GPIO_MODER_MODER11_0;
|
||||||
|
GPIOB->ODR &= ~(1 << (10 + 1));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// do enter bootloader
|
||||||
|
enter_bootloader_mode = 0;
|
||||||
|
void (*bootloader)(void) = (void (*)(void)) (*((uint32_t *)0x1fff0004));
|
||||||
|
|
||||||
|
// jump to bootloader
|
||||||
|
bootloader();
|
||||||
|
|
||||||
|
// LOOP
|
||||||
|
while(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
#!/bin/bash
|
||||||
|
sudo apt-get install gcc-arm-none-eabi
|
|
@ -0,0 +1,70 @@
|
||||||
|
void safety_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||||
|
// 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 brake press
|
||||||
|
if ((to_push->RIR>>21) == 0x17C) {
|
||||||
|
// bit 50
|
||||||
|
if (to_push->RDHR & 0x200000) {
|
||||||
|
controls_allowed = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// exit controls on gas press if interceptor
|
||||||
|
if ((to_push->RIR>>21) == 0x201) {
|
||||||
|
gas_interceptor_detected = 1;
|
||||||
|
int gas = ((to_push->RDLR & 0xFF) << 8) | ((to_push->RDLR & 0xFF00) >> 8);
|
||||||
|
if (gas > 328) {
|
||||||
|
controls_allowed = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// exit controls on gas press if no interceptor
|
||||||
|
if (!gas_interceptor_detected) {
|
||||||
|
if ((to_push->RIR>>21) == 0x17C) {
|
||||||
|
if (to_push->RDLR & 0xFF) {
|
||||||
|
controls_allowed = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void safety_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||||
|
// BRAKE: safety check
|
||||||
|
if ((to_send->RIR>>21) == 0x1FA) {
|
||||||
|
if (controls_allowed) {
|
||||||
|
to_send->RDLR &= 0xFFFFFF3F;
|
||||||
|
} else {
|
||||||
|
to_send->RDLR &= 0xFFFF0000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// STEER: safety check
|
||||||
|
if ((to_send->RIR>>21) == 0xE4) {
|
||||||
|
if (controls_allowed) {
|
||||||
|
to_send->RDLR &= 0xFFFFFFFF;
|
||||||
|
} else {
|
||||||
|
to_send->RDLR &= 0xFFFF0000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GAS: safety check
|
||||||
|
if ((to_send->RIR>>21) == 0x200) {
|
||||||
|
if (controls_allowed) {
|
||||||
|
to_send->RDLR &= 0xFFFFFFFF;
|
||||||
|
} else {
|
||||||
|
to_send->RDLR &= 0xFFFF0000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// block all other messages?
|
||||||
|
}
|
||||||
|
|
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,378 @@
|
||||||
|
#ifdef STM32F4
|
||||||
|
#include "stm32f4xx_hal_gpio_ex.h"
|
||||||
|
#else
|
||||||
|
#include "stm32f2xx_hal_gpio_ex.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#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 __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))
|
||||||
|
|
||||||
|
// **** shitty libc ****
|
||||||
|
|
||||||
|
void clock_init() {
|
||||||
|
#ifdef USE_INTERNAL_OSC
|
||||||
|
// enable internal oscillator
|
||||||
|
RCC->CR |= RCC_CR_HSION;
|
||||||
|
while ((RCC->CR & RCC_CR_HSIRDY) == 0);
|
||||||
|
#else
|
||||||
|
// enable external oscillator
|
||||||
|
RCC->CR |= RCC_CR_HSEON;
|
||||||
|
while ((RCC->CR & RCC_CR_HSERDY) == 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// divide shit
|
||||||
|
RCC->CFGR = RCC_CFGR_HPRE_DIV1 | RCC_CFGR_PPRE2_DIV2 | RCC_CFGR_PPRE1_DIV4;
|
||||||
|
#ifdef USE_INTERNAL_OSC
|
||||||
|
RCC->PLLCFGR = RCC_PLLCFGR_PLLQ_2 | RCC_PLLCFGR_PLLM_3 |
|
||||||
|
RCC_PLLCFGR_PLLN_6 | RCC_PLLCFGR_PLLN_5 | RCC_PLLCFGR_PLLSRC_HSI;
|
||||||
|
#else
|
||||||
|
#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
|
||||||
|
#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 ***
|
||||||
|
|
||||||
|
// enable GPIOB, UART2, CAN, USB clock
|
||||||
|
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
|
||||||
|
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN;
|
||||||
|
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN;
|
||||||
|
RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN;
|
||||||
|
|
||||||
|
RCC->AHB1ENR |= RCC_AHB1ENR_DMA2EN;
|
||||||
|
RCC->APB1ENR |= RCC_APB1ENR_USART2EN;
|
||||||
|
RCC->APB1ENR |= RCC_APB1ENR_USART3EN;
|
||||||
|
#ifdef PANDA
|
||||||
|
RCC->APB1ENR |= RCC_APB1ENR_UART5EN;
|
||||||
|
#endif
|
||||||
|
RCC->APB1ENR |= RCC_APB1ENR_CAN1EN;
|
||||||
|
RCC->APB1ENR |= RCC_APB1ENR_CAN2EN;
|
||||||
|
#ifdef CAN3
|
||||||
|
RCC->APB1ENR |= RCC_APB1ENR_CAN3EN;
|
||||||
|
#endif
|
||||||
|
RCC->APB1ENR |= RCC_APB1ENR_DACEN;
|
||||||
|
RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;
|
||||||
|
//RCC->APB1ENR |= RCC_APB1ENR_TIM4EN;
|
||||||
|
RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
|
||||||
|
RCC->AHB2ENR |= RCC_AHB2ENR_OTGFSEN;
|
||||||
|
RCC->APB2ENR |= RCC_APB2ENR_TIM1EN;
|
||||||
|
RCC->APB2ENR |= RCC_APB2ENR_ADC1EN;
|
||||||
|
RCC->APB2ENR |= RCC_APB2ENR_SPI1EN;
|
||||||
|
|
||||||
|
// needed?
|
||||||
|
RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN;
|
||||||
|
|
||||||
|
// fix interrupt vectors
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_can2_mode(int use_gmlan) {
|
||||||
|
uint32_t speed;
|
||||||
|
|
||||||
|
// connects to CAN2 xcvr or GMLAN xcvr
|
||||||
|
if (use_gmlan) {
|
||||||
|
// disable normal mode
|
||||||
|
GPIOB->MODER &= ~(GPIO_MODER_MODER5_1 | GPIO_MODER_MODER6_1);
|
||||||
|
GPIOB->AFR[0] &= ~(GPIO_AF9_CAN2 << (5*4) | GPIO_AF9_CAN2 << (6*4));
|
||||||
|
|
||||||
|
// gmlan mode
|
||||||
|
GPIOB->MODER |= GPIO_MODER_MODER12_1 | GPIO_MODER_MODER13_1;
|
||||||
|
GPIOB->AFR[1] |= GPIO_AF9_CAN2 << ((12-8)*4) | GPIO_AF9_CAN2 << ((13-8)*4);
|
||||||
|
|
||||||
|
/* GMLAN mode pins:
|
||||||
|
M0(B15) M1(B14) mode
|
||||||
|
=======================
|
||||||
|
0 0 sleep
|
||||||
|
1 0 100kbit
|
||||||
|
0 1 high voltage wakeup
|
||||||
|
1 1 33kbit (normal)
|
||||||
|
*/
|
||||||
|
GPIOB->ODR |= (1 << 15) | (1 << 14);
|
||||||
|
GPIOB->MODER |= GPIO_MODER_MODER14_0 | GPIO_MODER_MODER15_0;
|
||||||
|
|
||||||
|
// 83.3 kbps
|
||||||
|
//speed = 0x001c0011;
|
||||||
|
|
||||||
|
// 33.3 kbps
|
||||||
|
speed = 0x001c002d;
|
||||||
|
} else {
|
||||||
|
// disable GMLAN
|
||||||
|
GPIOB->MODER &= ~(GPIO_MODER_MODER12_1 | GPIO_MODER_MODER13_1);
|
||||||
|
GPIOB->AFR[1] &= ~(GPIO_AF9_CAN2 << ((12-8)*4) | GPIO_AF9_CAN2 << ((13-8)*4));
|
||||||
|
|
||||||
|
// normal mode
|
||||||
|
GPIOB->MODER |= GPIO_MODER_MODER5_1 | GPIO_MODER_MODER6_1;
|
||||||
|
GPIOB->AFR[0] |= GPIO_AF9_CAN2 << (5*4) | GPIO_AF9_CAN2 << (6*4);
|
||||||
|
|
||||||
|
speed = 0x001c0002;
|
||||||
|
}
|
||||||
|
|
||||||
|
// init
|
||||||
|
CAN2->MCR = CAN_MCR_TTCM | CAN_MCR_INRQ;
|
||||||
|
while((CAN2->MSR & CAN_MSR_INAK) != CAN_MSR_INAK);
|
||||||
|
|
||||||
|
// set speed
|
||||||
|
CAN2->BTR = speed;
|
||||||
|
|
||||||
|
// running
|
||||||
|
CAN2->MCR = CAN_MCR_TTCM;
|
||||||
|
while((CAN2->MSR & CAN_MSR_INAK) == CAN_MSR_INAK);
|
||||||
|
}
|
||||||
|
|
||||||
|
// board specific
|
||||||
|
void gpio_init() {
|
||||||
|
// pull low to hold ESP in reset??
|
||||||
|
// enable OTG out tied to ground
|
||||||
|
GPIOA->ODR = 0;
|
||||||
|
GPIOB->ODR = 0;
|
||||||
|
GPIOA->PUPDR = 0;
|
||||||
|
//GPIOC->ODR = 0;
|
||||||
|
GPIOB->AFR[0] = 0;
|
||||||
|
GPIOB->AFR[1] = 0;
|
||||||
|
|
||||||
|
// enable USB power tied to +
|
||||||
|
GPIOA->MODER = GPIO_MODER_MODER0_0;
|
||||||
|
|
||||||
|
// always set to zero, ESP in boot mode and reset
|
||||||
|
//GPIOB->MODER = GPIO_MODER_MODER0_0;
|
||||||
|
|
||||||
|
// analog mode
|
||||||
|
GPIOC->MODER |= GPIO_MODER_MODER3 | GPIO_MODER_MODER2;
|
||||||
|
//GPIOC->MODER |= GPIO_MODER_MODER1 | GPIO_MODER_MODER0;
|
||||||
|
|
||||||
|
// FAN on C9, aka TIM3_CH4
|
||||||
|
GPIOC->MODER |= GPIO_MODER_MODER8_1;
|
||||||
|
GPIOC->AFR[1] = GPIO_AF2_TIM3 << ((8-8)*4);
|
||||||
|
// IGNITION on C13
|
||||||
|
|
||||||
|
#ifdef PANDA
|
||||||
|
// turn off LEDs and set mode
|
||||||
|
GPIOC->ODR |= (1 << 6) | (1 << 7) | (1 << 9);
|
||||||
|
GPIOC->MODER |= GPIO_MODER_MODER6_0 | GPIO_MODER_MODER7_0 | GPIO_MODER_MODER9_0;
|
||||||
|
|
||||||
|
// set mode for ESP_RST line and enable it
|
||||||
|
// (done in init_hardware_early
|
||||||
|
//GPIOC->ODR |= (1 << 14) | (1 << 5);
|
||||||
|
//GPIOC->MODER |= GPIO_MODER_MODER14_0 | GPIO_MODER_MODER5_0;
|
||||||
|
|
||||||
|
// panda CAN enables
|
||||||
|
GPIOC->ODR |= (1 << 13) | (1 << 1);
|
||||||
|
GPIOC->MODER |= GPIO_MODER_MODER13_0 | GPIO_MODER_MODER1_0;
|
||||||
|
|
||||||
|
// enable started_alt
|
||||||
|
GPIOA->PUPDR |= GPIO_PUPDR_PUPDR1_0;
|
||||||
|
#else
|
||||||
|
// turn off LEDs and set mode
|
||||||
|
GPIOB->ODR = (1 << 10) | (1 << 11) | (1 << 12);
|
||||||
|
GPIOB->MODER = GPIO_MODER_MODER10_0 | GPIO_MODER_MODER11_0 | GPIO_MODER_MODER12_0;
|
||||||
|
|
||||||
|
// non panda CAN enables
|
||||||
|
GPIOB->MODER |= GPIO_MODER_MODER3_0 | GPIO_MODER_MODER7_0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// CAN 2 in normal mode
|
||||||
|
set_can2_mode(0);
|
||||||
|
|
||||||
|
// CAN 1
|
||||||
|
GPIOB->MODER |= GPIO_MODER_MODER8_1 | GPIO_MODER_MODER9_1;
|
||||||
|
#ifdef STM32F4
|
||||||
|
GPIOB->AFR[1] |= GPIO_AF8_CAN1 << ((8-8)*4) | GPIO_AF8_CAN1 << ((9-8)*4);
|
||||||
|
#else
|
||||||
|
GPIOB->AFR[1] |= GPIO_AF9_CAN1 << ((8-8)*4) | GPIO_AF9_CAN1 << ((9-8)*4);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// K enable + L enable
|
||||||
|
GPIOB->ODR |= (1 << 4);
|
||||||
|
GPIOB->MODER |= GPIO_MODER_MODER4_0;
|
||||||
|
GPIOA->ODR |= (1 << 14);
|
||||||
|
GPIOA->MODER |= GPIO_MODER_MODER14_0;
|
||||||
|
|
||||||
|
// USART 2 for debugging
|
||||||
|
GPIOA->MODER |= GPIO_MODER_MODER2_1 | GPIO_MODER_MODER3_1;
|
||||||
|
GPIOA->AFR[0] = GPIO_AF7_USART2 << (2*4) | GPIO_AF7_USART2 << (3*4);
|
||||||
|
|
||||||
|
// USART 1 for talking to the ESP
|
||||||
|
GPIOA->MODER |= GPIO_MODER_MODER9_1 | GPIO_MODER_MODER10_1;
|
||||||
|
GPIOA->AFR[1] = GPIO_AF7_USART1 << ((9-8)*4) | GPIO_AF7_USART1 << ((10-8)*4);
|
||||||
|
|
||||||
|
// USART 3 is L-Line
|
||||||
|
GPIOC->MODER |= GPIO_MODER_MODER10_1 | GPIO_MODER_MODER11_1;
|
||||||
|
GPIOC->AFR[1] |= GPIO_AF7_USART3 << ((10-8)*4) | GPIO_AF7_USART3 << ((11-8)*4);
|
||||||
|
GPIOC->PUPDR = GPIO_PUPDR_PUPDR11_0;
|
||||||
|
|
||||||
|
// USB
|
||||||
|
GPIOA->MODER |= GPIO_MODER_MODER11_1 | GPIO_MODER_MODER12_1;
|
||||||
|
GPIOA->OSPEEDR = GPIO_OSPEEDER_OSPEEDR11 | GPIO_OSPEEDER_OSPEEDR12;
|
||||||
|
GPIOA->AFR[1] |= GPIO_AF10_OTG_FS << ((11-8)*4) | GPIO_AF10_OTG_FS << ((12-8)*4);
|
||||||
|
GPIOA->PUPDR |= GPIO_PUPDR_PUPDR2_0 | GPIO_PUPDR_PUPDR3_0;
|
||||||
|
|
||||||
|
// GMLAN, ignition sense, pull up
|
||||||
|
GPIOB->PUPDR |= GPIO_PUPDR_PUPDR12_0;
|
||||||
|
|
||||||
|
// setup SPI
|
||||||
|
GPIOA->MODER |= GPIO_MODER_MODER4_1 | GPIO_MODER_MODER5_1 |
|
||||||
|
GPIO_MODER_MODER6_1 | GPIO_MODER_MODER7_1;
|
||||||
|
GPIOA->AFR[0] |= GPIO_AF5_SPI1 << (4*4) | GPIO_AF5_SPI1 << (5*4) |
|
||||||
|
GPIO_AF5_SPI1 << (6*4) | GPIO_AF5_SPI1 << (7*4);
|
||||||
|
|
||||||
|
// CAN3 setup
|
||||||
|
#ifdef CAN3
|
||||||
|
GPIOA->MODER |= GPIO_MODER_MODER8_1 | GPIO_MODER_MODER15_1;
|
||||||
|
GPIOA->AFR[1] |= GPIO_AF11_CAN3 << ((8-8)*4) | GPIO_AF11_CAN3 << ((15-8)*4);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// K-Line setup
|
||||||
|
#ifdef PANDA
|
||||||
|
GPIOC->AFR[1] |= GPIO_AF8_UART5 << ((12-8)*4);
|
||||||
|
GPIOC->MODER |= GPIO_MODER_MODER12_1;
|
||||||
|
GPIOD->AFR[0] = GPIO_AF8_UART5 << (2*4);
|
||||||
|
GPIOD->MODER = GPIO_MODER_MODER2_1;
|
||||||
|
GPIOD->PUPDR = GPIO_PUPDR_PUPDR2_0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void uart_set_baud(USART_TypeDef *u, int baud) {
|
||||||
|
if (u == USART1) {
|
||||||
|
// USART1 is on APB2
|
||||||
|
u->BRR = __USART_BRR(48000000, baud);
|
||||||
|
} else {
|
||||||
|
u->BRR = __USART_BRR(24000000, baud);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void uart_init(USART_TypeDef *u, int baud) {
|
||||||
|
// enable uart and tx+rx mode
|
||||||
|
u->CR1 = USART_CR1_UE;
|
||||||
|
uart_set_baud(u, baud);
|
||||||
|
|
||||||
|
u->CR1 |= USART_CR1_TE | USART_CR1_RE;
|
||||||
|
//u->CR2 = USART_CR2_STOP_0 | USART_CR2_STOP_1;
|
||||||
|
//u->CR2 = USART_CR2_STOP_0;
|
||||||
|
// ** UART is ready to work **
|
||||||
|
|
||||||
|
// enable interrupts
|
||||||
|
u->CR1 |= USART_CR1_RXNEIE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void delay(int a) {
|
||||||
|
volatile int i;
|
||||||
|
for (i=0;i<a;i++);
|
||||||
|
}
|
||||||
|
|
||||||
|
void putch(const char a) {
|
||||||
|
if (has_external_debug_serial) {
|
||||||
|
putc(&debug_ring, a);
|
||||||
|
} else {
|
||||||
|
injectc(&debug_ring, a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int puts(const char *a) {
|
||||||
|
for (;*a;a++) {
|
||||||
|
if (*a == '\n') putch('\r');
|
||||||
|
putch(*a);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void puth(unsigned int i) {
|
||||||
|
int pos;
|
||||||
|
char c[] = "0123456789abcdef";
|
||||||
|
for (pos = 28; pos != -4; pos -= 4) {
|
||||||
|
putch(c[(i >> pos) & 0xF]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void puth2(unsigned int i) {
|
||||||
|
int pos;
|
||||||
|
char c[] = "0123456789abcdef";
|
||||||
|
for (pos = 4; pos != -4; pos -= 4) {
|
||||||
|
putch(c[(i >> pos) & 0xF]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void hexdump(void *a, int l) {
|
||||||
|
int i;
|
||||||
|
for (i=0;i<l;i++) {
|
||||||
|
if (i != 0 && (i&0xf) == 0) puts("\n");
|
||||||
|
puth2(((unsigned char*)a)[i]);
|
||||||
|
puts(" ");
|
||||||
|
}
|
||||||
|
puts("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef PANDA
|
||||||
|
#define LED_RED 3
|
||||||
|
#define LED_GREEN 1
|
||||||
|
#define LED_BLUE 0
|
||||||
|
#else
|
||||||
|
#define LED_RED 0
|
||||||
|
#define LED_GREEN 1
|
||||||
|
#define LED_BLUE -1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void set_led(int led_num, int on) {
|
||||||
|
if (led_num == -1) return;
|
||||||
|
if (on) {
|
||||||
|
// turn on
|
||||||
|
#ifdef PANDA
|
||||||
|
GPIOC->ODR &= ~(1 << (6 + led_num));
|
||||||
|
#else
|
||||||
|
GPIOB->ODR &= ~(1 << (10 + led_num));
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
// turn off
|
||||||
|
#ifdef PANDA
|
||||||
|
GPIOC->ODR |= (1 << (6 + led_num));
|
||||||
|
#else
|
||||||
|
GPIOB->ODR |= (1 << (10 + led_num));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,859 @@
|
||||||
|
//#define DEBUG
|
||||||
|
//#define DEBUG_USB
|
||||||
|
//#define CAN_LOOPBACK_MODE
|
||||||
|
//#define USE_INTERNAL_OSC
|
||||||
|
|
||||||
|
#ifdef STM32F4
|
||||||
|
#define PANDA
|
||||||
|
#include "stm32f4xx.h"
|
||||||
|
#else
|
||||||
|
#include "stm32f2xx.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef PANDA
|
||||||
|
#define ENABLE_CURRENT_SENSOR
|
||||||
|
#define ENABLE_SPI
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define USB_VID 0xbbaa
|
||||||
|
#define USB_PID 0xddcc
|
||||||
|
|
||||||
|
#define NULL ((void*)0)
|
||||||
|
|
||||||
|
#include "early.h"
|
||||||
|
|
||||||
|
// assign CAN numbering
|
||||||
|
// old: CAN1 = 1 CAN2 = 0
|
||||||
|
// panda: CAN1 = 0 CAN2 = 1 CAN3 = 4
|
||||||
|
#ifdef PANDA
|
||||||
|
int can_numbering[] = {0,1,4};
|
||||||
|
#else
|
||||||
|
int can_numbering[] = {1,0,-1};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// *** end config ***
|
||||||
|
|
||||||
|
#include "obj/gitversion.h"
|
||||||
|
|
||||||
|
// debug safety check: is controls allowed?
|
||||||
|
int controls_allowed = 0;
|
||||||
|
int started = 0;
|
||||||
|
int can_live = 0, pending_can_live = 0;
|
||||||
|
|
||||||
|
// optional features
|
||||||
|
int gas_interceptor_detected = 0;
|
||||||
|
int started_signal_detected = 0;
|
||||||
|
|
||||||
|
// detect high on UART
|
||||||
|
// TODO: check for UART high
|
||||||
|
int did_usb_enumerate = 0;
|
||||||
|
|
||||||
|
// ********************* instantiate queues *********************
|
||||||
|
|
||||||
|
#define FIFO_SIZE 0x100
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t w_ptr;
|
||||||
|
uint8_t r_ptr;
|
||||||
|
CAN_FIFOMailBox_TypeDef elems[FIFO_SIZE];
|
||||||
|
} can_ring;
|
||||||
|
|
||||||
|
can_ring can_rx_q = { .w_ptr = 0, .r_ptr = 0 };
|
||||||
|
can_ring can_tx1_q = { .w_ptr = 0, .r_ptr = 0 };
|
||||||
|
can_ring can_tx2_q = { .w_ptr = 0, .r_ptr = 0 };
|
||||||
|
can_ring can_tx3_q = { .w_ptr = 0, .r_ptr = 0 };
|
||||||
|
|
||||||
|
// ********************* interrupt safe queue *********************
|
||||||
|
|
||||||
|
inline int pop(can_ring *q, CAN_FIFOMailBox_TypeDef *elem) {
|
||||||
|
if (q->w_ptr != q->r_ptr) {
|
||||||
|
*elem = q->elems[q->r_ptr];
|
||||||
|
q->r_ptr += 1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int push(can_ring *q, CAN_FIFOMailBox_TypeDef *elem) {
|
||||||
|
uint8_t next_w_ptr = q->w_ptr + 1;
|
||||||
|
if (next_w_ptr != q->r_ptr) {
|
||||||
|
q->elems[q->w_ptr] = *elem;
|
||||||
|
q->w_ptr = next_w_ptr;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ***************************** serial port queues *****************************
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
inline int putc(uart_ring *q, char elem);
|
||||||
|
|
||||||
|
// esp = USART1
|
||||||
|
uart_ring esp_ring = { .w_ptr_tx = 0, .r_ptr_tx = 0,
|
||||||
|
.w_ptr_rx = 0, .r_ptr_rx = 0,
|
||||||
|
.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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ***************************** serial port *****************************
|
||||||
|
|
||||||
|
void uart_ring_process(uart_ring *q) {
|
||||||
|
// TODO: check if external serial is connected
|
||||||
|
int sr = q->uart->SR;
|
||||||
|
|
||||||
|
if (q->w_ptr_tx != q->r_ptr_tx) {
|
||||||
|
if (sr & USART_SR_TXE) {
|
||||||
|
q->uart->DR = q->elems_tx[q->r_ptr_tx];
|
||||||
|
q->r_ptr_tx += 1;
|
||||||
|
} else {
|
||||||
|
// push on interrupt later
|
||||||
|
q->uart->CR1 |= USART_CR1_TXEIE;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// nothing to send
|
||||||
|
q->uart->CR1 &= ~USART_CR1_TXEIE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sr & USART_SR_RXNE) {
|
||||||
|
uint8_t c = q->uart->DR; // TODO: can drop packets
|
||||||
|
uint8_t next_w_ptr = q->w_ptr_rx + 1;
|
||||||
|
if (next_w_ptr != q->r_ptr_rx) {
|
||||||
|
q->elems_rx[q->w_ptr_rx] = c;
|
||||||
|
q->w_ptr_rx = next_w_ptr;
|
||||||
|
if (q->callback) q->callback(q);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// interrupt boilerplate
|
||||||
|
|
||||||
|
void USART1_IRQHandler(void) {
|
||||||
|
NVIC_DisableIRQ(USART1_IRQn);
|
||||||
|
uart_ring_process(&esp_ring);
|
||||||
|
NVIC_EnableIRQ(USART1_IRQn);
|
||||||
|
}
|
||||||
|
|
||||||
|
void USART2_IRQHandler(void) {
|
||||||
|
NVIC_DisableIRQ(USART2_IRQn);
|
||||||
|
uart_ring_process(&debug_ring);
|
||||||
|
NVIC_EnableIRQ(USART2_IRQn);
|
||||||
|
}
|
||||||
|
|
||||||
|
void USART3_IRQHandler(void) {
|
||||||
|
NVIC_DisableIRQ(USART3_IRQn);
|
||||||
|
uart_ring_process(&lin2_ring);
|
||||||
|
NVIC_EnableIRQ(USART3_IRQn);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UART5_IRQHandler(void) {
|
||||||
|
NVIC_DisableIRQ(UART5_IRQn);
|
||||||
|
uart_ring_process(&lin1_ring);
|
||||||
|
NVIC_EnableIRQ(UART5_IRQn);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int getc(uart_ring *q, char *elem) {
|
||||||
|
if (q->w_ptr_rx != q->r_ptr_rx) {
|
||||||
|
*elem = q->elems_rx[q->r_ptr_rx];
|
||||||
|
q->r_ptr_rx += 1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int injectc(uart_ring *q, char elem) {
|
||||||
|
uint8_t next_w_ptr = q->w_ptr_rx + 1;
|
||||||
|
int ret = 0;
|
||||||
|
if (next_w_ptr != q->r_ptr_rx) {
|
||||||
|
q->elems_rx[q->w_ptr_rx] = elem;
|
||||||
|
q->w_ptr_rx = next_w_ptr;
|
||||||
|
ret = 1;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int putc(uart_ring *q, char elem) {
|
||||||
|
uint8_t next_w_ptr = q->w_ptr_tx + 1;
|
||||||
|
int ret = 0;
|
||||||
|
if (next_w_ptr != q->r_ptr_tx) {
|
||||||
|
q->elems_tx[q->w_ptr_tx] = elem;
|
||||||
|
q->w_ptr_tx = next_w_ptr;
|
||||||
|
ret = 1;
|
||||||
|
}
|
||||||
|
uart_ring_process(q);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ********************* includes *********************
|
||||||
|
|
||||||
|
#include "libc.h"
|
||||||
|
#include "adc.h"
|
||||||
|
#include "timer.h"
|
||||||
|
#include "usb.h"
|
||||||
|
#include "can.h"
|
||||||
|
#include "spi.h"
|
||||||
|
|
||||||
|
void safety_rx_hook(CAN_FIFOMailBox_TypeDef *to_push);
|
||||||
|
void safety_tx_hook(CAN_FIFOMailBox_TypeDef *to_send);
|
||||||
|
#include "honda_safety.h"
|
||||||
|
|
||||||
|
// ***************************** CAN *****************************
|
||||||
|
|
||||||
|
void process_can(CAN_TypeDef *CAN, can_ring *can_q, int can_number) {
|
||||||
|
#ifdef DEBUG
|
||||||
|
puts("process CAN TX\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// add successfully transmitted message to my fifo
|
||||||
|
if ((CAN->TSR & CAN_TSR_TXOK0) == CAN_TSR_TXOK0) {
|
||||||
|
CAN_FIFOMailBox_TypeDef to_push;
|
||||||
|
to_push.RIR = CAN->sTxMailBox[0].TIR;
|
||||||
|
to_push.RDTR = (CAN->sTxMailBox[0].TDTR & 0xFFFF000F) | ((can_number+2) << 4);
|
||||||
|
to_push.RDLR = CAN->sTxMailBox[0].TDLR;
|
||||||
|
to_push.RDHR = CAN->sTxMailBox[0].TDHR;
|
||||||
|
push(&can_rx_q, &to_push);
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for empty mailbox
|
||||||
|
CAN_FIFOMailBox_TypeDef to_send;
|
||||||
|
if ((CAN->TSR & CAN_TSR_TME0) == CAN_TSR_TME0) {
|
||||||
|
if (pop(can_q, &to_send)) {
|
||||||
|
safety_tx_hook(&to_send);
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear interrupt
|
||||||
|
CAN->TSR |= CAN_TSR_RQCP0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// send more, possible for these to not trigger?
|
||||||
|
|
||||||
|
|
||||||
|
void CAN1_TX_IRQHandler() {
|
||||||
|
process_can(CAN1, &can_tx1_q, can_numbering[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CAN2_TX_IRQHandler() {
|
||||||
|
process_can(CAN2, &can_tx2_q, can_numbering[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CAN3
|
||||||
|
void CAN3_TX_IRQHandler() {
|
||||||
|
process_can(CAN3, &can_tx3_q, can_numbering[2]);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// board enforces
|
||||||
|
// in-state
|
||||||
|
// accel set/resume
|
||||||
|
// out-state
|
||||||
|
// cancel button
|
||||||
|
|
||||||
|
|
||||||
|
// all commands: brake and steering
|
||||||
|
// if controls_allowed
|
||||||
|
// allow all commands up to limit
|
||||||
|
// else
|
||||||
|
// block all commands that produce actuation
|
||||||
|
|
||||||
|
// CAN receive handlers
|
||||||
|
// blink blue when we are receiving CAN messages
|
||||||
|
void can_rx(CAN_TypeDef *CAN, int can_number) {
|
||||||
|
while (CAN->RF0R & CAN_RF0R_FMP0) {
|
||||||
|
// can is live
|
||||||
|
pending_can_live = 1;
|
||||||
|
|
||||||
|
// add to my fifo
|
||||||
|
CAN_FIFOMailBox_TypeDef to_push;
|
||||||
|
to_push.RIR = CAN->sFIFOMailBox[0].RIR;
|
||||||
|
// top 16-bits is the timestamp
|
||||||
|
to_push.RDTR = (CAN->sFIFOMailBox[0].RDTR & 0xFFFF000F) | (can_number << 4);
|
||||||
|
to_push.RDLR = CAN->sFIFOMailBox[0].RDLR;
|
||||||
|
to_push.RDHR = CAN->sFIFOMailBox[0].RDHR;
|
||||||
|
|
||||||
|
safety_rx_hook(&to_push);
|
||||||
|
|
||||||
|
set_led(LED_BLUE, 1);
|
||||||
|
push(&can_rx_q, &to_push);
|
||||||
|
|
||||||
|
// next
|
||||||
|
CAN->RF0R |= CAN_RF0R_RFOM0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CAN1_RX0_IRQHandler() {
|
||||||
|
//puts("CANRX1");
|
||||||
|
//delay(10000);
|
||||||
|
can_rx(CAN1, can_numbering[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CAN2_RX0_IRQHandler() {
|
||||||
|
//puts("CANRX0");
|
||||||
|
//delay(10000);
|
||||||
|
can_rx(CAN2, can_numbering[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CAN3
|
||||||
|
void CAN3_RX0_IRQHandler() {
|
||||||
|
//puts("CANRX0");
|
||||||
|
//delay(10000);
|
||||||
|
can_rx(CAN3, can_numbering[2]);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void CAN1_SCE_IRQHandler() {
|
||||||
|
//puts("CAN1_SCE\n");
|
||||||
|
can_sce(CAN1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CAN2_SCE_IRQHandler() {
|
||||||
|
//puts("CAN2_SCE\n");
|
||||||
|
can_sce(CAN2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CAN3
|
||||||
|
void CAN3_SCE_IRQHandler() {
|
||||||
|
//puts("CAN3_SCE\n");
|
||||||
|
can_sce(CAN3);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// ***************************** 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;
|
||||||
|
health->voltage = adc_get(ADCCHAN_VOLTAGE);
|
||||||
|
#ifdef ENABLE_CURRENT_SENSOR
|
||||||
|
health->current = adc_get(ADCCHAN_CURRENT);
|
||||||
|
#else
|
||||||
|
health->current = 0;
|
||||||
|
#endif
|
||||||
|
health->started = started;
|
||||||
|
|
||||||
|
#ifdef PANDA
|
||||||
|
health->started_alt = (GPIOA->IDR & (1 << 1)) == 0;
|
||||||
|
#else
|
||||||
|
health->started_alt = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
health->controls_allowed = controls_allowed;
|
||||||
|
|
||||||
|
health->gas_interceptor_detected = gas_interceptor_detected;
|
||||||
|
health->started_signal_detected = started_signal_detected;
|
||||||
|
return sizeof(*health);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_fan_speed(int fan_speed) {
|
||||||
|
TIM3->CCR3 = fan_speed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void usb_cb_ep1_in(int len) {
|
||||||
|
CAN_FIFOMailBox_TypeDef reply[4];
|
||||||
|
|
||||||
|
int ilen = 0;
|
||||||
|
while (ilen < min(len/0x10, 4) && pop(&can_rx_q, &reply[ilen])) ilen++;
|
||||||
|
|
||||||
|
/*#ifdef DEBUG
|
||||||
|
puts("FIFO SENDING ");
|
||||||
|
puth(ilen);
|
||||||
|
puts("\n");
|
||||||
|
#endif*/
|
||||||
|
|
||||||
|
USB_WritePacket((void *)reply, ilen*0x10, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// send on serial, first byte to select
|
||||||
|
void usb_cb_ep2_out(uint8_t *usbdata, int len) {
|
||||||
|
int i;
|
||||||
|
if (len == 0) return;
|
||||||
|
uart_ring *ur = get_ring_by_number(usbdata[0]);
|
||||||
|
if (!ur) return;
|
||||||
|
for (i = 1; i < len; i++) while (!putc(ur, usbdata[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
// send on CAN
|
||||||
|
void usb_cb_ep3_out(uint8_t *usbdata, int len) {
|
||||||
|
int dpkt = 0;
|
||||||
|
for (dpkt = 0; dpkt < len; dpkt += 0x10) {
|
||||||
|
uint32_t *tf = (uint32_t*)(&usbdata[dpkt]);
|
||||||
|
int flags = (tf[1] >> 4) & 0xF;
|
||||||
|
|
||||||
|
//puth(flags); puts("\n");
|
||||||
|
CAN_TypeDef *CAN;
|
||||||
|
can_ring *can_q;
|
||||||
|
int can_number;
|
||||||
|
if (flags == can_numbering[0]) {
|
||||||
|
CAN = CAN1;
|
||||||
|
can_q = &can_tx1_q;
|
||||||
|
} else if (flags == can_numbering[1]) {
|
||||||
|
CAN = CAN2;
|
||||||
|
can_q = &can_tx2_q;
|
||||||
|
#ifdef CAN3
|
||||||
|
} else if (flags == can_numbering[2]) {
|
||||||
|
CAN = CAN3;
|
||||||
|
can_q = &can_tx3_q;
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
// no crash
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add CAN packet to send queue
|
||||||
|
CAN_FIFOMailBox_TypeDef to_push;
|
||||||
|
to_push.RDHR = tf[3];
|
||||||
|
to_push.RDLR = tf[2];
|
||||||
|
to_push.RDTR = tf[1] & 0xF;
|
||||||
|
to_push.RIR = tf[0];
|
||||||
|
push(can_q, &to_push);
|
||||||
|
|
||||||
|
// flags = can_number
|
||||||
|
process_can(CAN, can_q, flags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void usb_cb_enumeration_complete() {
|
||||||
|
// power down the ESP
|
||||||
|
// this doesn't work and makes the board unflashable
|
||||||
|
// because the ESP spews shit on serial on startup
|
||||||
|
//GPIOC->ODR &= ~(1 << 14);
|
||||||
|
did_usb_enumerate = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define MAX_RESP_LEN 0x30
|
||||||
|
void usb_cb_control_msg() {
|
||||||
|
uint8_t resp[MAX_RESP_LEN];
|
||||||
|
int resp_len = 0;
|
||||||
|
uart_ring *ur = NULL;
|
||||||
|
int i;
|
||||||
|
switch (setup.b.bRequest) {
|
||||||
|
case 0xd1:
|
||||||
|
enter_bootloader_mode = ENTER_BOOTLOADER_MAGIC;
|
||||||
|
NVIC_SystemReset();
|
||||||
|
break;
|
||||||
|
case 0xd2:
|
||||||
|
resp_len = get_health_pkt(resp);
|
||||||
|
USB_WritePacket(resp, resp_len, 0);
|
||||||
|
USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
|
||||||
|
break;
|
||||||
|
case 0xd3:
|
||||||
|
set_fan_speed(setup.b.wValue.w);
|
||||||
|
USB_WritePacket(0, 0, 0);
|
||||||
|
USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
|
||||||
|
break;
|
||||||
|
case 0xd6: // GET_VERSION
|
||||||
|
USB_WritePacket(gitversion, min(sizeof(gitversion), setup.b.wLength.w), 0);
|
||||||
|
USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
|
||||||
|
break;
|
||||||
|
case 0xd8: // RESET
|
||||||
|
NVIC_SystemReset();
|
||||||
|
break;
|
||||||
|
case 0xda: // ESP RESET
|
||||||
|
// pull low for ESP boot mode
|
||||||
|
if (setup.b.wValue.w == 1) {
|
||||||
|
GPIOC->ODR &= ~(1 << 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
// do ESP reset
|
||||||
|
GPIOC->ODR &= ~(1 << 14);
|
||||||
|
delay(1000000);
|
||||||
|
GPIOC->ODR |= (1 << 14);
|
||||||
|
delay(1000000);
|
||||||
|
|
||||||
|
// reset done, no more boot mode
|
||||||
|
// TODO: ESP doesn't seem to listen here
|
||||||
|
if (setup.b.wValue.w == 1) {
|
||||||
|
GPIOC->ODR |= (1 << 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
USB_WritePacket(0, 0, 0);
|
||||||
|
USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
|
||||||
|
break;
|
||||||
|
case 0xdb: // toggle GMLAN
|
||||||
|
set_can2_mode(setup.b.wValue.w);
|
||||||
|
|
||||||
|
// null reply
|
||||||
|
USB_WritePacket(resp, resp_len, 0);
|
||||||
|
USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
|
||||||
|
break;
|
||||||
|
case 0xe0: // uart read
|
||||||
|
ur = get_ring_by_number(setup.b.wValue.w);
|
||||||
|
if (!ur) break;
|
||||||
|
if (setup.b.bRequest == 0xe0) {
|
||||||
|
// read
|
||||||
|
while (resp_len < min(setup.b.wLength.w, MAX_RESP_LEN) && getc(ur, &resp[resp_len])) {
|
||||||
|
++resp_len;
|
||||||
|
}
|
||||||
|
/*puts("uart read: ");
|
||||||
|
puth(setup.b.wLength.w);
|
||||||
|
puts(" ");
|
||||||
|
puth(resp_len);
|
||||||
|
puts("\n");*/
|
||||||
|
USB_WritePacket(resp, resp_len, 0);
|
||||||
|
USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0xe1: // uart set baud rate
|
||||||
|
ur = get_ring_by_number(setup.b.wValue.w);
|
||||||
|
uart_set_baud(ur->uart, setup.b.wIndex.w);
|
||||||
|
//puth(ur->uart->BRR); puts("\n");
|
||||||
|
|
||||||
|
// null reply
|
||||||
|
USB_WritePacket(resp, resp_len, 0);
|
||||||
|
USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
|
||||||
|
break;
|
||||||
|
case 0xf0: // k-line wValue pulse on uart2
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
//delay((int)setup.b.wValue.w * 8000);
|
||||||
|
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);
|
||||||
|
//delay((int)setup.b.wIndex.w * 8000);
|
||||||
|
|
||||||
|
// null reply
|
||||||
|
USB_WritePacket(resp, resp_len, 0);
|
||||||
|
USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
puts("NO HANDLER ");
|
||||||
|
puth(setup.b.bRequest);
|
||||||
|
puts("\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void OTG_FS_IRQHandler(void) {
|
||||||
|
NVIC_DisableIRQ(OTG_FS_IRQn);
|
||||||
|
//__disable_irq();
|
||||||
|
usb_irqhandler();
|
||||||
|
//__enable_irq();
|
||||||
|
NVIC_EnableIRQ(OTG_FS_IRQn);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ADC_IRQHandler(void) {
|
||||||
|
puts("ADC_IRQ\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ENABLE_SPI
|
||||||
|
|
||||||
|
#define SPI_BUF_SIZE 128
|
||||||
|
uint8_t spi_buf[SPI_BUF_SIZE];
|
||||||
|
int spi_buf_count = 0;
|
||||||
|
uint8_t spi_tx_buf[0x10];
|
||||||
|
|
||||||
|
/*void SPI1_IRQHandler(void) {
|
||||||
|
// status is 0x43
|
||||||
|
if (SPI1->SR & SPI_SR_RXNE) {
|
||||||
|
uint8_t dat = SPI1->DR;
|
||||||
|
spi_buf[spi_buf_count] = dat;
|
||||||
|
if (spi_buf_count < SPI_BUF_SIZE-1) {
|
||||||
|
spi_buf_count += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SPI1->SR & SPI_SR_TXE) {
|
||||||
|
// all i send is U U U no matter what
|
||||||
|
//SPI1->DR = 'U';
|
||||||
|
}
|
||||||
|
|
||||||
|
int stat = SPI1->SR;
|
||||||
|
if (stat & ((~SPI_SR_RXNE) & (~SPI_SR_TXE) & (~SPI_SR_BSY))) {
|
||||||
|
puts("SPI status: ");
|
||||||
|
puth(stat);
|
||||||
|
puts("\n");
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
void DMA2_Stream3_IRQHandler(void) {
|
||||||
|
// ack
|
||||||
|
DMA2->LIFCR = DMA_LIFCR_CTCIF3;
|
||||||
|
|
||||||
|
// reenable interrupt
|
||||||
|
EXTI->IMR |= (1 << 4);
|
||||||
|
//puts("stop\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EXTI4_IRQHandler(void) {
|
||||||
|
int pr = EXTI->PR;
|
||||||
|
// SPI CS rising
|
||||||
|
if (pr & (1 << 4)) {
|
||||||
|
if (pop(&can_rx_q, spi_tx_buf)) {
|
||||||
|
spi_tx_dma(spi_tx_buf, 0x10);
|
||||||
|
} else {
|
||||||
|
memset(spi_tx_buf, 0, 0x10);
|
||||||
|
spi_tx_dma(spi_tx_buf, 0x10);
|
||||||
|
}
|
||||||
|
//puts("start\n");
|
||||||
|
EXTI->IMR &= ~(1 << 4);
|
||||||
|
}
|
||||||
|
EXTI->PR = pr;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ***************************** main code *****************************
|
||||||
|
|
||||||
|
void __initialize_hardware_early() {
|
||||||
|
early();
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
// init devices
|
||||||
|
clock_init();
|
||||||
|
detect();
|
||||||
|
gpio_init();
|
||||||
|
|
||||||
|
// enable main uart
|
||||||
|
uart_init(USART2, 115200);
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
/*puts("EXTERNAL");
|
||||||
|
puth(has_external_debug_serial);
|
||||||
|
puts("\n");*/
|
||||||
|
|
||||||
|
// enable USB
|
||||||
|
usb_init();
|
||||||
|
|
||||||
|
can_init(CAN1);
|
||||||
|
can_init(CAN2);
|
||||||
|
#ifdef CAN3
|
||||||
|
can_init(CAN3);
|
||||||
|
#endif
|
||||||
|
adc_init();
|
||||||
|
|
||||||
|
#ifdef ENABLE_SPI
|
||||||
|
spi_init();
|
||||||
|
|
||||||
|
// set up DMA
|
||||||
|
//memset(spi_tx_buf, 0, 0x10);
|
||||||
|
//spi_tx_dma(spi_tx_buf, 0x10);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// timer for fan PWM
|
||||||
|
TIM3->CCMR2 = TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3M_1;
|
||||||
|
TIM3->CCER = TIM_CCER_CC3E;
|
||||||
|
|
||||||
|
// max value of the timer
|
||||||
|
// 64 makes it above the audible range
|
||||||
|
//TIM3->ARR = 64;
|
||||||
|
|
||||||
|
// 10 prescale makes it below the audible range
|
||||||
|
timer_init(TIM3, 10);
|
||||||
|
puth(DBGMCU->IDCODE);
|
||||||
|
|
||||||
|
// set PWM
|
||||||
|
set_fan_speed(65535);
|
||||||
|
|
||||||
|
|
||||||
|
puts("**** INTERRUPTS ON ****\n");
|
||||||
|
__disable_irq();
|
||||||
|
|
||||||
|
// 4 uarts!
|
||||||
|
NVIC_EnableIRQ(USART1_IRQn);
|
||||||
|
NVIC_EnableIRQ(USART2_IRQn);
|
||||||
|
NVIC_EnableIRQ(USART3_IRQn);
|
||||||
|
NVIC_EnableIRQ(UART5_IRQn);
|
||||||
|
|
||||||
|
NVIC_EnableIRQ(OTG_FS_IRQn);
|
||||||
|
NVIC_EnableIRQ(ADC_IRQn);
|
||||||
|
// CAN has so many interrupts!
|
||||||
|
|
||||||
|
NVIC_EnableIRQ(CAN1_TX_IRQn);
|
||||||
|
NVIC_EnableIRQ(CAN1_RX0_IRQn);
|
||||||
|
NVIC_EnableIRQ(CAN1_SCE_IRQn);
|
||||||
|
|
||||||
|
NVIC_EnableIRQ(CAN2_TX_IRQn);
|
||||||
|
NVIC_EnableIRQ(CAN2_RX0_IRQn);
|
||||||
|
NVIC_EnableIRQ(CAN2_SCE_IRQn);
|
||||||
|
|
||||||
|
#ifdef CAN3
|
||||||
|
NVIC_EnableIRQ(CAN3_TX_IRQn);
|
||||||
|
NVIC_EnableIRQ(CAN3_RX0_IRQn);
|
||||||
|
NVIC_EnableIRQ(CAN3_SCE_IRQn);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ENABLE_SPI
|
||||||
|
NVIC_EnableIRQ(DMA2_Stream3_IRQn);
|
||||||
|
//NVIC_EnableIRQ(SPI1_IRQn);
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
#endif
|
||||||
|
__enable_irq();
|
||||||
|
|
||||||
|
// LED should keep on blinking all the time
|
||||||
|
uint64_t cnt;
|
||||||
|
for (cnt=0;;cnt++) {
|
||||||
|
can_live = pending_can_live;
|
||||||
|
|
||||||
|
// 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*/
|
||||||
|
|
||||||
|
/*puts("voltage: "); puth(adc_get(ADCCHAN_VOLTAGE)); puts(" ");
|
||||||
|
puts("current: "); puth(adc_get(ADCCHAN_CURRENT)); puts("\n");*/
|
||||||
|
|
||||||
|
// set LED to be controls allowed
|
||||||
|
set_led(LED_GREEN, controls_allowed);
|
||||||
|
|
||||||
|
// blink the red LED
|
||||||
|
set_led(LED_RED, 0);
|
||||||
|
delay(2000000);
|
||||||
|
set_led(LED_RED, 1);
|
||||||
|
delay(2000000);
|
||||||
|
|
||||||
|
// ESP io proxy
|
||||||
|
//set_led(LED_BLUE, !(GPIOB->IDR&1));
|
||||||
|
set_led(LED_BLUE, 0);
|
||||||
|
|
||||||
|
#ifdef ENABLE_SPI
|
||||||
|
if (spi_buf_count > 0) {
|
||||||
|
hexdump(spi_buf, spi_buf_count);
|
||||||
|
spi_buf_count = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// started logic
|
||||||
|
#ifdef PANDA
|
||||||
|
int started_signal = (GPIOB->IDR & (1 << 12)) == 0;
|
||||||
|
#else
|
||||||
|
int started_signal = (GPIOC->IDR & (1 << 13)) != 0;
|
||||||
|
#endif
|
||||||
|
if (started_signal) { started_signal_detected = 1; }
|
||||||
|
|
||||||
|
if (started_signal || (!started_signal_detected && can_live)) {
|
||||||
|
started = 1;
|
||||||
|
|
||||||
|
// turn on fan at half speed
|
||||||
|
set_fan_speed(32768);
|
||||||
|
} else {
|
||||||
|
started = 0;
|
||||||
|
|
||||||
|
// turn off fan
|
||||||
|
set_fan_speed(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we've been on for a bit and we didn't connect on USB, power up the ESP
|
||||||
|
// TODO: make better logic for this
|
||||||
|
/*if (cnt > 5 && !did_usb_enumerate) {
|
||||||
|
// enable the ESP, disable ESP boot mode
|
||||||
|
GPIOC->ODR = (1 << 14) | (1 << 5);
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
void spi_init() {
|
||||||
|
puts("SPI init\n");
|
||||||
|
SPI1->CR1 = SPI_CR1_SPE;
|
||||||
|
//SPI1->CR2 = SPI_CR2_RXNEIE | SPI_CR2_ERRIE | SPI_CR2_TXEIE;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 = addr;
|
||||||
|
DMA2_Stream3->NDTR = len;
|
||||||
|
DMA2_Stream3->PAR = &(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;
|
||||||
|
}
|
||||||
|
|
|
@ -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,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;
|
||||||
|
}
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,27 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
import usb1
|
||||||
|
import time
|
||||||
|
import traceback
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
context = usb1.USBContext()
|
||||||
|
|
||||||
|
handle = None
|
||||||
|
for device in context.getDeviceList(skip_on_error=True):
|
||||||
|
if device.getVendorID() == 0xbbaa and device.getProductID()&0xFF00 == 0xdd00:
|
||||||
|
print "found device"
|
||||||
|
handle = device.open()
|
||||||
|
handle.claimInterface(0)
|
||||||
|
break
|
||||||
|
|
||||||
|
if handle == None:
|
||||||
|
print "no device found"
|
||||||
|
exit(0)
|
||||||
|
|
||||||
|
try:
|
||||||
|
handle.controlWrite(usb1.TYPE_VENDOR | usb1.RECIPIENT_DEVICE, 0xd1, 0, 0, '')
|
||||||
|
except Exception:
|
||||||
|
traceback.print_exc()
|
||||||
|
print "expected error, exiting cleanly"
|
||||||
|
time.sleep(1)
|
||||||
|
|
|
@ -0,0 +1,132 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
import sys
|
||||||
|
from hexdump import hexdump
|
||||||
|
import time
|
||||||
|
import socket
|
||||||
|
import struct
|
||||||
|
|
||||||
|
def connect(uart, cntl):
|
||||||
|
uart.send("\x00\xff")
|
||||||
|
try:
|
||||||
|
while 1:
|
||||||
|
ret = uart.recv(8192)
|
||||||
|
if ret[0] != '\x79':
|
||||||
|
print "GOT IDLE CRAP!"
|
||||||
|
hexdump(ret)
|
||||||
|
if ret[-1] == "\x79":
|
||||||
|
print "already in bootloader"
|
||||||
|
return
|
||||||
|
except socket.timeout:
|
||||||
|
print "first try entering bootloader"
|
||||||
|
pass
|
||||||
|
while 1:
|
||||||
|
try:
|
||||||
|
# boot, reset, uart is low for a while
|
||||||
|
print "resetting"
|
||||||
|
cntl.send("br")
|
||||||
|
time.sleep(0.1)
|
||||||
|
|
||||||
|
print "entering bootloader"
|
||||||
|
uart.send("\x7f")
|
||||||
|
ret = uart.recv(8192)
|
||||||
|
hexdump(ret)
|
||||||
|
if ret[-1] == "\x79":
|
||||||
|
# phase 2, send get command
|
||||||
|
# if this works it looks like the interface is stable
|
||||||
|
time.sleep(0.1)
|
||||||
|
uart.send("\x00\xff")
|
||||||
|
ret = uart.recv(8192)
|
||||||
|
hexdump(ret)
|
||||||
|
if len(ret) == 0xf:
|
||||||
|
print "CONNECTED!"
|
||||||
|
break
|
||||||
|
|
||||||
|
# retrying, drain first
|
||||||
|
while 1:
|
||||||
|
print "extra:",
|
||||||
|
hexdump(uart.recv(8192))
|
||||||
|
except socket.timeout:
|
||||||
|
print "timeout"
|
||||||
|
pass
|
||||||
|
print "retrying in 100ms..."
|
||||||
|
time.sleep(0.1)
|
||||||
|
|
||||||
|
|
||||||
|
def cmd(x, odat, resp=False):
|
||||||
|
x.write(odat)
|
||||||
|
x.flush()
|
||||||
|
# recv until ACK
|
||||||
|
while 1:
|
||||||
|
d = x.read(1)
|
||||||
|
if d == '\x1f':
|
||||||
|
raise Exception("NACK")
|
||||||
|
elif d == '\x79':
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
print "WTF got "+d.encode("hex")
|
||||||
|
continue
|
||||||
|
if resp:
|
||||||
|
ll = ord(x.read(1))+1
|
||||||
|
print "reading %d bytes" % ll
|
||||||
|
dat = x.read(ll)
|
||||||
|
hexdump(dat)
|
||||||
|
ack2 = x.read(1)
|
||||||
|
assert ack2 == '\x79'
|
||||||
|
return dat
|
||||||
|
else:
|
||||||
|
return True
|
||||||
|
|
||||||
|
def cksum(x):
|
||||||
|
ret = 0
|
||||||
|
for c in x:
|
||||||
|
ret ^= ord(c)
|
||||||
|
return x + chr(ret)
|
||||||
|
|
||||||
|
def main():
|
||||||
|
cntl = socket.create_connection(("192.168.0.10", 3333))
|
||||||
|
uart = socket.create_connection(("192.168.0.10", 3334))
|
||||||
|
print cntl, uart
|
||||||
|
|
||||||
|
# connect in socket mode
|
||||||
|
uart.settimeout(0.2)
|
||||||
|
s = connect(uart, cntl)
|
||||||
|
|
||||||
|
# file mode from here on
|
||||||
|
uart.setblocking(True)
|
||||||
|
uart = uart.makefile()
|
||||||
|
|
||||||
|
cmd(uart, "\x00\xff", True)
|
||||||
|
cmd(uart, "\x02\xfd", True)
|
||||||
|
|
||||||
|
if len(sys.argv) == 1:
|
||||||
|
return
|
||||||
|
|
||||||
|
# flash file
|
||||||
|
dat = open(sys.argv[1]).read()
|
||||||
|
print "flashing 0x%X bytes" % len(dat)
|
||||||
|
#addr = 0x08000000
|
||||||
|
addr = 0x08004000
|
||||||
|
|
||||||
|
# erase sector 1
|
||||||
|
cmd(uart, "\x44\xbb")
|
||||||
|
print "sent erase"
|
||||||
|
#cmd(uart, cksum("\x00\x00\x00\x00"))
|
||||||
|
cmd(uart, cksum("\x00\x00\x00\x01"))
|
||||||
|
print "erase done"
|
||||||
|
|
||||||
|
# fits in sector 0
|
||||||
|
for a in range(0, len(dat), 0x100):
|
||||||
|
print "flashing 0x%x" % (addr+a)
|
||||||
|
cmd(uart, "\x31\xce")
|
||||||
|
cmd(uart, cksum(struct.pack("!I", addr+a)))
|
||||||
|
dd = dat[a:a+0x100]
|
||||||
|
cmd(uart, cksum(chr(len(dd)-1)+dd))
|
||||||
|
print "flashing done"
|
||||||
|
|
||||||
|
cntl.send("nr")
|
||||||
|
print "rebooted in normal mode"
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,631 @@
|
||||||
|
// **** 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
|
||||||
|
|
||||||
|
// interfaces
|
||||||
|
void usb_cb_enumeration_complete();
|
||||||
|
void usb_cb_control_msg();
|
||||||
|
void usb_cb_ep1_in(int len);
|
||||||
|
void usb_cb_ep2_out(uint8_t *usbdata, int len);
|
||||||
|
void usb_cb_ep3_out(uint8_t *usbdata, int len);
|
||||||
|
|
||||||
|
uint8_t device_desc[] = {
|
||||||
|
0x12,0x01,0x00,0x01,
|
||||||
|
0xFF,0xFF,0xFF,0x40,
|
||||||
|
(USB_VID>>0)&0xFF,(USB_VID>>8)&0xFF,
|
||||||
|
(USB_PID>>0)&0xFF,(USB_PID>>8)&0xFF,
|
||||||
|
#ifdef STM32F4
|
||||||
|
0x00,0x23,
|
||||||
|
#else
|
||||||
|
0x00,0x22,
|
||||||
|
#endif
|
||||||
|
0x01,0x02,
|
||||||
|
0x03,0x01};
|
||||||
|
|
||||||
|
uint8_t configuration_desc[] = {
|
||||||
|
0x09, 0x02, 0x27, 0x00,
|
||||||
|
0x01, 0x01, 0x00, 0xc0,
|
||||||
|
0x32,
|
||||||
|
// interface 0
|
||||||
|
0x09, 0x04, 0x00, 0x00,
|
||||||
|
0x03, 0xff, 0xFF, 0xFF,
|
||||||
|
0x00,
|
||||||
|
// endpoint 1, read CAN
|
||||||
|
0x07, 0x05, 0x81, 0x02, 0x40, 0x00, 0x00,
|
||||||
|
// endpoint 2, send serial
|
||||||
|
0x07, 0x05, 0x02, 0x02, 0x40, 0x00, 0x00,
|
||||||
|
// endpoint 3, send CAN
|
||||||
|
0x07, 0x05, 0x03, 0x02, 0x40, 0x00, 0x00,
|
||||||
|
};
|
||||||
|
|
||||||
|
uint8_t string_0_desc[] = {
|
||||||
|
0x04, 0x03, 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'
|
||||||
|
};
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
// current packet
|
||||||
|
USB_Setup_TypeDef setup;
|
||||||
|
uint8_t usbdata[0x100];
|
||||||
|
|
||||||
|
// 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
|
||||||
|
uint32_t count32b = 0, i = 0;
|
||||||
|
count32b = (len + 3) / 4;
|
||||||
|
|
||||||
|
// bullshit
|
||||||
|
USBx_INEP(ep)->DIEPTSIZ = (USB_OTG_DIEPTSIZ_PKTCNT & (1 << 19)) | (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 i;
|
||||||
|
uint8_t resp[0x80];
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
// TODO: is this the right place for this?
|
||||||
|
usb_cb_enumeration_complete();
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
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(string_0_desc, min(sizeof(string_0_desc), setup.b.wLength.w), 0);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
USB_WritePacket(string_1_desc, min(sizeof(string_1_desc), setup.b.wLength.w), 0);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
USB_WritePacket(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 (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(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;
|
||||||
|
default:
|
||||||
|
usb_cb_control_msg();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ***************************** 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (endpoint == 3) {
|
||||||
|
usb_cb_ep3_out(usbdata, len);
|
||||||
|
}
|
||||||
|
} 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// in endpoint hit
|
||||||
|
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
|
||||||
|
|
||||||
|
// this happens first
|
||||||
|
if (USBx_INEP(1)->DIEPINT & USB_OTG_DIEPINT_XFRC) {
|
||||||
|
#ifdef DEBUG_USB
|
||||||
|
puts(" IN PACKET SEND\n");
|
||||||
|
#endif
|
||||||
|
//USBx_DEVICE->DIEPEMPMSK = ~(1 << 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// *** 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_cb_ep1_in(0x40);
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear interrupts
|
||||||
|
USBx_INEP(0)->DIEPINT = USBx_INEP(0)->DIEPINT;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
proxy
|
||||||
|
*.bin
|
||||||
|
esp-open-sdk
|
||||||
|
a.out
|
|
@ -0,0 +1,49 @@
|
||||||
|
PATH := esp-open-sdk/xtensa-lx106-elf/bin:$(PATH)
|
||||||
|
CC = xtensa-lx106-elf-gcc
|
||||||
|
CFLAGS = -Iinclude/ -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 = xtensa-lx106-elf-objcopy
|
||||||
|
SDK_BASE = esp-open-sdk/ESP8266_NONOS_SDK_V1.5.4_16_05_20
|
||||||
|
|
||||||
|
flash: user1.bin
|
||||||
|
#./tools/esptool.py write_flash 0 $(SDK_BASE)/bin/boot_v1.5.bin 0x01000 user1.bin 0x81000 user2.bin 0x3FE000 $(SDK_BASE)/bin/blank.bin
|
||||||
|
./tools/esptool.py write_flash 0 $(SDK_BASE)/bin/boot_v1.5.bin 0x01000 user1.bin 0x3FE000 $(SDK_BASE)/bin/blank.bin
|
||||||
|
|
||||||
|
proxy-0x00000.bin: proxy
|
||||||
|
./tools/esptool.py elf2image $^
|
||||||
|
|
||||||
|
proxy: proxy.o tcp_ota.o
|
||||||
|
|
||||||
|
proxy.o: proxy.c
|
||||||
|
|
||||||
|
tcp_ota.o: tcp_ota.c
|
||||||
|
|
||||||
|
oldflash: proxy-0x00000.bin
|
||||||
|
./tools/esptool.py write_flash 0 proxy-0x00000.bin 0x40000 proxy-0x40000.bin
|
||||||
|
|
||||||
|
user1.bin: proxy.o tcp_ota.o st_ota.o elm327.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 $@
|
||||||
|
|
||||||
|
user2.bin: proxy.o tcp_ota.o st_ota.o elm327.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 $@
|
||||||
|
|
||||||
|
ota: user1.bin user2.bin
|
||||||
|
./tools/tcp_flash.py 192.168.0.10 user1.bin user2.bin
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f proxy proxy.o proxy-0x00000.bin proxy-0x40000.bin eagle.app.* user1.bin user2.bin a.out
|
|
@ -0,0 +1,34 @@
|
||||||
|
#include "ets_sys.h"
|
||||||
|
#include "osapi.h"
|
||||||
|
#include "gpio.h"
|
||||||
|
#include "os_type.h"
|
||||||
|
#include "user_interface.h"
|
||||||
|
#include "espconn.h"
|
||||||
|
|
||||||
|
#include "driver/uart.h"
|
||||||
|
|
||||||
|
#define ELM_PORT 35000
|
||||||
|
|
||||||
|
static struct espconn elm_conn;
|
||||||
|
static esp_tcp elm_proto;
|
||||||
|
|
||||||
|
static void ICACHE_FLASH_ATTR elm_rx_cb(void *arg, char *data, uint16_t len) {
|
||||||
|
uart0_tx_buffer(data, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ICACHE_FLASH_ATTR elm_tcp_connect_cb(void *arg) {
|
||||||
|
struct espconn *conn = (struct espconn *)arg;
|
||||||
|
espconn_set_opt(&elm_conn, ESPCONN_NODELAY);
|
||||||
|
espconn_regist_recvcb(conn, elm_rx_cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ICACHE_FLASH_ATTR elm327_init() {
|
||||||
|
// control listener
|
||||||
|
elm_proto.local_port = ELM_PORT;
|
||||||
|
elm_conn.type = ESPCONN_TCP;
|
||||||
|
elm_conn.state = ESPCONN_NONE;
|
||||||
|
elm_conn.proto.tcp = &elm_proto;
|
||||||
|
espconn_regist_connectcb(&elm_conn, elm_tcp_connect_cb);
|
||||||
|
espconn_accept(&elm_conn);
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
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,17 @@
|
||||||
|
/*
|
||||||
|
* tcp_ota.h: Over The Air (OTA) firmware upgrade via direct TCP/IP connection.
|
||||||
|
*
|
||||||
|
* Author: Ian Marshall
|
||||||
|
* Date: 28/05/2016
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef TCP_OTA_H
|
||||||
|
#define TCP_OTA_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialises the required connection information to listen for OTA messages.
|
||||||
|
* WiFi must first have been set up for this to succeed.
|
||||||
|
*/
|
||||||
|
void ICACHE_FLASH_ATTR ota_init();
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,182 @@
|
||||||
|
#include "ets_sys.h"
|
||||||
|
#include "osapi.h"
|
||||||
|
#include "gpio.h"
|
||||||
|
#include "os_type.h"
|
||||||
|
#include "user_interface.h"
|
||||||
|
#include "espconn.h"
|
||||||
|
|
||||||
|
#include "tcp_ota.h"
|
||||||
|
#include "driver/spi_interface.h"
|
||||||
|
|
||||||
|
static const int pin = 2;
|
||||||
|
static volatile os_timer_t some_timer;
|
||||||
|
|
||||||
|
// Structure holding the TCP connection information.
|
||||||
|
struct espconn tcp_conn;
|
||||||
|
// TCP specific protocol structure.
|
||||||
|
esp_tcp tcp_proto;
|
||||||
|
|
||||||
|
uint8_t buf[0x40*0x10];
|
||||||
|
|
||||||
|
void ICACHE_FLASH_ATTR some_timerfunc(void *arg)
|
||||||
|
{
|
||||||
|
// uart testing
|
||||||
|
/*uart0_sendStr("hello uart0\n");
|
||||||
|
uart1_sendStr_no_wait("hello uart1\n");*/
|
||||||
|
//uart0_sendStr("hello uart0\n");
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// *** SPI MODE ***
|
||||||
|
|
||||||
|
uint32_t value = 0xD3D4D5D6;
|
||||||
|
uint32_t sendData[8] = {0};
|
||||||
|
SpiData spiData;
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
int first = 1;
|
||||||
|
while (i < 0x40) {
|
||||||
|
spiData.cmd = 2;
|
||||||
|
spiData.cmdLen = 0;
|
||||||
|
spiData.addr = NULL;
|
||||||
|
spiData.addrLen = 0;
|
||||||
|
spiData.data = sendData;
|
||||||
|
spiData.dataLen = 16;
|
||||||
|
|
||||||
|
// manual CS pin
|
||||||
|
gpio_output_set(0, (1 << 5), 0, 0);
|
||||||
|
SPIMasterRecvData(SpiNum_HSPI, &spiData);
|
||||||
|
gpio_output_set((1 << 5), 0, 0, 0);
|
||||||
|
|
||||||
|
if (sendData[0] != 0) {
|
||||||
|
memcpy(buf + i*0x10, sendData, 0x10);
|
||||||
|
i++;
|
||||||
|
} else {
|
||||||
|
if (first == 0) break;
|
||||||
|
}
|
||||||
|
first = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i != 0) {
|
||||||
|
espconn_send(&tcp_conn, buf, i*0x10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int did_start_timer = 0;
|
||||||
|
|
||||||
|
void ICACHE_FLASH_ATTR tcp_connect_cb(void *arg) {
|
||||||
|
struct espconn *conn = (struct espconn *)arg;
|
||||||
|
espconn_set_opt(&tcp_conn, ESPCONN_NODELAY);
|
||||||
|
|
||||||
|
/*char message[] = "hello\r\n";
|
||||||
|
uint16_t len = strlen(message);
|
||||||
|
espconn_send (&tcp_conn, message, len);*/
|
||||||
|
|
||||||
|
if (!did_start_timer) {
|
||||||
|
// not atomic!
|
||||||
|
did_start_timer = 1;
|
||||||
|
// setup timer (100ms, repeating)
|
||||||
|
os_timer_setfn(&some_timer, (os_timer_func_t *)some_timerfunc, NULL);
|
||||||
|
os_timer_arm(&some_timer, 50, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ICACHE_FLASH_ATTR wifi_init() {
|
||||||
|
// start wifi AP
|
||||||
|
wifi_set_opmode(SOFTAP_MODE);
|
||||||
|
struct softap_config config;
|
||||||
|
wifi_softap_get_config(&config);
|
||||||
|
char ssid[32];
|
||||||
|
os_sprintf(ssid, "panda-%08x", system_get_chip_id());
|
||||||
|
char password[] = "testing123"; //password must be 8 characters or longer
|
||||||
|
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);
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
#define LOOP_PRIO 2
|
||||||
|
#define QUEUE_SIZE 1
|
||||||
|
static os_event_t my_queue[QUEUE_SIZE];
|
||||||
|
void loop();
|
||||||
|
|
||||||
|
void ICACHE_FLASH_ATTR elm327_init();
|
||||||
|
void ICACHE_FLASH_ATTR st_ota_init();
|
||||||
|
void ICACHE_FLASH_ATTR uart0_init(int flashing_mode);
|
||||||
|
|
||||||
|
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_0_5MHz;
|
||||||
|
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);
|
||||||
|
|
||||||
|
uart0_init(0);
|
||||||
|
os_printf("hello\n");
|
||||||
|
|
||||||
|
wifi_init();
|
||||||
|
|
||||||
|
// support ota upgrades
|
||||||
|
ota_init();
|
||||||
|
st_ota_init();
|
||||||
|
elm327_init();
|
||||||
|
|
||||||
|
// jump to OS
|
||||||
|
system_os_task(loop, LOOP_PRIO, my_queue, QUEUE_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ICACHE_FLASH_ATTR loop(os_event_t *events) {
|
||||||
|
system_os_post(LOOP_PRIO, 0, 0);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,172 @@
|
||||||
|
#include "ets_sys.h"
|
||||||
|
#include "osapi.h"
|
||||||
|
#include "gpio.h"
|
||||||
|
#include "os_type.h"
|
||||||
|
#include "user_interface.h"
|
||||||
|
#include "espconn.h"
|
||||||
|
|
||||||
|
#include "driver/gpio16.h"
|
||||||
|
#include "driver/uart.h"
|
||||||
|
|
||||||
|
#define ST_OTA_PORT 3333
|
||||||
|
#define ST_UART_PORT 3334
|
||||||
|
|
||||||
|
static struct espconn ota_conn;
|
||||||
|
static esp_tcp ota_proto;
|
||||||
|
|
||||||
|
static struct espconn uart_conn;
|
||||||
|
static esp_tcp uart_proto;
|
||||||
|
|
||||||
|
#define ST_RESET_PIN 16
|
||||||
|
|
||||||
|
static void ICACHE_FLASH_ATTR null_function(char c) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// for out of band access
|
||||||
|
static void ICACHE_FLASH_ATTR ota_rx_cb(void *arg, char *data, uint16_t len) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
if (data[i] == 'n') {
|
||||||
|
// no boot mode (pull high)
|
||||||
|
gpio_output_set((1 << 4), 0, (1 << 4), 0);
|
||||||
|
// init the uart for normal mode
|
||||||
|
uart0_init(0);
|
||||||
|
} else if (data[i] == 'b') {
|
||||||
|
// boot mode (pull low)
|
||||||
|
gpio_output_set(0, (1 << 4), (1 << 4), 0);
|
||||||
|
// init the uart for boot mode
|
||||||
|
uart0_init(1);
|
||||||
|
} else if (data[i] == 'r') {
|
||||||
|
// reset the ST
|
||||||
|
gpio16_output_conf();
|
||||||
|
gpio16_output_set(0);
|
||||||
|
os_delay_us(10000);
|
||||||
|
gpio16_output_set(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ICACHE_FLASH_ATTR ota_tcp_connect_cb(void *arg) {
|
||||||
|
struct espconn *conn = (struct espconn *)arg;
|
||||||
|
os_printf("ST OTA connection received from "IPSTR":%d\n",
|
||||||
|
IP2STR(conn->proto.tcp->remote_ip), conn->proto.tcp->remote_port);
|
||||||
|
|
||||||
|
espconn_regist_recvcb(conn, ota_rx_cb);
|
||||||
|
//espconn_regist_disconcb(conn, ota_disc_cb);
|
||||||
|
//espconn_regist_reconcb(conn, ota_recon_cb);
|
||||||
|
|
||||||
|
char message[] = "ST control v2\r\n";
|
||||||
|
espconn_send(&ota_conn, message, strlen(message));
|
||||||
|
}
|
||||||
|
|
||||||
|
// for UART access
|
||||||
|
static void ICACHE_FLASH_ATTR uart_rx_cb(void *arg, char *data, uint16_t len) {
|
||||||
|
// write data to UART
|
||||||
|
uart0_tx_buffer(data, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ICACHE_FLASH_ATTR uart_tcp_connect_cb(void *arg) {
|
||||||
|
// go
|
||||||
|
struct espconn *conn = (struct espconn *)arg;
|
||||||
|
espconn_regist_recvcb(conn, uart_rx_cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
// size is only a byte, so this is max
|
||||||
|
|
||||||
|
static void uart0_rx_intr_handler(void *para) {
|
||||||
|
uint8 rx_buf[0x100];
|
||||||
|
|
||||||
|
if (UART_RXFIFO_TOUT_INT_ST == (READ_PERI_REG(UART_INT_ST(0)) & UART_RXFIFO_TOUT_INT_ST)) {
|
||||||
|
uint8 fifo_len = (READ_PERI_REG(UART_STATUS(UART0))>>UART_RXFIFO_CNT_S)&UART_RXFIFO_CNT;
|
||||||
|
int i = 0;
|
||||||
|
for (i = 0; i < fifo_len; i++) {
|
||||||
|
uint8 d_tmp = READ_PERI_REG(UART_FIFO(UART0)) & 0xFF;
|
||||||
|
rx_buf[i] = d_tmp;
|
||||||
|
}
|
||||||
|
WRITE_PERI_REG(UART_INT_CLR(0), UART_RXFIFO_TOUT_INT_CLR);
|
||||||
|
|
||||||
|
// echo
|
||||||
|
//uart0_tx_buffer(rx_buf, fifo_len);
|
||||||
|
|
||||||
|
// send to network
|
||||||
|
espconn_send(&uart_conn, rx_buf, fifo_len);
|
||||||
|
} else {
|
||||||
|
// WTF
|
||||||
|
os_printf("WTF rx %X\n", READ_PERI_REG(UART_INT_ST(0)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ICACHE_FLASH_ATTR uart0_init(int flashing_mode) {
|
||||||
|
// copy uart_config from the driver
|
||||||
|
ETS_UART_INTR_ATTACH(uart0_rx_intr_handler, NULL);
|
||||||
|
|
||||||
|
// make TXD be TXD
|
||||||
|
PIN_PULLUP_DIS(PERIPHS_IO_MUX_U0TXD_U);
|
||||||
|
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD);
|
||||||
|
|
||||||
|
// set baud rate to 115200
|
||||||
|
uart_div_modify(0, UART_CLK_FREQ / 115200);
|
||||||
|
|
||||||
|
if (flashing_mode) {
|
||||||
|
// even parity for ST
|
||||||
|
WRITE_PERI_REG(UART_CONF0(0), ((STICK_PARITY_EN & UART_PARITY_EN_M) << UART_PARITY_EN_S)
|
||||||
|
| ((EVEN_BITS & UART_PARITY_M) <<UART_PARITY_S )
|
||||||
|
| ((ONE_STOP_BIT & UART_STOP_BIT_NUM) << UART_STOP_BIT_NUM_S)
|
||||||
|
| ((EIGHT_BITS & UART_BIT_NUM) << UART_BIT_NUM_S));
|
||||||
|
} else {
|
||||||
|
// no parity
|
||||||
|
WRITE_PERI_REG(UART_CONF0(0), ((STICK_PARITY_DIS & UART_PARITY_EN_M) << UART_PARITY_EN_S)
|
||||||
|
| ((NONE_BITS & UART_PARITY_M) <<UART_PARITY_S )
|
||||||
|
| ((ONE_STOP_BIT & UART_STOP_BIT_NUM) << UART_STOP_BIT_NUM_S)
|
||||||
|
| ((EIGHT_BITS & UART_BIT_NUM) << UART_BIT_NUM_S));
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear rx and tx fifo
|
||||||
|
SET_PERI_REG_MASK(UART_CONF0(0), UART_RXFIFO_RST | UART_TXFIFO_RST);
|
||||||
|
CLEAR_PERI_REG_MASK(UART_CONF0(0), UART_RXFIFO_RST | UART_TXFIFO_RST);
|
||||||
|
|
||||||
|
// set rx fifo trigger?
|
||||||
|
WRITE_PERI_REG(UART_CONF1(0), ((100 & UART_RXFIFO_FULL_THRHD) << UART_RXFIFO_FULL_THRHD_S) |
|
||||||
|
(0x02 & UART_RX_TOUT_THRHD) << UART_RX_TOUT_THRHD_S |
|
||||||
|
UART_RX_TOUT_EN |
|
||||||
|
((0x10 & UART_TXFIFO_EMPTY_THRHD)<<UART_TXFIFO_EMPTY_THRHD_S));
|
||||||
|
|
||||||
|
// clear all interrupt
|
||||||
|
WRITE_PERI_REG(UART_INT_CLR(0), 0xffff);
|
||||||
|
|
||||||
|
// enable rx_interrupt
|
||||||
|
SET_PERI_REG_MASK(UART_INT_ENA(0), UART_RXFIFO_TOUT_INT_ENA);
|
||||||
|
//SET_PERI_REG_MASK(UART_INT_ENA(0), UART_RXFIFO_TOUT_INT_ENA | UART_FRM_ERR_INT_ENA);
|
||||||
|
//SET_PERI_REG_MASK(UART_INT_ENA(0), UART_RXFIFO_FULL_INT_ENA | UART_RXFIFO_OVF_INT_ENA);
|
||||||
|
|
||||||
|
// actually enable the UART interrupt
|
||||||
|
ETS_UART_INTR_ENABLE();
|
||||||
|
|
||||||
|
if (flashing_mode) {
|
||||||
|
// disable other UART writers
|
||||||
|
// TODO: looks like this must be after UART init
|
||||||
|
os_install_putc1((void*)null_function);
|
||||||
|
} else {
|
||||||
|
UART_SetPrintPort(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ICACHE_FLASH_ATTR st_ota_init() {
|
||||||
|
|
||||||
|
// control listener
|
||||||
|
ota_proto.local_port = ST_OTA_PORT;
|
||||||
|
ota_conn.type = ESPCONN_TCP;
|
||||||
|
ota_conn.state = ESPCONN_NONE;
|
||||||
|
ota_conn.proto.tcp = &ota_proto;
|
||||||
|
espconn_regist_connectcb(&ota_conn, ota_tcp_connect_cb);
|
||||||
|
espconn_accept(&ota_conn);
|
||||||
|
|
||||||
|
// uart listener
|
||||||
|
uart_proto.local_port = ST_UART_PORT;
|
||||||
|
uart_conn.type = ESPCONN_TCP;
|
||||||
|
uart_conn.state = ESPCONN_NONE;
|
||||||
|
uart_conn.proto.tcp = &uart_proto;
|
||||||
|
espconn_regist_connectcb(&uart_conn, uart_tcp_connect_cb);
|
||||||
|
espconn_accept(&uart_conn);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,437 @@
|
||||||
|
/*
|
||||||
|
* tcp_ota.c: Over The Air (OTA) firmware upgrade via direct TCP/IP connection.
|
||||||
|
*
|
||||||
|
* NOTE that this does not perform any security checks, so don't rely on this for production use!
|
||||||
|
*
|
||||||
|
* Author: Ian Marshall
|
||||||
|
* Date: 28/05/2016
|
||||||
|
*/
|
||||||
|
#include "ets_sys.h"
|
||||||
|
#include "osapi.h"
|
||||||
|
#include "gpio.h"
|
||||||
|
#include "os_type.h"
|
||||||
|
#include "ip_addr.h"
|
||||||
|
#include "espconn.h"
|
||||||
|
#include "mem.h"
|
||||||
|
#include "spi_flash.h"
|
||||||
|
#include "user_interface.h"
|
||||||
|
#include "upgrade.h"
|
||||||
|
#include "driver/uart.h"
|
||||||
|
#include "espmissingincludes.h"
|
||||||
|
#include "tcp_ota.h"
|
||||||
|
|
||||||
|
#define FIRMWARE_SIZE 503808
|
||||||
|
|
||||||
|
// The TCP port used to listen to for connections.
|
||||||
|
#define OTA_PORT 65056
|
||||||
|
|
||||||
|
// The number of bytes to use for the OTA message buffer (NOT the firmware buffer).
|
||||||
|
#define OTA_BUFFER_LEN 32
|
||||||
|
|
||||||
|
// Structure holding the TCP connection information for the OTA connection.
|
||||||
|
LOCAL struct espconn ota_conn;
|
||||||
|
|
||||||
|
// TCP specific protocol structure for the OTA connection.
|
||||||
|
LOCAL esp_tcp ota_proto;
|
||||||
|
|
||||||
|
// Timer used for rebooting the ESP8266 after an OTA upgrade is complete.
|
||||||
|
LOCAL os_timer_t ota_reboot_timer;
|
||||||
|
|
||||||
|
// Buffer used to hold the new firmware until we have received it all. This is not statically allocated, to avoid
|
||||||
|
// constantly blocking out the memory used, even when no OTA upgrade is in progress.
|
||||||
|
LOCAL uint8_t *ota_firmware = NULL;
|
||||||
|
|
||||||
|
// The total number of bytes expected for the firmware image that is to be flashed.
|
||||||
|
LOCAL uint32_t ota_firmware_size = 0;
|
||||||
|
|
||||||
|
// The total number of bytes received for the firmware image that is to be flashed.
|
||||||
|
LOCAL uint32_t ota_firmware_received = 0;
|
||||||
|
|
||||||
|
// The number of bytes that have currently been received into the "ota_firmware" buffer, which is reset every 4KB.
|
||||||
|
LOCAL uint32_t ota_firmware_len = 0;
|
||||||
|
|
||||||
|
// Buffer used for receiving header information via TCP, allowing the header information to be split over multiple
|
||||||
|
// packets.
|
||||||
|
LOCAL uint8_t ota_buffer[OTA_BUFFER_LEN];
|
||||||
|
|
||||||
|
// The number of bytes currently used in the OTA buffer.
|
||||||
|
LOCAL uint8_t ota_buffer_len = 0;
|
||||||
|
|
||||||
|
// Type used to define the possible status values of OTA upgrades.
|
||||||
|
typedef enum {
|
||||||
|
NOT_STARTED,
|
||||||
|
CONNECTION_ESTABLISHED,
|
||||||
|
RECEIVING_HEADER,
|
||||||
|
RECEIVING_FIRMWARE,
|
||||||
|
REBOOTING,
|
||||||
|
ERROR
|
||||||
|
} ota_state_t;
|
||||||
|
|
||||||
|
// The current status of the OTA flashing. This is required as multiple transmissions will be required to send through
|
||||||
|
// the firmware data.
|
||||||
|
LOCAL ota_state_t ota_state = NOT_STARTED;
|
||||||
|
|
||||||
|
// The IP address of the host sending the OTA data to us. Needed to avoid corruption if two hosts try to OTA upgrade at
|
||||||
|
// the same time.
|
||||||
|
LOCAL uint32_t ota_ip = 0;
|
||||||
|
|
||||||
|
// The TCP port of the host sending the OTA data to us.
|
||||||
|
LOCAL uint16_t ota_port = 0;
|
||||||
|
|
||||||
|
// Forward definitions.
|
||||||
|
LOCAL uint8_t ICACHE_FLASH_ATTR parse_header_line();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handles the receiving of information for the OTA update process.
|
||||||
|
*/
|
||||||
|
LOCAL void ICACHE_FLASH_ATTR ota_rx_cb(void *arg, char *data, uint16_t len) {
|
||||||
|
// Store the IP address from the sender of this data.
|
||||||
|
struct espconn *conn = (struct espconn *)arg;
|
||||||
|
uint8_t *addr_array = NULL;
|
||||||
|
addr_array = conn->proto.tcp->remote_ip;
|
||||||
|
ip_addr_t addr;
|
||||||
|
IP4_ADDR(&addr, conn->proto.tcp->remote_ip[0], conn->proto.tcp->remote_ip[1], conn->proto.tcp->remote_ip[2],
|
||||||
|
conn->proto.tcp->remote_ip[3]);
|
||||||
|
if (ota_ip == 0) {
|
||||||
|
// There is no previously stored IP address, so we have it.
|
||||||
|
ota_ip = addr.addr;
|
||||||
|
ota_port = conn->proto.tcp->remote_port;
|
||||||
|
ota_state = CONNECTION_ESTABLISHED;
|
||||||
|
} else if ((ota_ip != addr.addr) || (ota_port != conn->proto.tcp->remote_port)) {
|
||||||
|
// This connection is not the one curently sending OTA data.
|
||||||
|
espconn_send(conn, "ERR: Connection Already Exists\r\n", 32);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//os_printf("Rx packet - %d bytes, state=%d, size=%d, received=%d, len=%d.\r\n",
|
||||||
|
// len, ota_state, ota_firmware_size, ota_firmware_received, ota_firmware_len);
|
||||||
|
// OTA message sequence:
|
||||||
|
// Rx: "OTA\r\n"
|
||||||
|
// Rx: "GetNextFlash\r\n"
|
||||||
|
// Tx: "user1.bin\r\n" or "user2.bin\r\n", depending on which binary is the next one to be flashed.
|
||||||
|
// Rx: "FirmwareLength: <len>\r\n", where "<len>" is the number of bytes (in ASCII) to be sent in the firmware.
|
||||||
|
// Tx: "Ready\r\n"
|
||||||
|
// Rx: <Firmware>, for "<len>" bytes.
|
||||||
|
// Tx: "Flashing\r\n" or "Invalid\r\n".
|
||||||
|
// Tx: "Rebooting\r\n"
|
||||||
|
uint16_t unbuffered_start = 0;
|
||||||
|
if ((ota_state == CONNECTION_ESTABLISHED) || (ota_state == RECEIVING_HEADER)) {
|
||||||
|
// Store the received bytes into the buffer.
|
||||||
|
for (uint16_t ii = 0; ii < len; ii++) {
|
||||||
|
if (ota_buffer_len < (OTA_BUFFER_LEN - 1)) {
|
||||||
|
ota_buffer[ota_buffer_len++] = data[ii];
|
||||||
|
} else {
|
||||||
|
// The buffer has overflowed, remember where we left off.
|
||||||
|
unbuffered_start = ii;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (ota_state == RECEIVING_FIRMWARE) {
|
||||||
|
// Store received bytes in the firmware buffer.
|
||||||
|
uint32_t copy_len = (uint32_t)len;
|
||||||
|
if ((copy_len + ota_firmware_len) > SPI_FLASH_SEC_SIZE) {
|
||||||
|
copy_len = SPI_FLASH_SEC_SIZE - ota_firmware_len;
|
||||||
|
}
|
||||||
|
if ((copy_len + ota_firmware_received) > ota_firmware_size) {
|
||||||
|
copy_len = ota_firmware_size - ota_firmware_len;
|
||||||
|
}
|
||||||
|
os_memmove(&ota_firmware[ota_firmware_len], data, copy_len);
|
||||||
|
ota_firmware_len += copy_len;
|
||||||
|
ota_firmware_received += copy_len;
|
||||||
|
if (copy_len < len) {
|
||||||
|
unbuffered_start = copy_len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool repeat = true;
|
||||||
|
while (repeat) {
|
||||||
|
uint8_t eol = 0;
|
||||||
|
switch (ota_state) {
|
||||||
|
case CONNECTION_ESTABLISHED: {
|
||||||
|
// A connection has just been established. We expect an initial line of "OTA".
|
||||||
|
eol = parse_header_line();
|
||||||
|
if (eol > 0) {
|
||||||
|
// We have a line, it should be "OTA".
|
||||||
|
if (strncmp("OTA", ota_buffer, eol - 2)) {
|
||||||
|
// Oh dear, it's not.
|
||||||
|
espconn_send(conn, "ERR: Invalid protocol\r\n", 23);
|
||||||
|
ota_state = ERROR;
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
// We do, move to the next line in the header.
|
||||||
|
ota_state = RECEIVING_HEADER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case RECEIVING_HEADER: {
|
||||||
|
// We are now receiving header lines.
|
||||||
|
eol = parse_header_line();
|
||||||
|
if (eol > 0) {
|
||||||
|
// We have a line, see what it is.
|
||||||
|
if (!strncmp("GetNextFlash", ota_buffer, eol - 2)) {
|
||||||
|
// The remote device has requested to know what the next flash unit is.
|
||||||
|
uint8_t unit = system_upgrade_userbin_check(); // Note, returns the current unit!
|
||||||
|
if (unit == UPGRADE_FW_BIN1) {
|
||||||
|
espconn_send(conn, "user2.bin\r\n", 11);
|
||||||
|
} else {
|
||||||
|
espconn_send(conn, "user1.bin\r\n", 11);
|
||||||
|
}
|
||||||
|
} else if ((eol > 17) && (!strncmp("FirmwareLength:", ota_buffer, 15))) {
|
||||||
|
// The remote system is preparing to send the firmware. The expected length is supplied here.
|
||||||
|
uint32_t size = 0;
|
||||||
|
for (uint8_t ii = 16; ii < ota_buffer_len; ii++) {
|
||||||
|
if ((ota_buffer[ii] >= '0') && (ota_buffer[ii] <= '9')) {
|
||||||
|
size *= 10;
|
||||||
|
size += ota_buffer[ii] - '0';
|
||||||
|
} else if ((ota_buffer[ii] == '\r') || (ota_buffer[ii] == '\n')) {
|
||||||
|
// We have finished the firmware size.
|
||||||
|
break;
|
||||||
|
} else if ((ota_buffer[ii] != ' ') && (ota_buffer[ii] != ',')) {
|
||||||
|
// Anything that's not a number, space or new-line is invalid.
|
||||||
|
size = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size == 0) {
|
||||||
|
// We either didn't get a length, or the length is invalid.
|
||||||
|
espconn_send(conn, "ERR: Invalid firmware length\r\n", 30);
|
||||||
|
ota_state = ERROR;
|
||||||
|
return;
|
||||||
|
} else if (size > FIRMWARE_SIZE) {
|
||||||
|
// The size of the incoming firmware image is too big to fit.
|
||||||
|
espconn_send(conn, "ERR: Firmware length is too big\r\n", 33);
|
||||||
|
ota_state = ERROR;
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
// Ready to begin flashing!
|
||||||
|
ota_firmware = (uint8_t *)os_malloc(SPI_FLASH_SEC_SIZE);
|
||||||
|
if (ota_firmware == NULL) {
|
||||||
|
espconn_send(conn, "ERR: Unable to allocate OTA buffer.\r\n", 37);
|
||||||
|
ota_state = ERROR;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ota_firmware_size = size;
|
||||||
|
ota_firmware_received = 0;
|
||||||
|
ota_firmware_len = 0;
|
||||||
|
ota_state = RECEIVING_FIRMWARE;
|
||||||
|
|
||||||
|
// Copy any remaining bytes from the OTA buffer to the firmware buffer.
|
||||||
|
uint8_t remaining = ota_buffer_len - eol - 1;
|
||||||
|
if (remaining > 0) {
|
||||||
|
os_memmove(ota_firmware, &ota_buffer[eol + 1], remaining);
|
||||||
|
ota_firmware_received = ota_firmware_len = (uint32_t)remaining;
|
||||||
|
}
|
||||||
|
|
||||||
|
espconn_send(conn, "Ready\r\n", 7);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// We received an unexpected header line, abort.
|
||||||
|
espconn_send(conn, "ERR: Unexpected header.\r\n", 25);
|
||||||
|
ota_state = ERROR;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case RECEIVING_FIRMWARE: {
|
||||||
|
// We are now receiving the firmware image.
|
||||||
|
if ((ota_firmware_len == SPI_FLASH_SEC_SIZE) || (ota_firmware_received == ota_firmware_size)) {
|
||||||
|
// We have received a sector's worth of data, or the remainder of the flash image, flash it.
|
||||||
|
if (ota_firmware_received <= SPI_FLASH_SEC_SIZE) {
|
||||||
|
// This is the first block, check the header.
|
||||||
|
if (ota_firmware[0] != 0xEA) {
|
||||||
|
espconn_send(conn, "ERR: IROM magic missing.\r\n", 26);
|
||||||
|
ota_state = ERROR;
|
||||||
|
return;
|
||||||
|
} else if ((ota_firmware[1] != 0x04) || (ota_firmware[2] > 0x03) ||
|
||||||
|
((ota_firmware[3] >> 4) > 0x06)) {
|
||||||
|
espconn_send(conn, "ERR: Flash header invalid.\r\n", 28);
|
||||||
|
ota_state = ERROR;
|
||||||
|
return;
|
||||||
|
} else if (((uint16_t *)ota_firmware)[3] != 0x4010) {
|
||||||
|
espconn_send(conn, "ERR: Invalid entry address.\r\n", 29);
|
||||||
|
ota_state = ERROR;
|
||||||
|
return;
|
||||||
|
} else if (((uint32_t *)ota_firmware)[2] != 0x00000000) {
|
||||||
|
espconn_send(conn, "ERR: Invalid start offset.\r\n", 28);
|
||||||
|
ota_state = ERROR;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Zero out any remaining bytes in the last block, to avoid writing dirty data.
|
||||||
|
if (ota_firmware_len < SPI_FLASH_SEC_SIZE) {
|
||||||
|
os_memset(&ota_firmware[ota_firmware_len], 0, SPI_FLASH_SEC_SIZE - ota_firmware_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find out the starting address for the flash write.
|
||||||
|
int address;
|
||||||
|
uint8_t current = system_upgrade_userbin_check();
|
||||||
|
if (current == UPGRADE_FW_BIN1) {
|
||||||
|
// The next flash, user2.bin, will start after 4KB boot, user1, 16KB user params, 4KB reserved.
|
||||||
|
address = 4*1024 + FIRMWARE_SIZE + 16*1024 + 4*1024;
|
||||||
|
} else {
|
||||||
|
// The next flash, user1.bin, will start after 4KB boot.
|
||||||
|
address = 4*1024;
|
||||||
|
}
|
||||||
|
address += ota_firmware_received - ota_firmware_len;
|
||||||
|
|
||||||
|
|
||||||
|
// Erase the flash block.
|
||||||
|
if ((address % SPI_FLASH_SEC_SIZE) == 0) {
|
||||||
|
spi_flash_erase_sector(address / SPI_FLASH_SEC_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write the new flash block.
|
||||||
|
//os_printf("Flashing address %05x, total received = %d.\n", address, ota_firmware_received);
|
||||||
|
SpiFlashOpResult res = spi_flash_write(address, (uint32_t *)ota_firmware, SPI_FLASH_SEC_SIZE);
|
||||||
|
ota_firmware_len = 0;
|
||||||
|
if (res != SPI_FLASH_RESULT_OK) {
|
||||||
|
espconn_send(conn, "ERR: Flash failed.\r\n", 20);
|
||||||
|
ota_state = ERROR;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ota_firmware_received == ota_firmware_size) {
|
||||||
|
// We've flashed all of the firmware now, reboot into the new firmware.
|
||||||
|
os_printf("Preparing to update firmware.\n");
|
||||||
|
espconn_send(conn, "Flash upgrade success. Rebooting in 2s.\r\n", 41);
|
||||||
|
os_free(ota_firmware);
|
||||||
|
ota_firmware_size = 0;
|
||||||
|
ota_firmware_received = 0;
|
||||||
|
ota_firmware_len = 0;
|
||||||
|
ota_state = REBOOTING;
|
||||||
|
system_upgrade_flag_set(UPGRADE_FLAG_FINISH);
|
||||||
|
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, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear out the processed bytes from the buffer, if any.
|
||||||
|
repeat = false;
|
||||||
|
if ((ota_state == CONNECTION_ESTABLISHED) || (ota_state == RECEIVING_HEADER)) {
|
||||||
|
// In these states, we're still going to be using the buffer.
|
||||||
|
if (eol < (ota_buffer_len - 1)) {
|
||||||
|
// There are still more characters in the buffer yet to process, move them to the start of the buffer.
|
||||||
|
os_memmove(&ota_buffer[0], &ota_buffer[eol + 1], ota_buffer_len - eol - 1);
|
||||||
|
ota_buffer_len = ota_buffer_len - eol - 1;
|
||||||
|
repeat = true;
|
||||||
|
} else {
|
||||||
|
ota_buffer_len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unbuffered_start > 0) {
|
||||||
|
// Store unbuffered bytes to the end of the buffer.
|
||||||
|
for (uint16_t ii = unbuffered_start; ii < len; ii++) {
|
||||||
|
if (ota_buffer_len < (OTA_BUFFER_LEN - 1)) {
|
||||||
|
ota_buffer[ota_buffer_len++] = data[ii];
|
||||||
|
unbuffered_start = 0;
|
||||||
|
repeat = true;
|
||||||
|
} else {
|
||||||
|
// The buffer has overflowed again, remember where we left off.
|
||||||
|
unbuffered_start = ii;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (ota_state == RECEIVING_FIRMWARE) {
|
||||||
|
if (unbuffered_start > 0) {
|
||||||
|
// Store unbuffered bytes in the firmware buffer.
|
||||||
|
uint32_t copy_len = (uint32_t)(len - unbuffered_start);
|
||||||
|
if ((copy_len + ota_firmware_len) > SPI_FLASH_SEC_SIZE) {
|
||||||
|
copy_len = SPI_FLASH_SEC_SIZE - ota_firmware_len;
|
||||||
|
}
|
||||||
|
if ((copy_len + ota_firmware_received) > ota_firmware_size) {
|
||||||
|
copy_len = ota_firmware_size - ota_firmware_len;
|
||||||
|
}
|
||||||
|
os_memmove(&ota_firmware[ota_firmware_len], &data[unbuffered_start], copy_len);
|
||||||
|
ota_firmware_len += copy_len;
|
||||||
|
ota_firmware_received += copy_len;
|
||||||
|
if (copy_len < (len - unbuffered_start)) {
|
||||||
|
unbuffered_start += copy_len;
|
||||||
|
} else {
|
||||||
|
unbuffered_start = 0;
|
||||||
|
}
|
||||||
|
repeat = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the number of bytes in the message buffer for a single header line, or zero if no header is found.
|
||||||
|
LOCAL uint8_t ICACHE_FLASH_ATTR parse_header_line() {
|
||||||
|
for (uint8_t ii = 0; ii < ota_buffer_len - 1; ii++) {
|
||||||
|
if ((ota_buffer[ii] == '\r') && (ota_buffer[ii + 1] == '\n')) {
|
||||||
|
// We have found the end of line markers.
|
||||||
|
return ii + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we get here, we didn't find the end of line markers.
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Call-back for when a TCP connection has been disconnected.
|
||||||
|
*/
|
||||||
|
LOCAL void ICACHE_FLASH_ATTR ota_disc_cb(void *arg) {
|
||||||
|
// Reset the connection information, if we haven't progressed far enough.
|
||||||
|
if ((ota_state != NOT_STARTED) && (ota_state != REBOOTING)) {
|
||||||
|
ota_ip = 0;
|
||||||
|
ota_port = 0;
|
||||||
|
ota_state = NOT_STARTED;
|
||||||
|
|
||||||
|
ota_buffer_len = 0;
|
||||||
|
if (ota_firmware != NULL) {
|
||||||
|
os_free(ota_firmware);
|
||||||
|
ota_firmware = NULL;
|
||||||
|
ota_firmware_size = 0;
|
||||||
|
ota_firmware_len = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Call-back for when a TCP connection has failed - reconnected is a misleading name, sadly.
|
||||||
|
*/
|
||||||
|
LOCAL void ICACHE_FLASH_ATTR ota_recon_cb(void *arg, int8_t err) {
|
||||||
|
// Use the disconnect call-back to process this event.
|
||||||
|
ota_disc_cb(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Call-back for when an incoming TCP connection has been established.
|
||||||
|
*/
|
||||||
|
LOCAL void ICACHE_FLASH_ATTR ota_tcp_connect_cb(void *arg) {
|
||||||
|
struct espconn *conn = (struct espconn *)arg;
|
||||||
|
os_printf("TCP OTA connection received from "IPSTR":%d\n",
|
||||||
|
IP2STR(conn->proto.tcp->remote_ip), conn->proto.tcp->remote_port);
|
||||||
|
|
||||||
|
// See if this connection is allowed.
|
||||||
|
if (ota_ip == 0) {
|
||||||
|
// Now that we have a connection, register some call-backs.
|
||||||
|
espconn_regist_recvcb(conn, ota_rx_cb);
|
||||||
|
espconn_regist_disconcb(conn, ota_disc_cb);
|
||||||
|
espconn_regist_reconcb(conn, ota_recon_cb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialises the required connection information to listen for OTA messages.
|
||||||
|
* WiFi must first have been set up for this to succeed.
|
||||||
|
*/
|
||||||
|
void ICACHE_FLASH_ATTR ota_init() {
|
||||||
|
ota_proto.local_port = OTA_PORT;
|
||||||
|
ota_conn.type = ESPCONN_TCP;
|
||||||
|
ota_conn.state = ESPCONN_NONE;
|
||||||
|
ota_conn.proto.tcp = &ota_proto;
|
||||||
|
espconn_regist_connectcb(&ota_conn, ota_tcp_connect_cb);
|
||||||
|
espconn_accept(&ota_conn);
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,85 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
#
|
||||||
|
# tcp_flash.py - flashes an ESP8266 microcontroller via 'raw' TCP/IP (not HTTP).
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# tcp_flash.py <host|IP> <user1.bin> <user2.bin>
|
||||||
|
#
|
||||||
|
# Where:
|
||||||
|
# <host|IP> the hostname or IP address of the ESP8266 to be flashed.
|
||||||
|
# <user1.bin> the file holding the first flash format file. Used when the currently used flash is user2.bin
|
||||||
|
# <user2.bin> the file holding the second flash format file. Used when the currently used flash is user1.bin
|
||||||
|
#
|
||||||
|
# Author: Ian Marshall
|
||||||
|
# Date: 27/05/2016
|
||||||
|
#
|
||||||
|
|
||||||
|
import socket
|
||||||
|
import sys
|
||||||
|
|
||||||
|
PORT=65056
|
||||||
|
|
||||||
|
# Verify the parameters.
|
||||||
|
if len(sys.argv) < 3:
|
||||||
|
print 'Usage: '
|
||||||
|
print ' Usage:'
|
||||||
|
print ' tcp_flash.py <host|IP> <user1.bin> <user2.bin>'
|
||||||
|
print ''
|
||||||
|
print ' Where:'
|
||||||
|
print ' <host|IP> the hostname or IP address of the ESP8266 to be flashed.'
|
||||||
|
print ' <user1.bin> the file holding the first flash format file.'
|
||||||
|
print ' Used when the currently used flash is user2.bin'
|
||||||
|
print ' <user2.bin> the file holding the second flash format file.'
|
||||||
|
print ' Used when the currently used flash is user1.bin'
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# Copy the parameters to more descriptive variables.
|
||||||
|
host = sys.argv[1]
|
||||||
|
user1bin = sys.argv[2]
|
||||||
|
user2bin = sys.argv[3]
|
||||||
|
print 'Flashing to "{}"'.format(host)
|
||||||
|
|
||||||
|
# Open the connection to the ESP8266.
|
||||||
|
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
s.settimeout(5);
|
||||||
|
s.connect((host, PORT))
|
||||||
|
|
||||||
|
# Send a request for the correct user bin to be flashed.
|
||||||
|
s.send('OTA\r\nGetNextFlash\r\n')
|
||||||
|
|
||||||
|
# Wait for the reply.
|
||||||
|
f = None
|
||||||
|
response = s.recv(128)
|
||||||
|
if response == "user1.bin\r\n":
|
||||||
|
print 'Flashing \"{}\"...'.format(user1bin)
|
||||||
|
f = open(user1bin, "rb")
|
||||||
|
elif response == "user2.bin\r\n":
|
||||||
|
print 'Flashing \"{}\"...'.format(user2bin)
|
||||||
|
f = open(user2bin, "rb")
|
||||||
|
else:
|
||||||
|
print 'Unknown binary version requested by ESP8266: "{}"'.format(response)
|
||||||
|
sys.exit(2)
|
||||||
|
|
||||||
|
# Read the firmware file.
|
||||||
|
contents = f.read()
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
# Send through the firmware length
|
||||||
|
s.send('FirmwareLength: {}\r\n'.format(len(contents)))
|
||||||
|
|
||||||
|
# Wait until we get the go-ahead.
|
||||||
|
response = s.recv(128)
|
||||||
|
if response != "Ready\r\n":
|
||||||
|
print 'Received response: {}'.format(response)
|
||||||
|
sys.exit(3)
|
||||||
|
|
||||||
|
# Send the firmware.
|
||||||
|
print 'Sending {} bytes of firmware'.format(len(contents))
|
||||||
|
s.sendall(contents)
|
||||||
|
response = s.recv(128)
|
||||||
|
if len(response) > 0:
|
||||||
|
print 'Received response: {}'.format(response)
|
||||||
|
|
||||||
|
# Close the connection, as we're now done.
|
||||||
|
s.close()
|
||||||
|
sys.exit(0)
|
|
@ -0,0 +1,139 @@
|
||||||
|
# python library to interface with panda
|
||||||
|
import struct
|
||||||
|
|
||||||
|
import usb1
|
||||||
|
from usb1 import USBErrorIO, USBErrorOverflow
|
||||||
|
|
||||||
|
class Panda(object):
|
||||||
|
def __init__(self, serial=None, claim=True):
|
||||||
|
context = usb1.USBContext()
|
||||||
|
|
||||||
|
self.handle = None
|
||||||
|
for device in context.getDeviceList(skip_on_error=True):
|
||||||
|
if device.getVendorID() == 0xbbaa and device.getProductID() == 0xddcc:
|
||||||
|
if serial is None or device.getSerialNumber() == serial:
|
||||||
|
print "opening device", device.getSerialNumber()
|
||||||
|
self.handle = device.open()
|
||||||
|
if claim:
|
||||||
|
self.handle.claimInterface(0)
|
||||||
|
break
|
||||||
|
|
||||||
|
assert self.handle != None
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def list():
|
||||||
|
context = usb1.USBContext()
|
||||||
|
ret = []
|
||||||
|
for device in context.getDeviceList(skip_on_error=True):
|
||||||
|
if device.getVendorID() == 0xbbaa and device.getProductID() == 0xddcc:
|
||||||
|
ret.append(device.getSerialNumber())
|
||||||
|
return ret
|
||||||
|
|
||||||
|
# ******************* health *******************
|
||||||
|
|
||||||
|
def health(self):
|
||||||
|
dat = self.handle.controlRead(usb1.TYPE_VENDOR | usb1.RECIPIENT_DEVICE, 0xd2, 0, 0, 0x20)
|
||||||
|
a = struct.unpack("IIBBBBB", dat)
|
||||||
|
return {"voltage": a[0], "current": a[1],
|
||||||
|
"started": a[2], "controls_allowed": a[3],
|
||||||
|
"gas_interceptor_detected": a[4],
|
||||||
|
"started_signal_detected": a[5],
|
||||||
|
"started_alt": a[6]}
|
||||||
|
|
||||||
|
# ******************* can *******************
|
||||||
|
|
||||||
|
def set_gmlan(self, on):
|
||||||
|
if on:
|
||||||
|
self.handle.controlWrite(usb1.TYPE_VENDOR | usb1.RECIPIENT_DEVICE, 0xdb, 1, 0, '')
|
||||||
|
else:
|
||||||
|
self.handle.controlWrite(usb1.TYPE_VENDOR | usb1.RECIPIENT_DEVICE, 0xdb, 0, 0, '')
|
||||||
|
|
||||||
|
def can_send_many(self, arr):
|
||||||
|
snds = []
|
||||||
|
for addr, _, dat, bus in arr:
|
||||||
|
snd = struct.pack("II", ((addr << 21) | 1), len(dat) | (bus << 4)) + dat
|
||||||
|
snd = snd.ljust(0x10, '\x00')
|
||||||
|
snds.append(snd)
|
||||||
|
|
||||||
|
while 1:
|
||||||
|
try:
|
||||||
|
self.handle.bulkWrite(3, ''.join(snds))
|
||||||
|
break
|
||||||
|
except (USBErrorIO, USBErrorOverflow):
|
||||||
|
print "CAN: BAD SEND MANY, RETRYING"
|
||||||
|
|
||||||
|
def can_send(self, addr, dat, bus):
|
||||||
|
self.can_send_many([[addr, None, dat, bus]])
|
||||||
|
|
||||||
|
def can_recv(self):
|
||||||
|
def __parse_can_buffer(dat):
|
||||||
|
ret = []
|
||||||
|
for j in range(0, len(dat), 0x10):
|
||||||
|
ddat = dat[j:j+0x10]
|
||||||
|
f1, f2 = struct.unpack("II", ddat[0:8])
|
||||||
|
ret.append((f1 >> 21, f2>>16, ddat[8:8+(f2&0xF)], (f2>>4)&0xf))
|
||||||
|
return ret
|
||||||
|
dat = ""
|
||||||
|
while 1:
|
||||||
|
try:
|
||||||
|
dat = self.handle.bulkRead(1, 0x10*256)
|
||||||
|
break
|
||||||
|
except (USBErrorIO, USBErrorOverflow):
|
||||||
|
print "CAN: BAD RECV, RETRYING"
|
||||||
|
return __parse_can_buffer(dat)
|
||||||
|
|
||||||
|
# ******************* serial *******************
|
||||||
|
|
||||||
|
def serial_read(self, port_number):
|
||||||
|
return self.handle.controlRead(usb1.TYPE_VENDOR | usb1.RECIPIENT_DEVICE, 0xe0, port_number, 0, 0x100)
|
||||||
|
|
||||||
|
def serial_write(self, port_number):
|
||||||
|
return self.handle.bulkWrite(2, chr(port_number) + ln)
|
||||||
|
|
||||||
|
# ******************* kline *******************
|
||||||
|
|
||||||
|
# pulse low for wakeup
|
||||||
|
def kline_wakeup(self):
|
||||||
|
ret = self.handle.controlWrite(usb1.TYPE_VENDOR | usb1.RECIPIENT_DEVICE, 0xf0, 0, 0, "")
|
||||||
|
|
||||||
|
def kline_drain(self, bus=2):
|
||||||
|
# drain buffer
|
||||||
|
bret = ""
|
||||||
|
while 1:
|
||||||
|
ret = self.handle.controlRead(usb1.TYPE_VENDOR | usb1.RECIPIENT_DEVICE, 0xe0, bus, 0, 0x100)
|
||||||
|
if len(ret) == 0:
|
||||||
|
break
|
||||||
|
bret += str(ret)
|
||||||
|
return bret
|
||||||
|
|
||||||
|
def kline_ll_recv(self, cnt, bus=2):
|
||||||
|
echo = ""
|
||||||
|
while len(echo) != cnt:
|
||||||
|
echo += str(self.handle.controlRead(usb1.TYPE_VENDOR | usb1.RECIPIENT_DEVICE, 0xe0, bus, 0, cnt-len(echo)))
|
||||||
|
return echo
|
||||||
|
|
||||||
|
def kline_send(self, x, bus=2, checksum=True):
|
||||||
|
def get_checksum(dat):
|
||||||
|
result = 0
|
||||||
|
result += sum(map(ord, dat))
|
||||||
|
result = -result
|
||||||
|
return chr(result&0xFF)
|
||||||
|
|
||||||
|
self.kline_drain(bus=bus)
|
||||||
|
if checksum:
|
||||||
|
x += get_checksum(x)
|
||||||
|
for i in range(0, len(x), 0x10):
|
||||||
|
ts = x[i:i+0x10]
|
||||||
|
self.handle.bulkWrite(2, chr(bus)+ts)
|
||||||
|
echo = self.kline_ll_recv(len(ts), bus=bus)
|
||||||
|
if echo != ts:
|
||||||
|
print "**** ECHO ERROR %d ****" % i
|
||||||
|
print echo.encode("hex")
|
||||||
|
print ts.encode("hex")
|
||||||
|
assert echo == ts
|
||||||
|
|
||||||
|
def kline_recv(self, bus=2):
|
||||||
|
msg = self.kline_ll_recv(2, bus=bus)
|
||||||
|
msg += self.kline_ll_recv(ord(msg[1])-2, bus=bus)
|
||||||
|
return msg
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import usb1
|
||||||
|
import time
|
||||||
|
import select
|
||||||
|
from panda.lib.panda import Panda
|
||||||
|
|
||||||
|
setcolor = ["\033[1;32;40m", "\033[1;31;40m"]
|
||||||
|
unsetcolor = "\033[00m"
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
port_number = int(os.getenv("PORT", 0))
|
||||||
|
|
||||||
|
serials = Panda.list()
|
||||||
|
pandas = map(lambda x: Panda(x, False), serials)
|
||||||
|
while 1:
|
||||||
|
for i, panda in enumerate(pandas):
|
||||||
|
ret = panda.serial_read(port_number)
|
||||||
|
if len(ret) > 0:
|
||||||
|
sys.stdout.write(setcolor[i] + ret + unsetcolor)
|
||||||
|
sys.stdout.flush()
|
||||||
|
if select.select([sys.stdin], [], [], 0) == ([sys.stdin], [], []):
|
||||||
|
ln = sys.stdin.readline()
|
||||||
|
panda.serial_write(port_number)
|
||||||
|
time.sleep(0.05)
|
||||||
|
|
|
@ -0,0 +1,95 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
import usb1
|
||||||
|
import random
|
||||||
|
import struct
|
||||||
|
from panda.lib.panda import Panda
|
||||||
|
from hexdump import hexdump
|
||||||
|
|
||||||
|
def get_test_string():
|
||||||
|
return "test"+os.urandom(10)
|
||||||
|
|
||||||
|
def run_test():
|
||||||
|
pandas = Panda.list()
|
||||||
|
print pandas
|
||||||
|
h = map(lambda x: Panda(x), pandas)
|
||||||
|
print h
|
||||||
|
|
||||||
|
# test both directions
|
||||||
|
for ho in [[0,1], [1,0]]:
|
||||||
|
|
||||||
|
# **** test health packet ****
|
||||||
|
print "health", ho[0], h[ho[0]].health()
|
||||||
|
|
||||||
|
# **** test K/L line loopback ****
|
||||||
|
for bus in [2,3]:
|
||||||
|
# flush the output
|
||||||
|
h[ho[1]].kline_drain(bus=bus)
|
||||||
|
|
||||||
|
# send the characters
|
||||||
|
st = get_test_string()
|
||||||
|
st = "\xaa"+chr(len(st)+3)+st
|
||||||
|
h[ho[0]].kline_send(st, bus=bus, checksum=False)
|
||||||
|
|
||||||
|
# check for receive
|
||||||
|
ret = h[ho[1]].kline_drain(bus=bus)
|
||||||
|
|
||||||
|
hexdump(st)
|
||||||
|
hexdump(ret)
|
||||||
|
assert st == ret
|
||||||
|
print "K/L pass", bus, ho
|
||||||
|
|
||||||
|
# **** test can line loopback ****
|
||||||
|
for bus in [0,1,4,5]:
|
||||||
|
print "test can", bus
|
||||||
|
# flush
|
||||||
|
cans_echo = h[ho[0]].can_recv()
|
||||||
|
cans_loop = h[ho[1]].can_recv()
|
||||||
|
|
||||||
|
# set GMLAN mode
|
||||||
|
if bus == 5:
|
||||||
|
h[ho[0]].set_gmlan(True)
|
||||||
|
h[ho[1]].set_gmlan(True)
|
||||||
|
bus = 1 # GMLAN is multiplexed with CAN2
|
||||||
|
is_gmlan = True
|
||||||
|
else:
|
||||||
|
h[ho[0]].set_gmlan(False)
|
||||||
|
h[ho[1]].set_gmlan(False)
|
||||||
|
is_gmlan = False
|
||||||
|
|
||||||
|
# send the characters
|
||||||
|
# pick addresses high enough to not conflict with honda code
|
||||||
|
at = random.randint(1024, 2000)
|
||||||
|
st = get_test_string()[0:8]
|
||||||
|
h[ho[0]].can_send(at, st, bus)
|
||||||
|
time.sleep(0.1)
|
||||||
|
|
||||||
|
# check for receive
|
||||||
|
cans_echo = h[ho[0]].can_recv()
|
||||||
|
cans_loop = h[ho[1]].can_recv()
|
||||||
|
|
||||||
|
print bus, cans_echo, cans_loop
|
||||||
|
|
||||||
|
assert len(cans_echo) == 1
|
||||||
|
assert len(cans_loop) == 1
|
||||||
|
|
||||||
|
assert cans_echo[0][0] == at
|
||||||
|
assert cans_loop[0][0] == at
|
||||||
|
|
||||||
|
assert cans_echo[0][2] == st
|
||||||
|
assert cans_loop[0][2] == st
|
||||||
|
|
||||||
|
assert cans_echo[0][3] == bus+2
|
||||||
|
assert cans_loop[0][3] == bus
|
||||||
|
|
||||||
|
print "CAN pass", bus, ho
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
i = 0
|
||||||
|
while 1:
|
||||||
|
print "************* testing %d" % i
|
||||||
|
run_test()
|
||||||
|
i += 1
|
||||||
|
|
Loading…
Reference in New Issue