initial commit

This commit is contained in:
George Hotz 2017-04-06 18:11:36 -07:00
commit e07f9b111e
64 changed files with 37461 additions and 0 deletions

4
.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
*.pyc
.*.swp
*.o

7
LICENSE Normal file
View File

@ -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.

41
README.md Normal file
View File

@ -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

11
TODO Normal file
View File

@ -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
__init__.py Normal file
View File

1
board/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
obj/*

10
board/Makefile Normal file
View File

@ -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

9
board/Makefile.legacy Normal file
View File

@ -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

9
board/README Normal file
View File

@ -0,0 +1,9 @@
== Building ==
./get_sdk.sh
dfu-util from
git@github.com:dsigma/dfu-util.git

0
board/__init__.py Normal file
View File

39
board/adc.h Normal file
View File

@ -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;
}

22
board/bootstub.c Normal file
View File

@ -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;
}

54
board/build.mk Normal file
View File

@ -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/*

112
board/can.h Normal file
View File

@ -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;
}

16
board/dac.h Normal file
View File

@ -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;
}
}

84
board/early.h Normal file
View File

@ -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);
}
}

2
board/get_sdk.sh Executable file
View File

@ -0,0 +1,2 @@
#!/bin/bash
sudo apt-get install gcc-arm-none-eabi

70
board/honda_safety.h Normal file
View File

@ -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?
}

1373
board/inc/cmsis_gcc.h Normal file

File diff suppressed because it is too large Load Diff

1763
board/inc/core_cm3.h Normal file

File diff suppressed because it is too large Load Diff

1937
board/inc/core_cm4.h Normal file

File diff suppressed because it is too large Load Diff

87
board/inc/core_cmFunc.h Normal file
View File

@ -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 */

87
board/inc/core_cmInstr.h Normal file
View File

@ -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 */

96
board/inc/core_cmSimd.h Normal file
View File

@ -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 */

7666
board/inc/stm32f205xx.h Normal file

File diff suppressed because it is too large Load Diff

209
board/inc/stm32f2xx.h Normal file
View File

@ -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 peripherals drivers in application code(i.e.
* code will be based on direct access to peripherals registers
* rather than drivers API), this option is controlled by
* "#define USE_HAL_DRIVER"
*
******************************************************************************
* @attention
*
* <h2><center>&copy; 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****/

View 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>&copy; 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****/

View 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>&copy; 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****/

14994
board/inc/stm32f413xx.h Normal file

File diff suppressed because it is too large Load Diff

271
board/inc/stm32f4xx.h Normal file
View File

@ -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 peripherals drivers in application code(i.e.
* code will be based on direct access to peripherals registers
* rather than drivers API), this option is controlled by
* "#define USE_HAL_DRIVER"
*
******************************************************************************
* @attention
*
* <h2><center>&copy; 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****/

View 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>&copy; 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

View File

@ -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>&copy; 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****/

View 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>&copy; 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****/

378
board/libc.h Normal file
View 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
}
}

859
board/main.c Normal file
View File

@ -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;
}

23
board/spi.h Normal file
View File

@ -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;
}

511
board/startup_stm32f205xx.s Normal file
View File

@ -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>&copy; 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****/

583
board/startup_stm32f413xx.s Normal file
View 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>&copy; 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****/

165
board/stm32_flash.ld Normal file
View 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) }
}

7
board/timer.h Normal file
View File

@ -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;
}

BIN
board/tools/dfu-util-aarch64 Executable file

Binary file not shown.

Binary file not shown.

BIN
board/tools/dfu-util-x86_64-linux Executable file

Binary file not shown.

View File

@ -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)

132
board/tools/ota.py Executable file
View File

@ -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()

631
board/usb.h Normal file
View File

@ -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);
}

4
boardesp/.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
proxy
*.bin
esp-open-sdk
a.out

49
boardesp/Makefile Normal file
View File

@ -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

34
boardesp/elm327.c Normal file
View File

@ -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);
}

12
boardesp/get_sdk.sh Executable file
View File

@ -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

View File

@ -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

View File

@ -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

182
boardesp/proxy.c Normal file
View File

@ -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);
}

172
boardesp/st_ota.c Normal file
View File

@ -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);
}

437
boardesp/tcp_ota.c Normal file
View File

@ -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);
}

1309
boardesp/tools/esptool.py Executable file

File diff suppressed because it is too large Load Diff

85
boardesp/tools/tcp_flash.py Executable file
View File

@ -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
boardesp/user_config.h Normal file
View File

0
lib/__init__.py Normal file
View File

139
lib/panda.py Normal file
View File

@ -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
tests/__init__.py Normal file
View File

27
tests/debug_console.py Executable file
View File

@ -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)

95
tests/loopback_test.py Executable file
View File

@ -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