mirror of https://github.com/commaai/panda.git
Merge remote-tracking branch 'upstream/master' into isotp-canfd-support
This commit is contained in:
commit
6027f78cd0
|
@ -46,7 +46,7 @@ jobs:
|
|||
run: eval "$BUILD"
|
||||
- name: Test python package installer
|
||||
run: ${{ env.RUN }} "python setup.py install"
|
||||
- name: Build panda + pedal images and bootstub
|
||||
- name: Build panda images and bootstub
|
||||
run: ${{ env.RUN }} "scons -j4"
|
||||
- name: Build panda with SPI support
|
||||
run: ${{ env.RUN }} "ENABLE_SPI=1 scons -j4"
|
||||
|
@ -89,23 +89,6 @@ jobs:
|
|||
scons -j$(nproc) ${{ matrix.flags }} && \
|
||||
tests/safety/test.sh"
|
||||
|
||||
safety_coverage:
|
||||
name: safety coverage
|
||||
runs-on: ubuntu-20.04
|
||||
timeout-minutes: 20
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Build Docker image
|
||||
run: eval "$BUILD"
|
||||
- name: Run safety coverage test
|
||||
timeout-minutes: 5
|
||||
run: |
|
||||
${{ env.RUN }} "cd .. && \
|
||||
scons -c && \
|
||||
scons -j$(nproc) opendbc/ cereal/ && \
|
||||
cd panda/tests/safety && \
|
||||
./test_coverage.sh"
|
||||
|
||||
misra:
|
||||
name: MISRA C:2012
|
||||
runs-on: ubuntu-20.04
|
||||
|
@ -120,8 +103,8 @@ jobs:
|
|||
timeout-minutes: 1
|
||||
run: ${{ env.RUN }} "cd tests/misra && ./test_misra.sh"
|
||||
- name: MISRA mutation tests
|
||||
timeout-minutes: 3
|
||||
run: ${{ env.RUN }} "cd tests/misra && ./test_mutation.py"
|
||||
timeout-minutes: 5
|
||||
run: ${{ env.RUN }} "cd tests/misra && pytest -n8 test_mutation.py"
|
||||
|
||||
python_linter:
|
||||
name: python linter
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
repos:
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v4.5.0
|
||||
rev: v4.6.0
|
||||
hooks:
|
||||
- id: check-ast
|
||||
- id: check-yaml
|
||||
|
@ -9,12 +9,12 @@ repos:
|
|||
- id: check-executables-have-shebangs
|
||||
- id: check-shebang-scripts-are-executable
|
||||
- repo: https://github.com/pre-commit/mirrors-mypy
|
||||
rev: v1.8.0
|
||||
rev: v1.9.0
|
||||
hooks:
|
||||
- id: mypy
|
||||
additional_dependencies: ['git+https://github.com/numpy/numpy-stubs', 'types-requests', 'types-atomicwrites',
|
||||
'types-pycurl']
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
rev: v0.1.15
|
||||
rev: v0.4.1
|
||||
hooks:
|
||||
- id: ruff
|
||||
|
|
|
@ -51,8 +51,8 @@ RUN curl -L https://github.com/pyenv/pyenv-installer/raw/master/bin/pyenv-instal
|
|||
ENV PATH="/root/.pyenv/bin:/root/.pyenv/shims:${PATH}"
|
||||
|
||||
ENV PANDA_PATH=/tmp/openpilot/panda
|
||||
ENV OPENPILOT_REF="5690386d8d731c9bebda536a5c71c890f6dfe98c"
|
||||
ENV OPENDBC_REF="40d9c723d48496229fecc436046538a53af19c11"
|
||||
ENV OPENPILOT_REF="bc4b75822a609e6897058bc83688c84004f29093"
|
||||
ENV OPENDBC_REF="1745ab51825055cd18748013c4a5e3377319e390"
|
||||
|
||||
COPY requirements.txt /tmp/
|
||||
RUN pyenv install 3.11.4 && \
|
||||
|
@ -63,6 +63,8 @@ RUN pyenv install 3.11.4 && \
|
|||
ENV CPPCHECK_DIR=/tmp/cppcheck
|
||||
COPY tests/misra/install.sh /tmp/
|
||||
RUN /tmp/install.sh
|
||||
# don't try to install again
|
||||
ENV SKIP_CPPCHECK_INSTALL=1
|
||||
|
||||
RUN git config --global --add safe.directory /tmp/openpilot/panda
|
||||
RUN cd /tmp && \
|
||||
|
|
|
@ -82,7 +82,7 @@ pipeline {
|
|||
["build", "scons -j4"],
|
||||
["flash", "cd tests/ && ./reflash_internal_panda.py"],
|
||||
["flash jungle", "cd board/jungle && ./flash.py"],
|
||||
["test", "cd tests/hitl && HW_TYPES=6 pytest --durations=0 [2-7]*.py -k 'not test_send_recv'"],
|
||||
["test", "cd tests/hitl && HW_TYPES=6 pytest -n0 --durations=0 [2-9]*.py -k 'not test_send_recv'"],
|
||||
])
|
||||
}
|
||||
}
|
||||
|
@ -94,7 +94,7 @@ pipeline {
|
|||
["build", "scons -j4"],
|
||||
["flash", "cd tests/ && ./reflash_internal_panda.py"],
|
||||
["flash jungle", "cd board/jungle && ./flash.py"],
|
||||
["test", "cd tests/hitl && HW_TYPES=9 pytest --durations=0 2*.py [5-9]*.py"],
|
||||
["test", "cd tests/hitl && HW_TYPES=9 pytest -n0 --durations=0 2*.py [5-9]*.py"],
|
||||
])
|
||||
}
|
||||
}
|
||||
|
@ -126,35 +126,10 @@ pipeline {
|
|||
stage('bootkick tests') {
|
||||
steps {
|
||||
script {
|
||||
docker_run("test", 10, "pytest ./tests/som/test_bootkick.py")
|
||||
docker_run("test", 10, "pytest -n0 ./tests/som/test_bootkick.py")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
stage('pedal tests') {
|
||||
steps {
|
||||
script {
|
||||
docker_run("test pedal", 1, "PEDAL_JUNGLE=058010800f51363038363036 python ./tests/pedal/test_pedal.py")
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('HITL tests') {
|
||||
steps {
|
||||
script {
|
||||
docker_run("parallel tests", 5, 'PANDAS_JUNGLE=23002d000851393038373731 PANDAS_EXCLUDE="1d0002000c51303136383232 2f002e000c51303136383232" ./tests/hitl/run_parallel_tests.sh')
|
||||
docker_run("serial tests", 9, 'PANDAS_JUNGLE=23002d000851393038373731 PANDAS_EXCLUDE="1d0002000c51303136383232 2f002e000c51303136383232" ./tests/hitl/run_serial_tests.sh')
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('CANFD tests') {
|
||||
steps {
|
||||
script {
|
||||
docker_run("CANFD tets", 6, 'JUNGLE=058010800f51363038363036 H7_PANDAS_EXCLUDE="080021000c51303136383232 33000e001051393133353939" ./tests/canfd/test_canfd.py')
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
![panda tests](https://github.com/commaai/panda/workflows/tests/badge.svg)
|
||||
![panda drivers](https://github.com/commaai/panda/workflows/drivers/badge.svg)
|
||||
|
||||
panda speaks CAN and CAN FD, and it runs on [STM32F205](https://www.st.com/resource/en/reference_manual/rm0033-stm32f205xx-stm32f207xx-stm32f215xx-and-stm32f217xx-advanced-armbased-32bit-mcus-stmicroelectronics.pdf), [STM32F413](https://www.st.com/resource/en/reference_manual/rm0430-stm32f413423-advanced-armbased-32bit-mcus-stmicroelectronics.pdf), and [STM32H725](https://www.st.com/resource/en/reference_manual/rm0468-stm32h723733-stm32h725735-and-stm32h730-value-line-advanced-armbased-32bit-mcus-stmicroelectronics.pdf).
|
||||
panda speaks CAN and CAN FD, and it runs on [STM32F413](https://www.st.com/resource/en/reference_manual/rm0430-stm32f413423-advanced-armbased-32bit-mcus-stmicroelectronics.pdf) and [STM32H725](https://www.st.com/resource/en/reference_manual/rm0468-stm32h723733-stm32h725735-and-stm32h730-value-line-advanced-armbased-32bit-mcus-stmicroelectronics.pdf).
|
||||
|
||||
## Directory structure
|
||||
|
||||
|
|
|
@ -84,7 +84,7 @@ def build_project(project_name, project, extra_flags):
|
|||
'..',
|
||||
panda_root,
|
||||
f"{panda_root}/board/",
|
||||
f"{panda_root}/board/stm32fx/inc",
|
||||
f"{panda_root}/board/stm32f4/inc",
|
||||
f"{panda_root}/board/stm32h7/inc",
|
||||
]
|
||||
|
||||
|
@ -130,8 +130,8 @@ def build_project(project_name, project, extra_flags):
|
|||
|
||||
base_project_f4 = {
|
||||
"MAIN": "main.c",
|
||||
"STARTUP_FILE": File("./board/stm32fx/startup_stm32f413xx.s"),
|
||||
"LINKER_SCRIPT": File("./board/stm32fx/stm32f4_flash.ld"),
|
||||
"STARTUP_FILE": File("./board/stm32f4/startup_stm32f413xx.s"),
|
||||
"LINKER_SCRIPT": File("./board/stm32f4/stm32f4_flash.ld"),
|
||||
"APP_START_ADDRESS": "0x8004000",
|
||||
"PROJECT_FLAGS": [
|
||||
"-mcpu=cortex-m4",
|
||||
|
@ -180,9 +180,6 @@ with open("board/obj/cert.h", "w") as f:
|
|||
# panda fw
|
||||
SConscript('board/SConscript')
|
||||
|
||||
# pedal fw
|
||||
SConscript('board/pedal/SConscript')
|
||||
|
||||
# panda jungle fw
|
||||
SConscript('board/jungle/SConscript')
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ for project_name, project in build_projects.items():
|
|||
flags = [
|
||||
"-DPANDA",
|
||||
]
|
||||
if ("ENABLE_SPI" in os.environ or "h7" in project_name) and not project_name.startswith('pedal'):
|
||||
if ("ENABLE_SPI" in os.environ or "h7" in project_name):
|
||||
flags.append('-DENABLE_SPI')
|
||||
|
||||
if "H723" in os.environ:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// ///////////////////// //
|
||||
// Black Panda + Harness //
|
||||
// ///////////////////// //
|
||||
// /////////////////////////////// //
|
||||
// Black Panda (STM32F4) + Harness //
|
||||
// /////////////////////////////// //
|
||||
|
||||
void black_enable_can_transceiver(uint8_t transceiver, bool enabled) {
|
||||
switch (transceiver){
|
||||
|
@ -122,8 +122,6 @@ void black_init(void) {
|
|||
// Initialize harness
|
||||
harness_init();
|
||||
|
||||
// Initialize RTC
|
||||
rtc_init();
|
||||
|
||||
// Enable CAN transceivers
|
||||
black_enable_can_transceivers(true);
|
||||
|
@ -135,11 +133,6 @@ void black_init(void) {
|
|||
|
||||
// Set normal CAN mode
|
||||
black_set_can_mode(CAN_MODE_NORMAL);
|
||||
|
||||
// flip CAN0 and CAN2 if we are flipped
|
||||
if (harness.status == HARNESS_STATUS_FLIPPED) {
|
||||
can_flip_buses(0, 2);
|
||||
}
|
||||
}
|
||||
|
||||
void black_init_bootloader(void) {
|
||||
|
@ -148,7 +141,7 @@ void black_init_bootloader(void) {
|
|||
set_gpio_output(GPIOC, 12, 0);
|
||||
}
|
||||
|
||||
const harness_configuration black_harness_config = {
|
||||
harness_configuration black_harness_config = {
|
||||
.has_harness = true,
|
||||
.GPIO_SBU1 = GPIOC,
|
||||
.GPIO_SBU2 = GPIOC,
|
||||
|
@ -162,13 +155,12 @@ const harness_configuration black_harness_config = {
|
|||
.adc_channel_SBU2 = 13
|
||||
};
|
||||
|
||||
const board board_black = {
|
||||
board board_black = {
|
||||
.set_bootkick = unused_set_bootkick,
|
||||
.harness_config = &black_harness_config,
|
||||
.has_obd = true,
|
||||
.has_spi = false,
|
||||
.has_canfd = false,
|
||||
.has_rtc_battery = false,
|
||||
.fan_max_rpm = 0U,
|
||||
.avdd_mV = 3300U,
|
||||
.fan_stall_recovery = false,
|
||||
|
@ -180,7 +172,8 @@ const board board_black = {
|
|||
.set_led = black_set_led,
|
||||
.set_can_mode = black_set_can_mode,
|
||||
.check_ignition = black_check_ignition,
|
||||
.read_current = unused_read_current,
|
||||
.read_voltage_mV = white_read_voltage_mV,
|
||||
.read_current_mA = unused_read_current,
|
||||
.set_fan_enabled = unused_set_fan_enabled,
|
||||
.set_ir_power = unused_set_ir_power,
|
||||
.set_siren = unused_set_siren,
|
||||
|
|
|
@ -12,7 +12,8 @@ typedef void (*board_enable_can_transceivers)(bool enabled);
|
|||
typedef void (*board_set_led)(uint8_t color, bool enabled);
|
||||
typedef void (*board_set_can_mode)(uint8_t mode);
|
||||
typedef bool (*board_check_ignition)(void);
|
||||
typedef uint32_t (*board_read_current)(void);
|
||||
typedef uint32_t (*board_read_voltage_mV)(void);
|
||||
typedef uint32_t (*board_read_current_mA)(void);
|
||||
typedef void (*board_set_ir_power)(uint8_t percentage);
|
||||
typedef void (*board_set_fan_enabled)(bool enabled);
|
||||
typedef void (*board_set_siren)(bool enabled);
|
||||
|
@ -20,11 +21,10 @@ typedef void (*board_set_bootkick)(BootState state);
|
|||
typedef bool (*board_read_som_gpio)(void);
|
||||
|
||||
struct board {
|
||||
const harness_configuration *harness_config;
|
||||
harness_configuration *harness_config;
|
||||
const bool has_obd;
|
||||
const bool has_spi;
|
||||
const bool has_canfd;
|
||||
const bool has_rtc_battery;
|
||||
const uint16_t fan_max_rpm;
|
||||
const uint16_t avdd_mV;
|
||||
const bool fan_stall_recovery;
|
||||
|
@ -36,7 +36,8 @@ struct board {
|
|||
board_set_led set_led;
|
||||
board_set_can_mode set_can_mode;
|
||||
board_check_ignition check_ignition;
|
||||
board_read_current read_current;
|
||||
board_read_voltage_mV read_voltage_mV;
|
||||
board_read_current_mA read_current_mA;
|
||||
board_set_ir_power set_ir_power;
|
||||
board_set_fan_enabled set_fan_enabled;
|
||||
board_set_siren set_siren;
|
||||
|
@ -71,6 +72,4 @@ struct board {
|
|||
|
||||
// CAN modes
|
||||
#define CAN_MODE_NORMAL 0U
|
||||
#define CAN_MODE_GMLAN_CAN2 1U
|
||||
#define CAN_MODE_GMLAN_CAN3 2U
|
||||
#define CAN_MODE_OBD_CAN2 3U
|
||||
#define CAN_MODE_OBD_CAN2 1U
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
// ////////////////////////// //
|
||||
// Cuatro (STM32H7) + Harness //
|
||||
// ////////////////////////// //
|
||||
|
||||
void cuatro_set_led(uint8_t color, bool enabled) {
|
||||
switch (color) {
|
||||
case LED_RED:
|
||||
|
@ -15,29 +19,62 @@ void cuatro_set_led(uint8_t color, bool enabled) {
|
|||
}
|
||||
|
||||
void cuatro_enable_can_transceiver(uint8_t transceiver, bool enabled) {
|
||||
if (transceiver == 1U) {
|
||||
set_gpio_output(GPIOB, 7, !enabled);
|
||||
} else if (transceiver == 3U) {
|
||||
set_gpio_output(GPIOD, 8, !enabled);
|
||||
} else {
|
||||
red_enable_can_transceiver(transceiver, enabled);
|
||||
switch (transceiver) {
|
||||
case 1U:
|
||||
set_gpio_output(GPIOB, 7, !enabled);
|
||||
break;
|
||||
case 2U:
|
||||
set_gpio_output(GPIOB, 10, !enabled);
|
||||
break;
|
||||
case 3U:
|
||||
set_gpio_output(GPIOD, 8, !enabled);
|
||||
break;
|
||||
case 4U:
|
||||
set_gpio_output(GPIOB, 11, !enabled);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void cuatro_enable_can_transceivers(bool enabled) {
|
||||
uint8_t main_bus = (harness.status == HARNESS_STATUS_FLIPPED) ? 3U : 1U;
|
||||
for (uint8_t i=1U; i<=4U; i++) {
|
||||
// Leave main CAN always on for CAN-based ignition detection
|
||||
if (i == main_bus) {
|
||||
cuatro_enable_can_transceiver(i, true);
|
||||
} else {
|
||||
cuatro_enable_can_transceiver(i, enabled);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t cuatro_read_voltage_mV(void) {
|
||||
return adc_get_mV(8) * 11U;
|
||||
}
|
||||
|
||||
uint32_t cuatro_read_current_mA(void) {
|
||||
return adc_get_mV(3) * 2U;
|
||||
}
|
||||
|
||||
void cuatro_init(void) {
|
||||
red_chiplet_init();
|
||||
|
||||
// CAN FD 0 transceiver enable (rest are done in red init)
|
||||
// Power readout
|
||||
set_gpio_mode(GPIOC, 5, MODE_ANALOG);
|
||||
set_gpio_mode(GPIOA, 6, MODE_ANALOG);
|
||||
|
||||
// CAN transceiver enables
|
||||
set_gpio_pullup(GPIOB, 7, PULL_NONE);
|
||||
set_gpio_mode(GPIOB, 7, MODE_OUTPUT);
|
||||
set_gpio_pullup(GPIOD, 8, PULL_NONE);
|
||||
set_gpio_mode(GPIOD, 8, MODE_OUTPUT);
|
||||
|
||||
// FDCAN2
|
||||
// FDCAN3, different pins on this package than the rest of the reds
|
||||
set_gpio_pullup(GPIOD, 12, PULL_NONE);
|
||||
set_gpio_alternate(GPIOD, 12, GPIO_AF9_FDCAN2);
|
||||
set_gpio_alternate(GPIOD, 12, GPIO_AF5_FDCAN3);
|
||||
set_gpio_pullup(GPIOD, 13, PULL_NONE);
|
||||
set_gpio_alternate(GPIOD, 13, GPIO_AF9_FDCAN2);
|
||||
set_gpio_alternate(GPIOD, 13, GPIO_AF5_FDCAN3);
|
||||
|
||||
// C2: SOM GPIO used as input (fan control at boot)
|
||||
set_gpio_mode(GPIOC, 2, MODE_INPUT);
|
||||
|
@ -66,12 +103,11 @@ void cuatro_init(void) {
|
|||
clock_source_init();
|
||||
}
|
||||
|
||||
const board board_cuatro = {
|
||||
board board_cuatro = {
|
||||
.harness_config = &red_chiplet_harness_config,
|
||||
.has_obd = true,
|
||||
.has_spi = true,
|
||||
.has_canfd = true,
|
||||
.has_rtc_battery = true,
|
||||
.fan_max_rpm = 6600U,
|
||||
.avdd_mV = 1800U,
|
||||
.fan_stall_recovery = false,
|
||||
|
@ -79,11 +115,12 @@ const board board_cuatro = {
|
|||
.init = cuatro_init,
|
||||
.init_bootloader = unused_init_bootloader,
|
||||
.enable_can_transceiver = cuatro_enable_can_transceiver,
|
||||
.enable_can_transceivers = red_chiplet_enable_can_transceivers,
|
||||
.enable_can_transceivers = cuatro_enable_can_transceivers,
|
||||
.set_led = cuatro_set_led,
|
||||
.set_can_mode = red_chiplet_set_can_mode,
|
||||
.check_ignition = red_check_ignition,
|
||||
.read_current = unused_read_current,
|
||||
.read_voltage_mV = cuatro_read_voltage_mV,
|
||||
.read_current_mA = cuatro_read_current_mA,
|
||||
.set_fan_enabled = tres_set_fan_enabled,
|
||||
.set_ir_power = tres_set_ir_power,
|
||||
.set_siren = unused_set_siren,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// ///////////// //
|
||||
// Dos + Harness //
|
||||
// ///////////// //
|
||||
// /////////////////////// //
|
||||
// Dos (STM32F4) + Harness //
|
||||
// /////////////////////// //
|
||||
|
||||
void dos_enable_can_transceiver(uint8_t transceiver, bool enabled) {
|
||||
switch (transceiver){
|
||||
|
@ -90,10 +90,6 @@ bool dos_check_ignition(void){
|
|||
return harness_check_ignition();
|
||||
}
|
||||
|
||||
void dos_set_usb_switch(bool phone){
|
||||
set_gpio_output(GPIOB, 3, phone);
|
||||
}
|
||||
|
||||
void dos_set_ir_power(uint8_t percentage){
|
||||
pwm_set(TIM4, 2, percentage);
|
||||
}
|
||||
|
@ -151,8 +147,6 @@ void dos_init(void) {
|
|||
// Initialize harness
|
||||
harness_init();
|
||||
|
||||
// Initialize RTC
|
||||
rtc_init();
|
||||
|
||||
// Enable CAN transceivers
|
||||
dos_enable_can_transceivers(true);
|
||||
|
@ -168,16 +162,11 @@ void dos_init(void) {
|
|||
// Set normal CAN mode
|
||||
dos_set_can_mode(CAN_MODE_NORMAL);
|
||||
|
||||
// flip CAN0 and CAN2 if we are flipped
|
||||
if (harness.status == HARNESS_STATUS_FLIPPED) {
|
||||
can_flip_buses(0, 2);
|
||||
}
|
||||
|
||||
// Init clock source (camera strobe) using PWM
|
||||
clock_source_init();
|
||||
}
|
||||
|
||||
const harness_configuration dos_harness_config = {
|
||||
harness_configuration dos_harness_config = {
|
||||
.has_harness = true,
|
||||
.GPIO_SBU1 = GPIOC,
|
||||
.GPIO_SBU2 = GPIOC,
|
||||
|
@ -191,7 +180,7 @@ const harness_configuration dos_harness_config = {
|
|||
.adc_channel_SBU2 = 13
|
||||
};
|
||||
|
||||
const board board_dos = {
|
||||
board board_dos = {
|
||||
.harness_config = &dos_harness_config,
|
||||
.has_obd = true,
|
||||
#ifdef ENABLE_SPI
|
||||
|
@ -200,7 +189,6 @@ const board board_dos = {
|
|||
.has_spi = false,
|
||||
#endif
|
||||
.has_canfd = false,
|
||||
.has_rtc_battery = true,
|
||||
.fan_max_rpm = 6500U,
|
||||
.avdd_mV = 3300U,
|
||||
.fan_stall_recovery = true,
|
||||
|
@ -212,7 +200,8 @@ const board board_dos = {
|
|||
.set_led = dos_set_led,
|
||||
.set_can_mode = dos_set_can_mode,
|
||||
.check_ignition = dos_check_ignition,
|
||||
.read_current = unused_read_current,
|
||||
.read_voltage_mV = white_read_voltage_mV,
|
||||
.read_current_mA = unused_read_current,
|
||||
.set_fan_enabled = dos_set_fan_enabled,
|
||||
.set_ir_power = dos_set_ir_power,
|
||||
.set_siren = dos_set_siren,
|
||||
|
|
|
@ -1,16 +1,15 @@
|
|||
// ////////// //
|
||||
// Grey Panda //
|
||||
// ////////// //
|
||||
// //////////////////// //
|
||||
// Grey Panda (STM32F4) //
|
||||
// //////////////////// //
|
||||
|
||||
// Most hardware functionality is similar to white panda
|
||||
|
||||
const board board_grey = {
|
||||
board board_grey = {
|
||||
.set_bootkick = unused_set_bootkick,
|
||||
.harness_config = &white_harness_config,
|
||||
.has_obd = false,
|
||||
.has_spi = false,
|
||||
.has_canfd = false,
|
||||
.has_rtc_battery = false,
|
||||
.fan_max_rpm = 0U,
|
||||
.avdd_mV = 3300U,
|
||||
.fan_stall_recovery = false,
|
||||
|
@ -22,7 +21,8 @@ const board board_grey = {
|
|||
.set_led = white_set_led,
|
||||
.set_can_mode = white_set_can_mode,
|
||||
.check_ignition = white_check_ignition,
|
||||
.read_current = white_read_current,
|
||||
.read_voltage_mV = white_read_voltage_mV,
|
||||
.read_current_mA = white_read_current_mA,
|
||||
.set_fan_enabled = unused_set_fan_enabled,
|
||||
.set_ir_power = unused_set_ir_power,
|
||||
.set_siren = unused_set_siren,
|
||||
|
|
|
@ -1,92 +0,0 @@
|
|||
// ///// //
|
||||
// Pedal //
|
||||
// ///// //
|
||||
|
||||
void pedal_enable_can_transceiver(uint8_t transceiver, bool enabled) {
|
||||
switch (transceiver){
|
||||
case 1:
|
||||
set_gpio_output(GPIOB, 3, !enabled);
|
||||
break;
|
||||
default:
|
||||
print("Invalid CAN transceiver ("); puth(transceiver); print("): enabling failed\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void pedal_enable_can_transceivers(bool enabled) {
|
||||
pedal_enable_can_transceiver(1U, enabled);
|
||||
}
|
||||
|
||||
void pedal_set_led(uint8_t color, bool enabled) {
|
||||
switch (color){
|
||||
case LED_RED:
|
||||
set_gpio_output(GPIOB, 10, !enabled);
|
||||
break;
|
||||
case LED_GREEN:
|
||||
set_gpio_output(GPIOB, 11, !enabled);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void pedal_set_can_mode(uint8_t mode){
|
||||
switch (mode) {
|
||||
case CAN_MODE_NORMAL:
|
||||
break;
|
||||
default:
|
||||
print("Tried to set unsupported CAN mode: "); puth(mode); print("\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool pedal_check_ignition(void){
|
||||
// not supported on pedal
|
||||
return false;
|
||||
}
|
||||
|
||||
void pedal_init(void) {
|
||||
common_init_gpio();
|
||||
|
||||
// C0, C1: Throttle inputs
|
||||
set_gpio_mode(GPIOC, 0, MODE_ANALOG);
|
||||
set_gpio_mode(GPIOC, 1, MODE_ANALOG);
|
||||
// DAC outputs on A4 and A5
|
||||
// apparently they don't need GPIO setup
|
||||
|
||||
// Enable transceiver
|
||||
pedal_enable_can_transceivers(true);
|
||||
|
||||
// Disable LEDs
|
||||
pedal_set_led(LED_RED, false);
|
||||
pedal_set_led(LED_GREEN, false);
|
||||
}
|
||||
|
||||
const harness_configuration pedal_harness_config = {
|
||||
.has_harness = false
|
||||
};
|
||||
|
||||
const board board_pedal = {
|
||||
.set_bootkick = unused_set_bootkick,
|
||||
.harness_config = &pedal_harness_config,
|
||||
.has_obd = false,
|
||||
.has_spi = false,
|
||||
.has_canfd = false,
|
||||
.has_rtc_battery = false,
|
||||
.fan_max_rpm = 0U,
|
||||
.avdd_mV = 3300U,
|
||||
.fan_stall_recovery = false,
|
||||
.fan_enable_cooldown_time = 0U,
|
||||
.init = pedal_init,
|
||||
.init_bootloader = unused_init_bootloader,
|
||||
.enable_can_transceiver = pedal_enable_can_transceiver,
|
||||
.enable_can_transceivers = pedal_enable_can_transceivers,
|
||||
.set_led = pedal_set_led,
|
||||
.set_can_mode = pedal_set_can_mode,
|
||||
.check_ignition = pedal_check_ignition,
|
||||
.read_current = unused_read_current,
|
||||
.set_fan_enabled = unused_set_fan_enabled,
|
||||
.set_ir_power = unused_set_ir_power,
|
||||
.set_siren = unused_set_siren,
|
||||
.read_som_gpio = unused_read_som_gpio
|
||||
};
|
|
@ -1,6 +1,6 @@
|
|||
// ///////////////////// //
|
||||
// Red Panda + Harness //
|
||||
// ///////////////////// //
|
||||
// ///////////////////////////// //
|
||||
// Red Panda (STM32H7) + Harness //
|
||||
// ///////////////////////////// //
|
||||
|
||||
void red_enable_can_transceiver(uint8_t transceiver, bool enabled) {
|
||||
switch (transceiver) {
|
||||
|
@ -96,6 +96,10 @@ bool red_check_ignition(void) {
|
|||
return harness_check_ignition();
|
||||
}
|
||||
|
||||
uint32_t red_read_voltage_mV(void){
|
||||
return adc_get_mV(2) * 11U; // TODO: is this correct?
|
||||
}
|
||||
|
||||
void red_init(void) {
|
||||
common_init_gpio();
|
||||
|
||||
|
@ -136,8 +140,6 @@ void red_init(void) {
|
|||
// Initialize harness
|
||||
harness_init();
|
||||
|
||||
// Initialize RTC
|
||||
rtc_init();
|
||||
|
||||
// Enable CAN transceivers
|
||||
red_enable_can_transceivers(true);
|
||||
|
@ -149,14 +151,9 @@ void red_init(void) {
|
|||
|
||||
// Set normal CAN mode
|
||||
red_set_can_mode(CAN_MODE_NORMAL);
|
||||
|
||||
// flip CAN0 and CAN2 if we are flipped
|
||||
if (harness.status == HARNESS_STATUS_FLIPPED) {
|
||||
can_flip_buses(0, 2);
|
||||
}
|
||||
}
|
||||
|
||||
const harness_configuration red_harness_config = {
|
||||
harness_configuration red_harness_config = {
|
||||
.has_harness = true,
|
||||
.GPIO_SBU1 = GPIOC,
|
||||
.GPIO_SBU2 = GPIOA,
|
||||
|
@ -170,13 +167,12 @@ const harness_configuration red_harness_config = {
|
|||
.adc_channel_SBU2 = 17 //ADC1_INP17
|
||||
};
|
||||
|
||||
const board board_red = {
|
||||
board board_red = {
|
||||
.set_bootkick = unused_set_bootkick,
|
||||
.harness_config = &red_harness_config,
|
||||
.has_obd = true,
|
||||
.has_spi = false,
|
||||
.has_canfd = true,
|
||||
.has_rtc_battery = false,
|
||||
.fan_max_rpm = 0U,
|
||||
.avdd_mV = 3300U,
|
||||
.fan_stall_recovery = false,
|
||||
|
@ -188,7 +184,8 @@ const board board_red = {
|
|||
.set_led = red_set_led,
|
||||
.set_can_mode = red_set_can_mode,
|
||||
.check_ignition = red_check_ignition,
|
||||
.read_current = unused_read_current,
|
||||
.read_voltage_mV = red_read_voltage_mV,
|
||||
.read_current_mA = unused_read_current,
|
||||
.set_fan_enabled = unused_set_fan_enabled,
|
||||
.set_ir_power = unused_set_ir_power,
|
||||
.set_siren = unused_set_siren,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// ///////////////////// //
|
||||
// Red Panda chiplet + Harness //
|
||||
// ///////////////////// //
|
||||
// ///////////////////////////////////// //
|
||||
// Red Panda chiplet (STM32H7) + Harness //
|
||||
// ///////////////////////////////////// //
|
||||
|
||||
// Most hardware functionality is similar to red panda
|
||||
|
||||
|
@ -119,8 +119,6 @@ void red_chiplet_init(void) {
|
|||
// Initialize harness
|
||||
harness_init();
|
||||
|
||||
// Initialize RTC
|
||||
rtc_init();
|
||||
|
||||
// Enable CAN transceivers
|
||||
red_chiplet_enable_can_transceivers(true);
|
||||
|
@ -132,14 +130,9 @@ void red_chiplet_init(void) {
|
|||
|
||||
// Set normal CAN mode
|
||||
red_chiplet_set_can_mode(CAN_MODE_NORMAL);
|
||||
|
||||
// flip CAN0 and CAN2 if we are flipped
|
||||
if (harness.status == HARNESS_STATUS_FLIPPED) {
|
||||
can_flip_buses(0, 2);
|
||||
}
|
||||
}
|
||||
|
||||
const harness_configuration red_chiplet_harness_config = {
|
||||
harness_configuration red_chiplet_harness_config = {
|
||||
.has_harness = true,
|
||||
.GPIO_SBU1 = GPIOC,
|
||||
.GPIO_SBU2 = GPIOA,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// /////////////////
|
||||
// Tres + Harness //
|
||||
// /////////////////
|
||||
// ///////////////////////////
|
||||
// Tres (STM32H7) + Harness //
|
||||
// ///////////////////////////
|
||||
|
||||
bool tres_ir_enabled;
|
||||
bool tres_fan_enabled;
|
||||
|
@ -33,7 +33,7 @@ void tres_init(void) {
|
|||
// Enable USB 3.3V LDO for USB block
|
||||
register_set_bits(&(PWR->CR3), PWR_CR3_USBREGEN);
|
||||
register_set_bits(&(PWR->CR3), PWR_CR3_USB33DEN);
|
||||
while ((PWR->CR3 & PWR_CR3_USB33RDY) == 0);
|
||||
while ((PWR->CR3 & PWR_CR3_USB33RDY) == 0U);
|
||||
|
||||
red_chiplet_init();
|
||||
|
||||
|
@ -70,12 +70,11 @@ void tres_init(void) {
|
|||
clock_source_init();
|
||||
}
|
||||
|
||||
const board board_tres = {
|
||||
board board_tres = {
|
||||
.harness_config = &red_chiplet_harness_config,
|
||||
.has_obd = true,
|
||||
.has_spi = true,
|
||||
.has_canfd = true,
|
||||
.has_rtc_battery = true,
|
||||
.fan_max_rpm = 6600U,
|
||||
.avdd_mV = 1800U,
|
||||
.fan_stall_recovery = false,
|
||||
|
@ -87,7 +86,8 @@ const board board_tres = {
|
|||
.set_led = red_set_led,
|
||||
.set_can_mode = red_chiplet_set_can_mode,
|
||||
.check_ignition = red_check_ignition,
|
||||
.read_current = unused_read_current,
|
||||
.read_voltage_mV = red_read_voltage_mV,
|
||||
.read_current_mA = unused_read_current,
|
||||
.set_fan_enabled = tres_set_fan_enabled,
|
||||
.set_ir_power = tres_set_ir_power,
|
||||
.set_siren = fake_siren_set,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// ///////////// //
|
||||
// Uno + Harness //
|
||||
// ///////////// //
|
||||
// /////////////////////// //
|
||||
// Uno (STM32F4) + Harness //
|
||||
// /////////////////////// //
|
||||
|
||||
void uno_enable_can_transceiver(uint8_t transceiver, bool enabled) {
|
||||
switch (transceiver){
|
||||
|
@ -147,8 +147,6 @@ void uno_init(void) {
|
|||
// Initialize harness
|
||||
harness_init();
|
||||
|
||||
// Initialize RTC
|
||||
rtc_init();
|
||||
|
||||
// Enable CAN transceivers
|
||||
uno_enable_can_transceivers(true);
|
||||
|
@ -161,13 +159,8 @@ void uno_init(void) {
|
|||
// Set normal CAN mode
|
||||
uno_set_can_mode(CAN_MODE_NORMAL);
|
||||
|
||||
// flip CAN0 and CAN2 if we are flipped
|
||||
if (harness.status == HARNESS_STATUS_FLIPPED) {
|
||||
can_flip_buses(0, 2);
|
||||
}
|
||||
|
||||
// Switch to phone usb mode if harness connection is powered by less than 7V
|
||||
if((adc_get_mV(ADCCHAN_VIN) * VIN_READOUT_DIVIDER) < 7000U){
|
||||
if(white_read_voltage_mV() < 7000U){
|
||||
uno_set_usb_switch(true);
|
||||
} else {
|
||||
uno_set_usb_switch(false);
|
||||
|
@ -184,7 +177,7 @@ void uno_init_bootloader(void) {
|
|||
set_gpio_output(GPIOC, 12, 0);
|
||||
}
|
||||
|
||||
const harness_configuration uno_harness_config = {
|
||||
harness_configuration uno_harness_config = {
|
||||
.has_harness = true,
|
||||
.GPIO_SBU1 = GPIOC,
|
||||
.GPIO_SBU2 = GPIOC,
|
||||
|
@ -198,12 +191,11 @@ const harness_configuration uno_harness_config = {
|
|||
.adc_channel_SBU2 = 13
|
||||
};
|
||||
|
||||
const board board_uno = {
|
||||
board board_uno = {
|
||||
.harness_config = &uno_harness_config,
|
||||
.has_obd = true,
|
||||
.has_spi = false,
|
||||
.has_canfd = false,
|
||||
.has_rtc_battery = true,
|
||||
.fan_max_rpm = 5100U,
|
||||
.avdd_mV = 3300U,
|
||||
.fan_stall_recovery = false,
|
||||
|
@ -215,7 +207,8 @@ const board board_uno = {
|
|||
.set_led = uno_set_led,
|
||||
.set_can_mode = uno_set_can_mode,
|
||||
.check_ignition = uno_check_ignition,
|
||||
.read_current = unused_read_current,
|
||||
.read_voltage_mV = white_read_voltage_mV,
|
||||
.read_current_mA = unused_read_current,
|
||||
.set_fan_enabled = uno_set_fan_enabled,
|
||||
.set_ir_power = uno_set_ir_power,
|
||||
.set_siren = unused_set_siren,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// /////////// //
|
||||
// White Panda //
|
||||
// /////////// //
|
||||
// ///////////////////// //
|
||||
// White Panda (STM32F4) //
|
||||
// ///////////////////// //
|
||||
|
||||
void white_enable_can_transceiver(uint8_t transceiver, bool enabled) {
|
||||
switch (transceiver){
|
||||
|
@ -66,66 +66,32 @@ void white_set_usb_power_mode(uint8_t mode){
|
|||
}
|
||||
|
||||
void white_set_can_mode(uint8_t mode){
|
||||
switch (mode) {
|
||||
case CAN_MODE_NORMAL:
|
||||
// B12,B13: disable GMLAN mode
|
||||
set_gpio_mode(GPIOB, 12, MODE_INPUT);
|
||||
set_gpio_mode(GPIOB, 13, MODE_INPUT);
|
||||
if (mode == CAN_MODE_NORMAL) {
|
||||
// B12,B13: disable GMLAN mode
|
||||
set_gpio_mode(GPIOB, 12, MODE_INPUT);
|
||||
set_gpio_mode(GPIOB, 13, MODE_INPUT);
|
||||
|
||||
// B3,B4: disable GMLAN mode
|
||||
set_gpio_mode(GPIOB, 3, MODE_INPUT);
|
||||
set_gpio_mode(GPIOB, 4, MODE_INPUT);
|
||||
// B3,B4: disable GMLAN mode
|
||||
set_gpio_mode(GPIOB, 3, MODE_INPUT);
|
||||
set_gpio_mode(GPIOB, 4, MODE_INPUT);
|
||||
|
||||
// B5,B6: normal CAN2 mode
|
||||
set_gpio_alternate(GPIOB, 5, GPIO_AF9_CAN2);
|
||||
set_gpio_alternate(GPIOB, 6, GPIO_AF9_CAN2);
|
||||
// B5,B6: normal CAN2 mode
|
||||
set_gpio_alternate(GPIOB, 5, GPIO_AF9_CAN2);
|
||||
set_gpio_alternate(GPIOB, 6, GPIO_AF9_CAN2);
|
||||
|
||||
// A8,A15: normal CAN3 mode
|
||||
set_gpio_alternate(GPIOA, 8, GPIO_AF11_CAN3);
|
||||
set_gpio_alternate(GPIOA, 15, GPIO_AF11_CAN3);
|
||||
break;
|
||||
case CAN_MODE_GMLAN_CAN2:
|
||||
// B5,B6: disable CAN2 mode
|
||||
set_gpio_mode(GPIOB, 5, MODE_INPUT);
|
||||
set_gpio_mode(GPIOB, 6, MODE_INPUT);
|
||||
|
||||
// B3,B4: disable GMLAN mode
|
||||
set_gpio_mode(GPIOB, 3, MODE_INPUT);
|
||||
set_gpio_mode(GPIOB, 4, MODE_INPUT);
|
||||
|
||||
// B12,B13: GMLAN mode
|
||||
set_gpio_alternate(GPIOB, 12, GPIO_AF9_CAN2);
|
||||
set_gpio_alternate(GPIOB, 13, GPIO_AF9_CAN2);
|
||||
|
||||
// A8,A15: normal CAN3 mode
|
||||
set_gpio_alternate(GPIOA, 8, GPIO_AF11_CAN3);
|
||||
set_gpio_alternate(GPIOA, 15, GPIO_AF11_CAN3);
|
||||
break;
|
||||
case CAN_MODE_GMLAN_CAN3:
|
||||
// A8,A15: disable CAN3 mode
|
||||
set_gpio_mode(GPIOA, 8, MODE_INPUT);
|
||||
set_gpio_mode(GPIOA, 15, MODE_INPUT);
|
||||
|
||||
// B12,B13: disable GMLAN mode
|
||||
set_gpio_mode(GPIOB, 12, MODE_INPUT);
|
||||
set_gpio_mode(GPIOB, 13, MODE_INPUT);
|
||||
|
||||
// B3,B4: GMLAN mode
|
||||
set_gpio_alternate(GPIOB, 3, GPIO_AF11_CAN3);
|
||||
set_gpio_alternate(GPIOB, 4, GPIO_AF11_CAN3);
|
||||
|
||||
// B5,B6: normal CAN2 mode
|
||||
set_gpio_alternate(GPIOB, 5, GPIO_AF9_CAN2);
|
||||
set_gpio_alternate(GPIOB, 6, GPIO_AF9_CAN2);
|
||||
break;
|
||||
default:
|
||||
print("Tried to set unsupported CAN mode: "); puth(mode); print("\n");
|
||||
break;
|
||||
// A8,A15: normal CAN3 mode
|
||||
set_gpio_alternate(GPIOA, 8, GPIO_AF11_CAN3);
|
||||
set_gpio_alternate(GPIOA, 15, GPIO_AF11_CAN3);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t white_read_current(void){
|
||||
return adc_get_raw(ADCCHAN_CURRENT);
|
||||
uint32_t white_read_voltage_mV(void){
|
||||
return adc_get_mV(12) * 11U;
|
||||
}
|
||||
|
||||
uint32_t white_read_current_mA(void){
|
||||
// This isn't in mA, but we're keeping it for backwards compatibility
|
||||
return adc_get_raw(13);
|
||||
}
|
||||
|
||||
bool white_check_ignition(void){
|
||||
|
@ -163,8 +129,8 @@ void white_grey_init(void) {
|
|||
0 1 high voltage wakeup
|
||||
1 1 33kbit (normal)
|
||||
*/
|
||||
set_gpio_output(GPIOB, 14, 1);
|
||||
set_gpio_output(GPIOB, 15, 1);
|
||||
set_gpio_output(GPIOB, 14, 0);
|
||||
set_gpio_output(GPIOB, 15, 0);
|
||||
|
||||
// B7: K-line enable
|
||||
set_gpio_output(GPIOB, 7, 1);
|
||||
|
@ -182,8 +148,6 @@ void white_grey_init(void) {
|
|||
set_gpio_alternate(GPIOC, 11, GPIO_AF7_USART3);
|
||||
set_gpio_pullup(GPIOC, 11, PULL_UP);
|
||||
|
||||
// Initialize RTC
|
||||
rtc_init();
|
||||
|
||||
// Enable CAN transceivers
|
||||
white_enable_can_transceivers(true);
|
||||
|
@ -197,10 +161,9 @@ void white_grey_init(void) {
|
|||
white_set_can_mode(CAN_MODE_NORMAL);
|
||||
|
||||
// Init usb power mode
|
||||
uint32_t voltage = adc_get_mV(ADCCHAN_VIN) * VIN_READOUT_DIVIDER;
|
||||
// Init in CDP mode only if panda is powered by 12V.
|
||||
// Otherwise a PC would not be able to flash a standalone panda
|
||||
if (voltage > 8000U) { // 8V threshold
|
||||
if (white_read_voltage_mV() > 8000U) { // 8V threshold
|
||||
white_set_usb_power_mode(USB_POWER_CDP);
|
||||
} else {
|
||||
white_set_usb_power_mode(USB_POWER_CLIENT);
|
||||
|
@ -217,17 +180,16 @@ void white_grey_init_bootloader(void) {
|
|||
set_gpio_output(GPIOC, 14, 0);
|
||||
}
|
||||
|
||||
const harness_configuration white_harness_config = {
|
||||
harness_configuration white_harness_config = {
|
||||
.has_harness = false
|
||||
};
|
||||
|
||||
const board board_white = {
|
||||
board board_white = {
|
||||
.set_bootkick = unused_set_bootkick,
|
||||
.harness_config = &white_harness_config,
|
||||
.has_obd = false,
|
||||
.has_spi = false,
|
||||
.has_canfd = false,
|
||||
.has_rtc_battery = false,
|
||||
.fan_max_rpm = 0U,
|
||||
.avdd_mV = 3300U,
|
||||
.fan_stall_recovery = false,
|
||||
|
@ -239,7 +201,8 @@ const board board_white = {
|
|||
.set_led = white_set_led,
|
||||
.set_can_mode = white_set_can_mode,
|
||||
.check_ignition = white_check_ignition,
|
||||
.read_current = white_read_current,
|
||||
.read_voltage_mV = white_read_voltage_mV,
|
||||
.read_current_mA = white_read_current_mA,
|
||||
.set_fan_enabled = unused_set_fan_enabled,
|
||||
.set_ir_power = unused_set_ir_power,
|
||||
.set_siren = unused_set_siren,
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "obj/gitversion.h"
|
||||
#include "flasher.h"
|
||||
|
||||
// cppcheck-suppress unusedFunction ; used in headers not included in cppcheck
|
||||
void __initialize_hardware_early(void) {
|
||||
early_initialization();
|
||||
}
|
||||
|
|
|
@ -6,8 +6,6 @@ void puth4(uint8_t i){ UNUSED(i); }
|
|||
void hexdump(const void *a, int l){ UNUSED(a); UNUSED(l); }
|
||||
typedef struct board board;
|
||||
typedef struct harness_configuration harness_configuration;
|
||||
// No CAN support on bootloader
|
||||
void can_flip_buses(uint8_t bus1, uint8_t bus2){UNUSED(bus1); UNUSED(bus2);}
|
||||
void pwm_init(TIM_TypeDef *TIM, uint8_t channel);
|
||||
void pwm_set(TIM_TypeDef *TIM, uint8_t channel, uint8_t percentage);
|
||||
// No UART support in bootloader
|
||||
|
@ -17,4 +15,4 @@ void uart_init(uart_ring *q, int baud) { UNUSED(q); UNUSED(baud); }
|
|||
|
||||
// ********************* Globals **********************
|
||||
uint8_t hw_type = 0;
|
||||
const board *current_board;
|
||||
board *current_board;
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
#pragma once
|
||||
|
||||
const uint8_t PANDA_CAN_CNT = 3U;
|
||||
const uint8_t PANDA_BUS_CNT = 4U;
|
||||
const uint8_t PANDA_BUS_CNT = 3U;
|
||||
|
||||
// bump this when changing the CAN packet
|
||||
#define CAN_PACKET_VERSION 4
|
||||
|
||||
#define CANPACKET_HEAD_SIZE 6U
|
||||
|
||||
#if !defined(STM32F4) && !defined(STM32F2)
|
||||
#if !defined(STM32F4)
|
||||
#define CANFD
|
||||
#define CANPACKET_DATA_SIZE_MAX 64U
|
||||
#else
|
||||
|
|
|
@ -11,13 +11,10 @@
|
|||
//#define DEBUG_FAN
|
||||
|
||||
#define CAN_INIT_TIMEOUT_MS 500U
|
||||
#define DEEPSLEEP_WAKEUP_DELAY 3U
|
||||
#define USBPACKET_MAX_SIZE 0x40U
|
||||
#define MAX_CAN_MSGS_PER_USB_BULK_TRANSFER 51U
|
||||
#define MAX_CAN_MSGS_PER_SPI_BULK_TRANSFER 170U
|
||||
|
||||
#define VIN_READOUT_DIVIDER 11U
|
||||
|
||||
// USB definitions
|
||||
#define USB_VID 0xBBAAU
|
||||
|
||||
|
@ -38,8 +35,8 @@
|
|||
// platform includes
|
||||
#ifdef STM32H7
|
||||
#include "stm32h7/stm32h7_config.h"
|
||||
#elif defined(STM32F2) || defined(STM32F4)
|
||||
#include "stm32fx/stm32fx_config.h"
|
||||
#elif defined(STM32F4)
|
||||
#include "stm32f4/stm32f4_config.h"
|
||||
#else
|
||||
// TODO: uncomment this, cppcheck complains
|
||||
// building for tests
|
||||
|
|
|
@ -48,7 +48,7 @@ void update_can_health_pkt(uint8_t can_number, uint32_t ir_reg) {
|
|||
can_health[can_number].total_error_cnt += 1U;
|
||||
|
||||
// RX message lost due to FIFO overrun
|
||||
if ((CANx->RF0R & (CAN_RF0R_FOVR0)) != 0) {
|
||||
if ((CANx->RF0R & (CAN_RF0R_FOVR0)) != 0U) {
|
||||
can_health[can_number].total_rx_lost_cnt += 1U;
|
||||
CANx->RF0R &= ~(CAN_RF0R_FOVR0);
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ void process_can(uint8_t can_number) {
|
|||
|
||||
// check for empty mailbox
|
||||
CANPacket_t to_send;
|
||||
if ((CANx->TSR & (CAN_TSR_TERR0 | CAN_TSR_ALST0)) != 0) { // last TX failed due to error arbitration lost
|
||||
if ((CANx->TSR & (CAN_TSR_TERR0 | CAN_TSR_ALST0)) != 0U) { // last TX failed due to error arbitration lost
|
||||
can_health[can_number].total_tx_lost_cnt += 1U;
|
||||
CANx->TSR |= (CAN_TSR_TERR0 | CAN_TSR_ALST0);
|
||||
}
|
||||
|
@ -129,7 +129,7 @@ void can_rx(uint8_t can_number) {
|
|||
CAN_TypeDef *CANx = CANIF_FROM_CAN_NUM(can_number);
|
||||
uint8_t bus_number = BUS_NUM_FROM_CAN_NUM(can_number);
|
||||
|
||||
while ((CANx->RF0R & CAN_RF0R_FMP0) != 0) {
|
||||
while ((CANx->RF0R & CAN_RF0R_FMP0) != 0U) {
|
||||
can_health[can_number].total_rx_cnt += 1U;
|
||||
|
||||
// can is live
|
||||
|
|
|
@ -20,7 +20,6 @@ uint32_t safety_tx_blocked = 0;
|
|||
uint32_t safety_rx_invalid = 0;
|
||||
uint32_t tx_buffer_overflow = 0;
|
||||
uint32_t rx_buffer_overflow = 0;
|
||||
uint32_t gmlan_send_errs = 0;
|
||||
|
||||
can_health_t can_health[] = {{0}, {0}, {0}};
|
||||
|
||||
|
@ -28,8 +27,8 @@ extern int can_live;
|
|||
extern int pending_can_live;
|
||||
|
||||
// must reinit after changing these
|
||||
extern int can_loopback;
|
||||
extern int can_silent;
|
||||
extern bool can_loopback;
|
||||
|
||||
// Ignition detected from CAN meessages
|
||||
bool ignition_can = false;
|
||||
|
@ -40,8 +39,8 @@ uint32_t ignition_can_cnt = 0U;
|
|||
|
||||
int can_live = 0;
|
||||
int pending_can_live = 0;
|
||||
int can_loopback = 0;
|
||||
int can_silent = ALL_CAN_SILENT;
|
||||
bool can_loopback = false;
|
||||
|
||||
// ******************* functions prototypes *********************
|
||||
bool can_init(uint8_t can_number);
|
||||
|
@ -54,7 +53,6 @@ void process_can(uint8_t can_number);
|
|||
|
||||
#define CAN_RX_BUFFER_SIZE 4096U
|
||||
#define CAN_TX_BUFFER_SIZE 416U
|
||||
#define GMLAN_TX_BUFFER_SIZE 416U
|
||||
|
||||
#ifdef STM32H7
|
||||
// ITCM RAM and DTCM RAM are the fastest for Cortex-M7 core access
|
||||
|
@ -67,10 +65,10 @@ can_buffer(tx1_q, CAN_TX_BUFFER_SIZE)
|
|||
can_buffer(tx2_q, CAN_TX_BUFFER_SIZE)
|
||||
#endif
|
||||
can_buffer(tx3_q, CAN_TX_BUFFER_SIZE)
|
||||
can_buffer(txgmlan_q, GMLAN_TX_BUFFER_SIZE)
|
||||
|
||||
// FIXME:
|
||||
// cppcheck-suppress misra-c2012-9.3
|
||||
can_ring *can_queues[] = {&can_tx1_q, &can_tx2_q, &can_tx3_q, &can_txgmlan_q};
|
||||
can_ring *can_queues[] = {&can_tx1_q, &can_tx2_q, &can_tx3_q};
|
||||
|
||||
// helpers
|
||||
#define WORD_TO_BYTE_ARRAY(dst8, src32) 0[dst8] = ((src32) & 0xFFU); 1[dst8] = (((src32) >> 8U) & 0xFFU); 2[dst8] = (((src32) >> 16U) & 0xFFU); 3[dst8] = (((src32) >> 24U) & 0xFFU)
|
||||
|
@ -122,8 +120,6 @@ bool can_push(can_ring *q, const CANPacket_t *elem) {
|
|||
print("can_tx2_q");
|
||||
} else if (q == &can_tx3_q) {
|
||||
print("can_tx3_q");
|
||||
} else if (q == &can_txgmlan_q) {
|
||||
print("can_txgmlan_q");
|
||||
} else {
|
||||
print("unknown");
|
||||
}
|
||||
|
@ -157,7 +153,7 @@ void can_clear(can_ring *q) {
|
|||
}
|
||||
|
||||
// assign CAN numbering
|
||||
// bus num: Can bus number on ODB connector. Sent to/from USB
|
||||
// bus num: CAN Bus numbers in panda, sent to/from USB
|
||||
// Min: 0; Max: 127; Bit 7 marks message as receipt (bus 129 is receipt for but 1)
|
||||
// cans: Look up MCU can interface from bus number
|
||||
// can number: numeric lookup for MCU CAN interfaces (0 = CAN1, 1 = CAN2, etc);
|
||||
|
@ -179,22 +175,20 @@ bus_config_t bus_config[] = {
|
|||
#define CAN_NUM_FROM_BUS_NUM(num) (bus_config[num].can_num_lookup)
|
||||
|
||||
void can_init_all(void) {
|
||||
bool ret = true;
|
||||
for (uint8_t i=0U; i < PANDA_CAN_CNT; i++) {
|
||||
if (!current_board->has_canfd) {
|
||||
bus_config[i].can_data_speed = 0U;
|
||||
}
|
||||
can_clear(can_queues[i]);
|
||||
ret &= can_init(i);
|
||||
(void)can_init(i);
|
||||
}
|
||||
UNUSED(ret);
|
||||
}
|
||||
|
||||
void can_flip_buses(uint8_t bus1, uint8_t bus2){
|
||||
bus_config[bus1].bus_lookup = bus2;
|
||||
bus_config[bus2].bus_lookup = bus1;
|
||||
bus_config[bus1].can_num_lookup = bus2;
|
||||
bus_config[bus2].can_num_lookup = bus1;
|
||||
void can_set_orientation(bool flipped) {
|
||||
bus_config[0].bus_lookup = flipped ? 2U : 0U;
|
||||
bus_config[0].can_num_lookup = flipped ? 2U : 0U;
|
||||
bus_config[2].bus_lookup = flipped ? 0U : 2U;
|
||||
bus_config[2].can_num_lookup = flipped ? 0U : 2U;
|
||||
}
|
||||
|
||||
void can_set_forwarding(uint8_t from, uint8_t to) {
|
||||
|
@ -234,8 +228,7 @@ bool can_tx_check_min_slots_free(uint32_t min) {
|
|||
return
|
||||
(can_slots_empty(&can_tx1_q) >= min) &&
|
||||
(can_slots_empty(&can_tx2_q) >= min) &&
|
||||
(can_slots_empty(&can_tx3_q) >= min) &&
|
||||
(can_slots_empty(&can_txgmlan_q) >= min);
|
||||
(can_slots_empty(&can_tx3_q) >= min);
|
||||
}
|
||||
|
||||
uint8_t calculate_checksum(const uint8_t *dat, uint32_t len) {
|
||||
|
@ -259,12 +252,8 @@ void can_send(CANPacket_t *to_push, uint8_t bus_number, bool skip_tx_hook) {
|
|||
if (skip_tx_hook || safety_tx_hook(to_push) != 0) {
|
||||
if (bus_number < PANDA_BUS_CNT) {
|
||||
// add CAN packet to send queue
|
||||
if ((bus_number == 3U) && (bus_config[3].can_num_lookup == 0xFFU)) {
|
||||
gmlan_send_errs += bitbang_gmlan(to_push) ? 0U : 1U;
|
||||
} else {
|
||||
tx_buffer_overflow += can_push(can_queues[bus_number], to_push) ? 0U : 1U;
|
||||
process_can(CAN_NUM_FROM_BUS_NUM(bus_number));
|
||||
}
|
||||
tx_buffer_overflow += can_push(can_queues[bus_number], to_push) ? 0U : 1U;
|
||||
process_can(CAN_NUM_FROM_BUS_NUM(bus_number));
|
||||
}
|
||||
} else {
|
||||
safety_tx_blocked += 1U;
|
||||
|
@ -277,10 +266,10 @@ void can_send(CANPacket_t *to_push, uint8_t bus_number, bool skip_tx_hook) {
|
|||
}
|
||||
}
|
||||
|
||||
bool is_speed_valid(uint32_t speed, const uint32_t *speeds, uint8_t len) {
|
||||
bool is_speed_valid(uint32_t speed, const uint32_t *all_speeds, uint8_t len) {
|
||||
bool ret = false;
|
||||
for (uint8_t i = 0U; i < len; i++) {
|
||||
if (speeds[i] == speed) {
|
||||
if (all_speeds[i] == speed) {
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,8 +26,8 @@ void clock_source_init(void) {
|
|||
set_gpio_alternate(GPIOB, 15, GPIO_AF1_TIM1);
|
||||
|
||||
// Set PWM mode
|
||||
register_set(&(TIM1->CCMR1), (0b110 << TIM_CCMR1_OC2M_Pos), 0xFFFFU);
|
||||
register_set(&(TIM1->CCMR2), (0b110 << TIM_CCMR2_OC3M_Pos), 0xFFFFU);
|
||||
register_set(&(TIM1->CCMR1), (0b110UL << TIM_CCMR1_OC2M_Pos), 0xFFFFU);
|
||||
register_set(&(TIM1->CCMR2), (0b110UL << TIM_CCMR2_OC3M_Pos), 0xFFFFU);
|
||||
|
||||
// Enable output
|
||||
register_set(&(TIM1->BDTR), TIM_BDTR_MOE, 0xFFFFU);
|
||||
|
|
|
@ -59,13 +59,13 @@ void fake_siren_init(void) {
|
|||
register_set(&DMA1_Stream1->PAR, (uint32_t) &(DAC1->DHR8R1), 0xFFFFFFFFU);
|
||||
DMA1_Stream1->NDTR = sizeof(fake_siren_lut);
|
||||
register_set(&DMA1_Stream1->FCR, 0U, 0x00000083U);
|
||||
DMA1_Stream1->CR = (0b11 << DMA_SxCR_PL_Pos);
|
||||
DMA1_Stream1->CR |= DMA_SxCR_MINC | DMA_SxCR_CIRC | (1 << DMA_SxCR_DIR_Pos);
|
||||
DMA1_Stream1->CR = (0b11UL << DMA_SxCR_PL_Pos);
|
||||
DMA1_Stream1->CR |= DMA_SxCR_MINC | DMA_SxCR_CIRC | (1U << DMA_SxCR_DIR_Pos);
|
||||
|
||||
// Init trigger timer (around 2.5kHz)
|
||||
register_set(&TIM7->PSC, 0U, 0xFFFFU);
|
||||
register_set(&TIM7->ARR, 133U, 0xFFFFU);
|
||||
register_set(&TIM7->CR2, (0b10 << TIM_CR2_MMS_Pos), TIM_CR2_MMS_Msk);
|
||||
register_set(&TIM7->CR2, (0b10U << TIM_CR2_MMS_Pos), TIM_CR2_MMS_Msk);
|
||||
register_set(&TIM7->CR1, TIM_CR1_ARPE | TIM_CR1_URS, 0x088EU);
|
||||
TIM7->SR = 0U;
|
||||
TIM7->CR1 |= TIM_CR1_CEN;
|
||||
|
|
|
@ -67,14 +67,14 @@ void update_can_health_pkt(uint8_t can_number, uint32_t ir_reg) {
|
|||
FDCANx->IR |= (FDCAN_IR_PED | FDCAN_IR_PEA | FDCAN_IR_EP | FDCAN_IR_BO | FDCAN_IR_RF0L);
|
||||
can_health[can_number].total_error_cnt += 1U;
|
||||
// Check for RX FIFO overflow
|
||||
if ((ir_reg & (FDCAN_IR_RF0L)) != 0) {
|
||||
if ((ir_reg & (FDCAN_IR_RF0L)) != 0U) {
|
||||
can_health[can_number].total_rx_lost_cnt += 1U;
|
||||
}
|
||||
// Cases:
|
||||
// 1. while multiplexing between buses 1 and 3 we are getting ACK errors that overwhelm CAN core, by resetting it recovers faster
|
||||
// 2. H7 gets stuck in bus off recovery state indefinitely
|
||||
if ((((can_health[can_number].last_error == CAN_ACK_ERROR) || (can_health[can_number].last_data_error == CAN_ACK_ERROR)) && (can_health[can_number].transmit_error_cnt > 127U)) ||
|
||||
((ir_reg & FDCAN_IR_BO) != 0)) {
|
||||
((ir_reg & FDCAN_IR_BO) != 0U)) {
|
||||
can_health[can_number].can_core_reset_cnt += 1U;
|
||||
can_health[can_number].total_tx_lost_cnt += (FDCAN_TX_FIFO_EL_CNT - (FDCANx->TXFQS & FDCAN_TXFQS_TFFL)); // TX FIFO msgs will be lost after reset
|
||||
llcan_clear_send(FDCANx);
|
||||
|
@ -93,7 +93,7 @@ void process_can(uint8_t can_number) {
|
|||
|
||||
FDCANx->IR |= FDCAN_IR_TFE; // Clear Tx FIFO Empty flag
|
||||
|
||||
if ((FDCANx->TXFQS & FDCAN_TXFQS_TFQF) == 0) {
|
||||
if ((FDCANx->TXFQS & FDCAN_TXFQS_TFQF) == 0U) {
|
||||
CANPacket_t to_send;
|
||||
if (can_pop(can_queues[bus_number], &to_send)) {
|
||||
if (can_check_checksum(&to_send)) {
|
||||
|
@ -101,7 +101,7 @@ void process_can(uint8_t can_number) {
|
|||
|
||||
uint32_t TxFIFOSA = FDCAN_START_ADDRESS + (can_number * FDCAN_OFFSET) + (FDCAN_RX_FIFO_0_EL_CNT * FDCAN_RX_FIFO_0_EL_SIZE);
|
||||
// get the index of the next TX FIFO element (0 to FDCAN_TX_FIFO_EL_CNT - 1)
|
||||
uint32_t tx_index = (FDCANx->TXFQS >> FDCAN_TXFQS_TFQPI_Pos) & 0x1F;
|
||||
uint32_t tx_index = (FDCANx->TXFQS >> FDCAN_TXFQS_TFQPI_Pos) & 0x1FU;
|
||||
// only send if we have received a packet
|
||||
canfd_fifo *fifo;
|
||||
fifo = (canfd_fifo *)(TxFIFOSA + (tx_index * FDCAN_TX_FIFO_EL_SIZE));
|
||||
|
@ -126,7 +126,7 @@ void process_can(uint8_t can_number) {
|
|||
to_push.rejected = 0U;
|
||||
to_push.extended = to_send.extended;
|
||||
to_push.addr = to_send.addr;
|
||||
to_push.bus = to_send.bus;
|
||||
to_push.bus = bus_number;
|
||||
to_push.data_len_code = to_send.data_len_code;
|
||||
(void)memcpy(to_push.data, to_send.data, dlc_to_len[to_push.data_len_code]);
|
||||
can_set_checksum(&to_push);
|
||||
|
@ -153,14 +153,14 @@ void can_rx(uint8_t can_number) {
|
|||
|
||||
// Clear all new messages from Rx FIFO 0
|
||||
FDCANx->IR |= FDCAN_IR_RF0N;
|
||||
while((FDCANx->RXF0S & FDCAN_RXF0S_F0FL) != 0) {
|
||||
while((FDCANx->RXF0S & FDCAN_RXF0S_F0FL) != 0U) {
|
||||
can_health[can_number].total_rx_cnt += 1U;
|
||||
|
||||
// can is live
|
||||
pending_can_live = 1;
|
||||
|
||||
// get the index of the next RX FIFO element (0 to FDCAN_RX_FIFO_0_EL_CNT - 1)
|
||||
uint32_t rx_fifo_idx = (uint8_t)((FDCANx->RXF0S >> FDCAN_RXF0S_F0GI_Pos) & 0x3F);
|
||||
uint32_t rx_fifo_idx = (uint8_t)((FDCANx->RXF0S >> FDCAN_RXF0S_F0GI_Pos) & 0x3FU);
|
||||
|
||||
// Recommended to offset get index by at least +1 if RX FIFO is in overwrite mode and full (datasheet)
|
||||
if((FDCANx->RXF0S & FDCAN_RXF0S_F0F) == FDCAN_RXF0S_F0F) {
|
||||
|
@ -232,7 +232,7 @@ void can_rx(uint8_t can_number) {
|
|||
}
|
||||
|
||||
// Error handling
|
||||
if ((ir_reg & (FDCAN_IR_PED | FDCAN_IR_PEA | FDCAN_IR_EP | FDCAN_IR_BO | FDCAN_IR_RF0L)) != 0) {
|
||||
if ((ir_reg & (FDCAN_IR_PED | FDCAN_IR_PEA | FDCAN_IR_EP | FDCAN_IR_BO | FDCAN_IR_RF0L)) != 0U) {
|
||||
update_can_health_pkt(can_number, ir_reg);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,296 +0,0 @@
|
|||
#define GMLAN_TICKS_PER_SECOND 33300 //1sec @ 33.3kbps
|
||||
#define GMLAN_TICKS_PER_TIMEOUT_TICKLE 500 //15ms @ 33.3kbps
|
||||
#define GMLAN_HIGH 0 //0 is high on bus (dominant)
|
||||
#define GMLAN_LOW 1 //1 is low on bus
|
||||
|
||||
#define DISABLED -1
|
||||
#define BITBANG 0
|
||||
#define GPIO_SWITCH 1
|
||||
|
||||
#define MAX_BITS_CAN_PACKET (200)
|
||||
|
||||
int gmlan_alt_mode = DISABLED;
|
||||
|
||||
// returns out_len
|
||||
int do_bitstuff(char *out, const char *in, int in_len) {
|
||||
int last_bit = -1;
|
||||
int bit_cnt = 0;
|
||||
int j = 0;
|
||||
for (int i = 0; i < in_len; i++) {
|
||||
char bit = in[i];
|
||||
out[j] = bit;
|
||||
j++;
|
||||
|
||||
// do the stuffing
|
||||
if (bit == (char)last_bit) {
|
||||
bit_cnt++;
|
||||
if (bit_cnt == 5) {
|
||||
// 5 in a row the same, do stuff
|
||||
last_bit = !bit;
|
||||
out[j] = last_bit;
|
||||
j++;
|
||||
bit_cnt = 1;
|
||||
}
|
||||
} else {
|
||||
// this is a new bit
|
||||
last_bit = bit;
|
||||
bit_cnt = 1;
|
||||
}
|
||||
}
|
||||
return j;
|
||||
}
|
||||
|
||||
int append_crc(char *in, int in_len) {
|
||||
unsigned int crc = 0;
|
||||
for (int i = 0; i < in_len; i++) {
|
||||
crc <<= 1;
|
||||
if (((unsigned int)(in[i]) ^ ((crc >> 15) & 1U)) != 0U) {
|
||||
crc = crc ^ 0x4599U;
|
||||
}
|
||||
crc &= 0x7fffU;
|
||||
}
|
||||
int in_len_copy = in_len;
|
||||
for (int i = 14; i >= 0; i--) {
|
||||
in[in_len_copy] = (crc >> (unsigned int)(i)) & 1U;
|
||||
in_len_copy++;
|
||||
}
|
||||
return in_len_copy;
|
||||
}
|
||||
|
||||
int append_bits(char *in, int in_len, const char *app, int app_len) {
|
||||
int in_len_copy = in_len;
|
||||
for (int i = 0; i < app_len; i++) {
|
||||
in[in_len_copy] = app[i];
|
||||
in_len_copy++;
|
||||
}
|
||||
return in_len_copy;
|
||||
}
|
||||
|
||||
int append_int(char *in, int in_len, int val, int val_len) {
|
||||
int in_len_copy = in_len;
|
||||
for (int i = val_len - 1; i >= 0; i--) {
|
||||
in[in_len_copy] = ((unsigned int)(val) & (1U << (unsigned int)(i))) != 0U;
|
||||
in_len_copy++;
|
||||
}
|
||||
return in_len_copy;
|
||||
}
|
||||
|
||||
int get_bit_message(char *out, const CANPacket_t *to_bang) {
|
||||
char pkt[MAX_BITS_CAN_PACKET];
|
||||
char footer[] = {
|
||||
1, // CRC delimiter
|
||||
1, // ACK
|
||||
1, // ACK delimiter
|
||||
1,1,1,1,1,1,1, // EOF
|
||||
1,1,1, // IFS
|
||||
};
|
||||
|
||||
int len = 0;
|
||||
|
||||
// test packet
|
||||
int dlc_len = GET_LEN(to_bang);
|
||||
len = append_int(pkt, len, 0, 1); // Start-of-frame
|
||||
|
||||
if (to_bang->extended != 0U) {
|
||||
// extended identifier
|
||||
len = append_int(pkt, len, GET_ADDR(to_bang) >> 18, 11); // Identifier
|
||||
len = append_int(pkt, len, 3, 2); // SRR+IDE
|
||||
len = append_int(pkt, len, (GET_ADDR(to_bang)) & ((1UL << 18) - 1U), 18); // Identifier
|
||||
len = append_int(pkt, len, 0, 3); // RTR+r1+r0
|
||||
} else {
|
||||
// standard identifier
|
||||
len = append_int(pkt, len, GET_ADDR(to_bang), 11); // Identifier
|
||||
len = append_int(pkt, len, 0, 3); // RTR+IDE+reserved
|
||||
}
|
||||
|
||||
len = append_int(pkt, len, dlc_len, 4); // Data length code
|
||||
|
||||
// append data
|
||||
for (int i = 0; i < dlc_len; i++) {
|
||||
len = append_int(pkt, len, to_bang->data[i], 8);
|
||||
}
|
||||
|
||||
// append crc
|
||||
len = append_crc(pkt, len);
|
||||
|
||||
// do bitstuffing
|
||||
len = do_bitstuff(out, pkt, len);
|
||||
|
||||
// append footer
|
||||
len = append_bits(out, len, footer, sizeof(footer));
|
||||
return len;
|
||||
}
|
||||
|
||||
void TIM12_IRQ_Handler(void);
|
||||
|
||||
void setup_timer(void) {
|
||||
// register interrupt
|
||||
REGISTER_INTERRUPT(TIM8_BRK_TIM12_IRQn, TIM12_IRQ_Handler, 40000U, FAULT_INTERRUPT_RATE_GMLAN)
|
||||
|
||||
// setup
|
||||
register_set(&(TIM12->PSC), (APB1_TIMER_FREQ-1U), 0xFFFFU); // Tick on 1 us
|
||||
register_set(&(TIM12->CR1), TIM_CR1_CEN, 0x3FU); // Enable
|
||||
register_set(&(TIM12->ARR), (30U-1U), 0xFFFFU); // 33.3 kbps
|
||||
|
||||
// in case it's disabled
|
||||
NVIC_EnableIRQ(TIM8_BRK_TIM12_IRQn);
|
||||
|
||||
// run the interrupt
|
||||
register_set(&(TIM12->DIER), TIM_DIER_UIE, 0x5F5FU); // Update interrupt
|
||||
TIM12->SR = 0;
|
||||
}
|
||||
|
||||
int gmlan_timeout_counter = GMLAN_TICKS_PER_TIMEOUT_TICKLE; //GMLAN transceiver times out every 17ms held high; tickle every 15ms
|
||||
int can_timeout_counter = GMLAN_TICKS_PER_SECOND; //1 second
|
||||
|
||||
int inverted_bit_to_send = GMLAN_HIGH;
|
||||
int gmlan_switch_below_timeout = -1;
|
||||
int gmlan_switch_timeout_enable = 0;
|
||||
|
||||
void gmlan_switch_init(int timeout_enable) {
|
||||
gmlan_switch_timeout_enable = timeout_enable;
|
||||
gmlan_alt_mode = GPIO_SWITCH;
|
||||
gmlan_switch_below_timeout = 1;
|
||||
set_gpio_mode(GPIOB, 13, MODE_OUTPUT);
|
||||
|
||||
setup_timer();
|
||||
|
||||
inverted_bit_to_send = GMLAN_LOW; //We got initialized, set the output low
|
||||
}
|
||||
|
||||
void set_gmlan_digital_output(int to_set) {
|
||||
inverted_bit_to_send = to_set;
|
||||
/*
|
||||
print("Writing ");
|
||||
puth(inverted_bit_to_send);
|
||||
print("\n");
|
||||
*/
|
||||
}
|
||||
|
||||
void reset_gmlan_switch_timeout(void) {
|
||||
can_timeout_counter = GMLAN_TICKS_PER_SECOND;
|
||||
gmlan_switch_below_timeout = 1;
|
||||
gmlan_alt_mode = GPIO_SWITCH;
|
||||
}
|
||||
|
||||
void set_bitbanged_gmlan(int val) {
|
||||
if (val != 0) {
|
||||
register_set_bits(&(GPIOB->ODR), (1UL << 13));
|
||||
} else {
|
||||
register_clear_bits(&(GPIOB->ODR), (1UL << 13));
|
||||
}
|
||||
}
|
||||
|
||||
char pkt_stuffed[MAX_BITS_CAN_PACKET];
|
||||
int gmlan_sending = -1;
|
||||
int gmlan_sendmax = -1;
|
||||
bool gmlan_send_ok = true;
|
||||
|
||||
int gmlan_silent_count = 0;
|
||||
int gmlan_fail_count = 0;
|
||||
#define REQUIRED_SILENT_TIME 10
|
||||
#define MAX_FAIL_COUNT 10
|
||||
|
||||
void TIM12_IRQ_Handler(void) {
|
||||
if (gmlan_alt_mode == BITBANG) {
|
||||
if ((TIM12->SR & TIM_SR_UIF) && (gmlan_sendmax != -1)) {
|
||||
int read = get_gpio_input(GPIOB, 12);
|
||||
if (gmlan_silent_count < REQUIRED_SILENT_TIME) {
|
||||
if (read == 0) {
|
||||
gmlan_silent_count = 0;
|
||||
} else {
|
||||
gmlan_silent_count++;
|
||||
}
|
||||
} else {
|
||||
bool retry = 0;
|
||||
// in send loop
|
||||
if ((gmlan_sending > 0) && // not first bit
|
||||
((read == 0) && (pkt_stuffed[gmlan_sending-1] == (char)1)) && // bus wrongly dominant
|
||||
(gmlan_sending != (gmlan_sendmax - 11))) { //not ack bit
|
||||
print("GMLAN ERR: bus driven at ");
|
||||
puth(gmlan_sending);
|
||||
print("\n");
|
||||
retry = 1;
|
||||
} else if ((read == 1) && (gmlan_sending == (gmlan_sendmax - 11))) { // recessive during ACK
|
||||
print("GMLAN ERR: didn't recv ACK\n");
|
||||
retry = 1;
|
||||
} else {
|
||||
// do not retry
|
||||
}
|
||||
if (retry) {
|
||||
// reset sender (retry after 7 silent)
|
||||
set_bitbanged_gmlan(1); // recessive
|
||||
gmlan_silent_count = 0;
|
||||
gmlan_sending = 0;
|
||||
gmlan_fail_count++;
|
||||
if (gmlan_fail_count == MAX_FAIL_COUNT) {
|
||||
print("GMLAN ERR: giving up send\n");
|
||||
gmlan_send_ok = false;
|
||||
}
|
||||
} else {
|
||||
set_bitbanged_gmlan(pkt_stuffed[gmlan_sending]);
|
||||
gmlan_sending++;
|
||||
}
|
||||
}
|
||||
if ((gmlan_sending == gmlan_sendmax) || (gmlan_fail_count == MAX_FAIL_COUNT)) {
|
||||
set_bitbanged_gmlan(1); // recessive
|
||||
set_gpio_mode(GPIOB, 13, MODE_INPUT);
|
||||
register_clear_bits(&(TIM12->DIER), TIM_DIER_UIE); // No update interrupt
|
||||
register_set(&(TIM12->CR1), 0U, 0x3FU); // Disable timer
|
||||
gmlan_sendmax = -1; // exit
|
||||
}
|
||||
}
|
||||
} else if (gmlan_alt_mode == GPIO_SWITCH) {
|
||||
if ((TIM12->SR & TIM_SR_UIF) && (gmlan_switch_below_timeout != -1)) {
|
||||
if ((can_timeout_counter == 0) && gmlan_switch_timeout_enable) {
|
||||
//it has been more than 1 second since timeout was reset; disable timer and restore the GMLAN output
|
||||
set_gpio_output(GPIOB, 13, GMLAN_LOW);
|
||||
gmlan_switch_below_timeout = -1;
|
||||
gmlan_timeout_counter = GMLAN_TICKS_PER_TIMEOUT_TICKLE;
|
||||
gmlan_alt_mode = DISABLED;
|
||||
}
|
||||
else {
|
||||
can_timeout_counter--;
|
||||
if (gmlan_timeout_counter == 0) {
|
||||
//Send a 1 (bus low) every 15ms to reset the GMLAN transceivers timeout
|
||||
gmlan_timeout_counter = GMLAN_TICKS_PER_TIMEOUT_TICKLE;
|
||||
set_gpio_output(GPIOB, 13, GMLAN_LOW);
|
||||
}
|
||||
else {
|
||||
set_gpio_output(GPIOB, 13, inverted_bit_to_send);
|
||||
gmlan_timeout_counter--;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Invalid GMLAN mode. Do not put a print statement here, way too fast to keep up with
|
||||
}
|
||||
TIM12->SR = 0;
|
||||
}
|
||||
|
||||
bool bitbang_gmlan(const CANPacket_t *to_bang) {
|
||||
gmlan_send_ok = true;
|
||||
gmlan_alt_mode = BITBANG;
|
||||
|
||||
#ifdef HW_TYPE_DOS
|
||||
if (hw_type == HW_TYPE_DOS) {
|
||||
if (gmlan_sendmax == -1) {
|
||||
int len = get_bit_message(pkt_stuffed, to_bang);
|
||||
gmlan_fail_count = 0;
|
||||
gmlan_silent_count = 0;
|
||||
gmlan_sending = 0;
|
||||
gmlan_sendmax = len;
|
||||
// setup for bitbang loop
|
||||
set_bitbanged_gmlan(1); // recessive
|
||||
set_gpio_mode(GPIOB, 13, MODE_OUTPUT);
|
||||
|
||||
// 33kbps
|
||||
setup_timer();
|
||||
}
|
||||
}
|
||||
#else
|
||||
UNUSED(to_bang);
|
||||
#endif
|
||||
|
||||
return gmlan_send_ok;
|
||||
}
|
|
@ -11,7 +11,7 @@
|
|||
#define OUTPUT_TYPE_OPEN_DRAIN 1U
|
||||
|
||||
typedef struct {
|
||||
GPIO_TypeDef *bank;
|
||||
GPIO_TypeDef * const bank;
|
||||
uint8_t pin;
|
||||
} gpio_t;
|
||||
|
||||
|
@ -68,13 +68,13 @@ int get_gpio_input(const GPIO_TypeDef *GPIO, unsigned int pin) {
|
|||
return (GPIO->IDR & (1UL << pin)) == (1UL << pin);
|
||||
}
|
||||
|
||||
void gpio_set_all_output(const gpio_t *pins, uint8_t num_pins, bool enabled) {
|
||||
void gpio_set_all_output(gpio_t *pins, uint8_t num_pins, bool enabled) {
|
||||
for (uint8_t i = 0; i < num_pins; i++) {
|
||||
set_gpio_output(pins[i].bank, pins[i].pin, enabled);
|
||||
}
|
||||
}
|
||||
|
||||
void gpio_set_bitmask(const gpio_t *pins, uint8_t num_pins, uint32_t bitmask) {
|
||||
void gpio_set_bitmask(gpio_t *pins, uint8_t num_pins, uint32_t bitmask) {
|
||||
for (uint8_t i = 0; i < num_pins; i++) {
|
||||
set_gpio_output(pins[i].bank, pins[i].pin, (bitmask >> i) & 1U);
|
||||
}
|
||||
|
|
|
@ -13,16 +13,16 @@ struct harness_t harness;
|
|||
|
||||
struct harness_configuration {
|
||||
const bool has_harness;
|
||||
GPIO_TypeDef *GPIO_SBU1;
|
||||
GPIO_TypeDef *GPIO_SBU2;
|
||||
GPIO_TypeDef *GPIO_relay_SBU1;
|
||||
GPIO_TypeDef *GPIO_relay_SBU2;
|
||||
uint8_t pin_SBU1;
|
||||
uint8_t pin_SBU2;
|
||||
uint8_t pin_relay_SBU1;
|
||||
uint8_t pin_relay_SBU2;
|
||||
uint8_t adc_channel_SBU1;
|
||||
uint8_t adc_channel_SBU2;
|
||||
GPIO_TypeDef * const GPIO_SBU1;
|
||||
GPIO_TypeDef * const GPIO_SBU2;
|
||||
GPIO_TypeDef * const GPIO_relay_SBU1;
|
||||
GPIO_TypeDef * const GPIO_relay_SBU2;
|
||||
const uint8_t pin_SBU1;
|
||||
const uint8_t pin_SBU2;
|
||||
const uint8_t pin_relay_SBU1;
|
||||
const uint8_t pin_relay_SBU2;
|
||||
const uint8_t adc_channel_SBU1;
|
||||
const uint8_t adc_channel_SBU2;
|
||||
};
|
||||
|
||||
// The ignition relay is only used for testing purposes
|
||||
|
@ -95,6 +95,7 @@ uint8_t harness_detect_orientation(void) {
|
|||
ret = HARNESS_STATUS_FLIPPED;
|
||||
} else {
|
||||
// orientation normal (PANDA_SBU2->HARNESS_SBU1(relay), PANDA_SBU1->HARNESS_SBU2(ign))
|
||||
// (SBU1->SBU2 is the normal orientation connection per USB-C cable spec)
|
||||
ret = HARNESS_STATUS_NORMAL;
|
||||
}
|
||||
} else {
|
||||
|
@ -116,11 +117,6 @@ void harness_tick(void) {
|
|||
}
|
||||
|
||||
void harness_init(void) {
|
||||
// delay such that the connection is fully made before trying orientation detection
|
||||
current_board->set_led(LED_BLUE, true);
|
||||
delay(10000000);
|
||||
current_board->set_led(LED_BLUE, false);
|
||||
|
||||
// try to detect orientation
|
||||
harness.status = harness_detect_orientation();
|
||||
if (harness.status != HARNESS_STATUS_NC) {
|
||||
|
|
|
@ -64,7 +64,7 @@ void handle_interrupt(IRQn_Type irq_type){
|
|||
|
||||
// Every second
|
||||
void interrupt_timer_handler(void) {
|
||||
if (INTERRUPT_TIMER->SR != 0) {
|
||||
if (INTERRUPT_TIMER->SR != 0U) {
|
||||
for (uint16_t i = 0U; i < NUM_INTERRUPTS; i++) {
|
||||
// Log IRQ call rate faults
|
||||
if (check_interrupt_rate && (interrupts[i].call_counter > interrupts[i].max_call_rate)) {
|
||||
|
@ -78,8 +78,8 @@ void interrupt_timer_handler(void) {
|
|||
|
||||
// Calculate interrupt load
|
||||
// The bootstub does not have the FPU enabled, so can't do float operations.
|
||||
#if !defined(PEDAL) && !defined(BOOTSTUB)
|
||||
interrupt_load = ((busy_time + idle_time) > 0U) ? ((float) busy_time) / (busy_time + idle_time) : 0.0f;
|
||||
#if !defined(BOOTSTUB)
|
||||
interrupt_load = ((busy_time + idle_time) > 0U) ? ((float) (((float) busy_time) / (busy_time + idle_time))) : 0.0f;
|
||||
#endif
|
||||
idle_time = 0U;
|
||||
busy_time = 0U;
|
||||
|
|
|
@ -1,79 +0,0 @@
|
|||
#define YEAR_OFFSET 2000U
|
||||
|
||||
typedef struct __attribute__((packed)) timestamp_t {
|
||||
uint16_t year;
|
||||
uint8_t month;
|
||||
uint8_t day;
|
||||
uint8_t weekday;
|
||||
uint8_t hour;
|
||||
uint8_t minute;
|
||||
uint8_t second;
|
||||
} timestamp_t;
|
||||
|
||||
uint8_t to_bcd(uint16_t value){
|
||||
return (((value / 10U) & 0x0FU) << 4U) | ((value % 10U) & 0x0FU);
|
||||
}
|
||||
|
||||
uint16_t from_bcd(uint8_t value){
|
||||
return (((value & 0xF0U) >> 4U) * 10U) + (value & 0x0FU);
|
||||
}
|
||||
|
||||
void rtc_set_time(timestamp_t time){
|
||||
print("Setting RTC time\n");
|
||||
|
||||
// Disable write protection
|
||||
disable_bdomain_protection();
|
||||
RTC->WPR = 0xCA;
|
||||
RTC->WPR = 0x53;
|
||||
|
||||
// Enable initialization mode
|
||||
register_set_bits(&(RTC->ISR), RTC_ISR_INIT);
|
||||
while((RTC->ISR & RTC_ISR_INITF) == 0){}
|
||||
|
||||
// Set time
|
||||
RTC->TR = (to_bcd(time.hour) << RTC_TR_HU_Pos) | (to_bcd(time.minute) << RTC_TR_MNU_Pos) | (to_bcd(time.second) << RTC_TR_SU_Pos);
|
||||
RTC->DR = (to_bcd(time.year - YEAR_OFFSET) << RTC_DR_YU_Pos) | (time.weekday << RTC_DR_WDU_Pos) | (to_bcd(time.month) << RTC_DR_MU_Pos) | (to_bcd(time.day) << RTC_DR_DU_Pos);
|
||||
|
||||
// Set options
|
||||
register_set(&(RTC->CR), 0U, 0xFCFFFFU);
|
||||
|
||||
// Disable initalization mode
|
||||
register_clear_bits(&(RTC->ISR), RTC_ISR_INIT);
|
||||
|
||||
// Wait for synchronization
|
||||
while((RTC->ISR & RTC_ISR_RSF) == 0){}
|
||||
|
||||
// Re-enable write protection
|
||||
RTC->WPR = 0x00;
|
||||
enable_bdomain_protection();
|
||||
}
|
||||
|
||||
timestamp_t rtc_get_time(void){
|
||||
timestamp_t result;
|
||||
// Init with zero values in case there is no RTC running
|
||||
result.year = 0U;
|
||||
result.month = 0U;
|
||||
result.day = 0U;
|
||||
result.weekday = 0U;
|
||||
result.hour = 0U;
|
||||
result.minute = 0U;
|
||||
result.second = 0U;
|
||||
|
||||
// Wait until the register sync flag is set
|
||||
while((RTC->ISR & RTC_ISR_RSF) == 0){}
|
||||
|
||||
// Read time and date registers. Since our HSE > 7*LSE, this should be fine.
|
||||
uint32_t time = RTC->TR;
|
||||
uint32_t date = RTC->DR;
|
||||
|
||||
// Parse values
|
||||
result.year = from_bcd((date & (RTC_DR_YT | RTC_DR_YU)) >> RTC_DR_YU_Pos) + YEAR_OFFSET;
|
||||
result.month = from_bcd((date & (RTC_DR_MT | RTC_DR_MU)) >> RTC_DR_MU_Pos);
|
||||
result.day = from_bcd((date & (RTC_DR_DT | RTC_DR_DU)) >> RTC_DR_DU_Pos);
|
||||
result.weekday = ((date & RTC_DR_WDU) >> RTC_DR_WDU_Pos);
|
||||
result.hour = from_bcd((time & (RTC_TR_HT | RTC_TR_HU)) >> RTC_TR_HU_Pos);
|
||||
result.minute = from_bcd((time & (RTC_TR_MNT | RTC_TR_MNU)) >> RTC_TR_MNU_Pos);
|
||||
result.second = from_bcd((time & (RTC_TR_ST | RTC_TR_SU)) >> RTC_TR_SU_Pos);
|
||||
|
||||
return result;
|
||||
}
|
|
@ -73,10 +73,8 @@ uint16_t spi_version_packet(uint8_t *out) {
|
|||
uint16_t data_pos = 7U + 2U;
|
||||
|
||||
// write serial
|
||||
#ifdef UID_BASE
|
||||
(void)memcpy(&out[data_pos], ((uint8_t *)UID_BASE), 12);
|
||||
data_len += 12U;
|
||||
#endif
|
||||
|
||||
// HW type
|
||||
out[data_pos + data_len] = hw_type;
|
||||
|
@ -232,7 +230,7 @@ void spi_rx_done(void) {
|
|||
llspi_miso_dma(spi_buf_tx, response_len);
|
||||
|
||||
spi_state = next_rx_state;
|
||||
if (!checksum_valid && (spi_checksum_error_count < __UINT16_MAX__)) {
|
||||
if (!checksum_valid && (spi_checksum_error_count < UINT16_MAX)) {
|
||||
spi_checksum_error_count += 1U;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -129,21 +129,6 @@ bool put_char(uart_ring *q, char elem) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
// Seems dangerous to use (might lock CPU if called with interrupts disabled f.e.)
|
||||
// TODO: Remove? Not used anyways
|
||||
void uart_flush(const uart_ring *q) {
|
||||
while (q->w_ptr_tx != q->r_ptr_tx) {
|
||||
__WFI();
|
||||
}
|
||||
}
|
||||
|
||||
void uart_flush_sync(uart_ring *q) {
|
||||
// empty the TX buffer
|
||||
while (q->w_ptr_tx != q->r_ptr_tx) {
|
||||
uart_tx_ring(q);
|
||||
}
|
||||
}
|
||||
|
||||
void clear_uart_buff(uart_ring *q) {
|
||||
ENTER_CRITICAL();
|
||||
q->w_ptr_tx = 0;
|
||||
|
|
|
@ -79,7 +79,7 @@ void refresh_can_tx_slots_available(void);
|
|||
#define STS_SETUP_COMP 4
|
||||
#define STS_SETUP_UPDT 6
|
||||
|
||||
uint8_t resp[USBPACKET_MAX_SIZE];
|
||||
uint8_t response[USBPACKET_MAX_SIZE];
|
||||
|
||||
// for the repeating interfaces
|
||||
#define DSCR_INTERFACE_LEN 9
|
||||
|
@ -198,13 +198,8 @@ uint16_t string_product_desc[] = {
|
|||
|
||||
// default serial number when we're not a panda
|
||||
uint16_t string_serial_desc[] = {
|
||||
#ifdef PEDAL
|
||||
STRING_DESCRIPTOR_HEADER(5),
|
||||
'p', 'e', 'd', 'a', 'l'
|
||||
#else
|
||||
STRING_DESCRIPTOR_HEADER(4),
|
||||
'n', 'o', 'n', 'e'
|
||||
#endif
|
||||
};
|
||||
|
||||
// a string containing the default configuration index
|
||||
|
@ -309,13 +304,6 @@ uint8_t binary_object_store_desc[] = {
|
|||
MS_VENDOR_CODE, 0x00 // vendor code, no alternate enumeration
|
||||
};
|
||||
|
||||
uint8_t webusb_url_descriptor[] = {
|
||||
0x14, /* bLength */
|
||||
WEBUSB_DESC_TYPE_URL, // bDescriptorType
|
||||
WEBUSB_URL_SCHEME_HTTPS, // bScheme
|
||||
'u', 's', 'b', 'p', 'a', 'n', 'd', 'a', '.', 'c', 'o', 'm', 'm', 'a', '.', 'a', 'i'
|
||||
};
|
||||
|
||||
// WinUSB 2.0 descriptor. This is what modern systems use
|
||||
// https://github.com/sowbug/weblight/blob/192ad7a0e903542e2aa28c607d98254a12a6399d/firmware/webusb.c
|
||||
// http://janaxelson.com/files/ms_os_20_descriptors.c
|
||||
|
@ -369,10 +357,10 @@ int current_int0_alt_setting = 0;
|
|||
|
||||
void *USB_ReadPacket(void *dest, uint16_t len) {
|
||||
uint32_t *dest_copy = (uint32_t *)dest;
|
||||
uint32_t count32b = (len + 3U) / 4U;
|
||||
uint32_t count32b = ((uint32_t)len + 3U) / 4U;
|
||||
|
||||
for (uint32_t i = 0; i < count32b; i++) {
|
||||
*dest_copy = USBx_DFIFO(0);
|
||||
*dest_copy = USBx_DFIFO(0U);
|
||||
dest_copy++;
|
||||
}
|
||||
return ((void *)dest_copy);
|
||||
|
@ -384,9 +372,9 @@ void USB_WritePacket(const void *src, uint16_t len, uint32_t ep) {
|
|||
hexdump(src, len);
|
||||
#endif
|
||||
|
||||
uint32_t numpacket = (len + (USBPACKET_MAX_SIZE - 1U)) / USBPACKET_MAX_SIZE;
|
||||
uint32_t numpacket = ((uint32_t)len + (USBPACKET_MAX_SIZE - 1U)) / USBPACKET_MAX_SIZE;
|
||||
uint32_t count32b = 0;
|
||||
count32b = (len + 3U) / 4U;
|
||||
count32b = ((uint32_t)len + 3U) / 4U;
|
||||
|
||||
// TODO: revisit this
|
||||
USBx_INEP(ep)->DIEPTSIZ = ((numpacket << 19) & USB_OTG_DIEPTSIZ_PKTCNT) |
|
||||
|
@ -419,7 +407,7 @@ void USB_WritePacket_EP0(uint8_t *src, uint16_t len) {
|
|||
ep0_txlen = len - wplen;
|
||||
USBx_DEVICE->DIEPEMPMSK |= 1;
|
||||
} else {
|
||||
USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
|
||||
USBx_OUTEP(0U)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -436,8 +424,8 @@ void usb_reset(void) {
|
|||
USBx_DEVICE->DOEPMSK = 0xFFFFFFFFU;
|
||||
|
||||
// clear interrupts
|
||||
USBx_INEP(0)->DIEPINT = 0xFF;
|
||||
USBx_OUTEP(0)->DOEPINT = 0xFF;
|
||||
USBx_INEP(0U)->DIEPINT = 0xFF;
|
||||
USBx_OUTEP(0U)->DOEPINT = 0xFF;
|
||||
|
||||
// unset the address
|
||||
USBx_DEVICE->DCFG &= ~USB_OTG_DCFG_DAD;
|
||||
|
@ -463,15 +451,15 @@ void usb_reset(void) {
|
|||
USBx_DEVICE->DCTL |= USB_OTG_DCTL_CGINAK;
|
||||
|
||||
// ready to receive setup packets
|
||||
USBx_OUTEP(0)->DOEPTSIZ = USB_OTG_DOEPTSIZ_STUPCNT | (USB_OTG_DOEPTSIZ_PKTCNT & (1UL << 19)) | (3U << 3);
|
||||
USBx_OUTEP(0U)->DOEPTSIZ = USB_OTG_DOEPTSIZ_STUPCNT | (USB_OTG_DOEPTSIZ_PKTCNT & (1UL << 19)) | (3U << 3);
|
||||
}
|
||||
|
||||
char to_hex_char(int a) {
|
||||
char to_hex_char(uint8_t a) {
|
||||
char ret;
|
||||
if (a < 10) {
|
||||
if (a < 10U) {
|
||||
ret = '0' + a;
|
||||
} else {
|
||||
ret = 'a' + (a - 10);
|
||||
ret = 'a' + (a - 10U);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -490,26 +478,26 @@ void usb_setup(void) {
|
|||
switch (setup.b.bRequest) {
|
||||
case USB_REQ_SET_CONFIGURATION:
|
||||
// enable other endpoints, has to be here?
|
||||
USBx_INEP(1)->DIEPCTL = (0x40U & USB_OTG_DIEPCTL_MPSIZ) | (2UL << 18) | (1UL << 22) |
|
||||
USBx_INEP(1U)->DIEPCTL = (0x40U & USB_OTG_DIEPCTL_MPSIZ) | (2UL << 18) | (1UL << 22) |
|
||||
USB_OTG_DIEPCTL_SD0PID_SEVNFRM | USB_OTG_DIEPCTL_USBAEP;
|
||||
USBx_INEP(1)->DIEPINT = 0xFF;
|
||||
USBx_INEP(1U)->DIEPINT = 0xFF;
|
||||
|
||||
USBx_OUTEP(2)->DOEPTSIZ = (1UL << 19) | 0x40U;
|
||||
USBx_OUTEP(2)->DOEPCTL = (0x40U & USB_OTG_DOEPCTL_MPSIZ) | (2UL << 18) |
|
||||
USBx_OUTEP(2U)->DOEPTSIZ = (1UL << 19) | 0x40U;
|
||||
USBx_OUTEP(2U)->DOEPCTL = (0x40U & USB_OTG_DOEPCTL_MPSIZ) | (2UL << 18) |
|
||||
USB_OTG_DOEPCTL_SD0PID_SEVNFRM | USB_OTG_DOEPCTL_USBAEP;
|
||||
USBx_OUTEP(2)->DOEPINT = 0xFF;
|
||||
USBx_OUTEP(2U)->DOEPINT = 0xFF;
|
||||
|
||||
USBx_OUTEP(3)->DOEPTSIZ = (32UL << 19) | 0x800U;
|
||||
USBx_OUTEP(3)->DOEPCTL = (0x40U & USB_OTG_DOEPCTL_MPSIZ) | (2UL << 18) |
|
||||
USBx_OUTEP(3U)->DOEPTSIZ = (32UL << 19) | 0x800U;
|
||||
USBx_OUTEP(3U)->DOEPCTL = (0x40U & USB_OTG_DOEPCTL_MPSIZ) | (2UL << 18) |
|
||||
USB_OTG_DOEPCTL_SD0PID_SEVNFRM | USB_OTG_DOEPCTL_USBAEP;
|
||||
USBx_OUTEP(3)->DOEPINT = 0xFF;
|
||||
USBx_OUTEP(3U)->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;
|
||||
USBx_OUTEP(2U)->DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK;
|
||||
USBx_OUTEP(3U)->DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK;
|
||||
|
||||
USB_WritePacket(0, 0, 0);
|
||||
USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
|
||||
USBx_OUTEP(0U)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
|
||||
break;
|
||||
case USB_REQ_SET_ADDRESS:
|
||||
// set now?
|
||||
|
@ -520,7 +508,7 @@ void usb_setup(void) {
|
|||
#endif
|
||||
|
||||
USB_WritePacket(0, 0, 0);
|
||||
USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
|
||||
USBx_OUTEP(0U)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
|
||||
|
||||
break;
|
||||
case USB_REQ_GET_DESCRIPTOR:
|
||||
|
@ -532,17 +520,17 @@ void usb_setup(void) {
|
|||
device_desc[13] = hw_type;
|
||||
// setup transfer
|
||||
USB_WritePacket(device_desc, MIN(sizeof(device_desc), setup.b.wLength.w), 0);
|
||||
USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
|
||||
USBx_OUTEP(0U)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
|
||||
|
||||
//print("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;
|
||||
USBx_OUTEP(0U)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
|
||||
break;
|
||||
case USB_DESC_TYPE_DEVICE_QUALIFIER:
|
||||
USB_WritePacket(device_qualifier, MIN(sizeof(device_qualifier), setup.b.wLength.w), 0);
|
||||
USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
|
||||
USBx_OUTEP(0U)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
|
||||
break;
|
||||
case USB_DESC_TYPE_STRING:
|
||||
switch (setup.b.wValue.bw.msb) {
|
||||
|
@ -556,23 +544,19 @@ void usb_setup(void) {
|
|||
USB_WritePacket((uint8_t*)string_product_desc, MIN(sizeof(string_product_desc), setup.b.wLength.w), 0);
|
||||
break;
|
||||
case STRING_OFFSET_ISERIAL:
|
||||
#ifdef UID_BASE
|
||||
resp[0] = 0x02 + (12 * 4);
|
||||
resp[1] = 0x03;
|
||||
response[0] = 0x02 + (12 * 4);
|
||||
response[1] = 0x03;
|
||||
|
||||
// 96 bits = 12 bytes
|
||||
for (int i = 0; i < 12; i++){
|
||||
uint8_t cc = ((uint8_t *)UID_BASE)[i];
|
||||
resp[2 + (i * 4)] = to_hex_char((cc >> 4) & 0xFU);
|
||||
resp[2 + (i * 4) + 1] = '\0';
|
||||
resp[2 + (i * 4) + 2] = to_hex_char((cc >> 0) & 0xFU);
|
||||
resp[2 + (i * 4) + 3] = '\0';
|
||||
}
|
||||
// 96 bits = 12 bytes
|
||||
for (int i = 0; i < 12; i++){
|
||||
uint8_t cc = ((uint8_t *)UID_BASE)[i];
|
||||
response[2 + (i * 4)] = to_hex_char((cc >> 4) & 0xFU);
|
||||
response[2 + (i * 4) + 1] = '\0';
|
||||
response[2 + (i * 4) + 2] = to_hex_char((cc >> 0) & 0xFU);
|
||||
response[2 + (i * 4) + 3] = '\0';
|
||||
}
|
||||
|
||||
USB_WritePacket(resp, MIN(resp[0], setup.b.wLength.w), 0);
|
||||
#else
|
||||
USB_WritePacket((const uint8_t *)string_serial_desc, MIN(sizeof(string_serial_desc), setup.b.wLength.w), 0);
|
||||
#endif
|
||||
USB_WritePacket(response, MIN(response[0], setup.b.wLength.w), 0);
|
||||
break;
|
||||
case STRING_OFFSET_ICONFIGURATION:
|
||||
USB_WritePacket((uint8_t*)string_configuration_desc, MIN(sizeof(string_configuration_desc), setup.b.wLength.w), 0);
|
||||
|
@ -585,44 +569,36 @@ void usb_setup(void) {
|
|||
USB_WritePacket(0, 0, 0);
|
||||
break;
|
||||
}
|
||||
USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
|
||||
USBx_OUTEP(0U)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
|
||||
break;
|
||||
case USB_DESC_TYPE_BINARY_OBJECT_STORE:
|
||||
USB_WritePacket(binary_object_store_desc, MIN(sizeof(binary_object_store_desc), setup.b.wLength.w), 0);
|
||||
USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
|
||||
USBx_OUTEP(0U)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
|
||||
break;
|
||||
default:
|
||||
// nothing here?
|
||||
USB_WritePacket(0, 0, 0);
|
||||
USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
|
||||
USBx_OUTEP(0U)->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;
|
||||
// empty response?
|
||||
response[0] = 0;
|
||||
response[1] = 0;
|
||||
USB_WritePacket((void*)&response, 2, 0);
|
||||
USBx_OUTEP(0U)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
|
||||
break;
|
||||
case USB_REQ_SET_INTERFACE:
|
||||
// Store the alt setting number for IN EP behavior.
|
||||
current_int0_alt_setting = setup.b.wValue.w;
|
||||
USB_WritePacket(0, 0, 0);
|
||||
USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
|
||||
USBx_OUTEP(0U)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
|
||||
break;
|
||||
case WEBUSB_VENDOR_CODE:
|
||||
switch (setup.b.wIndex.w) {
|
||||
case WEBUSB_REQ_GET_URL:
|
||||
USB_WritePacket(webusb_url_descriptor, MIN(sizeof(webusb_url_descriptor), setup.b.wLength.w), 0);
|
||||
USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
|
||||
break;
|
||||
default:
|
||||
// probably asking for allowed origins, which was removed from the spec
|
||||
USB_WritePacket(0, 0, 0);
|
||||
USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
|
||||
break;
|
||||
}
|
||||
// probably asking for allowed origins, which was removed from the spec
|
||||
USB_WritePacket(0, 0, 0);
|
||||
USBx_OUTEP(0U)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
|
||||
break;
|
||||
case MS_VENDOR_CODE:
|
||||
switch (setup.b.wIndex.w) {
|
||||
|
@ -648,11 +624,11 @@ void usb_setup(void) {
|
|||
control_req.param2 = setup.b.wIndex.w;
|
||||
control_req.length = setup.b.wLength.w;
|
||||
|
||||
resp_len = comms_control_handler(&control_req, resp);
|
||||
resp_len = comms_control_handler(&control_req, response);
|
||||
// response pending if -1 was returned
|
||||
if (resp_len != -1) {
|
||||
USB_WritePacket(resp, MIN(resp_len, setup.b.wLength.w), 0);
|
||||
USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
|
||||
USB_WritePacket(response, MIN(resp_len, setup.b.wLength.w), 0);
|
||||
USBx_OUTEP(0U)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -680,23 +656,23 @@ void usb_irqhandler(void) {
|
|||
print(" USB interrupt!\n");
|
||||
#endif
|
||||
|
||||
if ((gintsts & USB_OTG_GINTSTS_CIDSCHG) != 0) {
|
||||
if ((gintsts & USB_OTG_GINTSTS_CIDSCHG) != 0U) {
|
||||
print("connector ID status change\n");
|
||||
}
|
||||
|
||||
if ((gintsts & USB_OTG_GINTSTS_USBRST) != 0) {
|
||||
if ((gintsts & USB_OTG_GINTSTS_USBRST) != 0U) {
|
||||
print("USB reset\n");
|
||||
usb_reset();
|
||||
}
|
||||
|
||||
if ((gintsts & USB_OTG_GINTSTS_ENUMDNE) != 0) {
|
||||
if ((gintsts & USB_OTG_GINTSTS_ENUMDNE) != 0U) {
|
||||
print("enumeration done");
|
||||
// Full speed, ENUMSPD
|
||||
//puth(USBx_DEVICE->DSTS);
|
||||
print("\n");
|
||||
}
|
||||
|
||||
if ((gintsts & USB_OTG_GINTSTS_OTGINT) != 0) {
|
||||
if ((gintsts & USB_OTG_GINTSTS_OTGINT) != 0U) {
|
||||
print("OTG int:");
|
||||
puth(USBx->GOTGINT);
|
||||
print("\n");
|
||||
|
@ -706,7 +682,7 @@ void usb_irqhandler(void) {
|
|||
}
|
||||
|
||||
// RX FIFO first
|
||||
if ((gintsts & USB_OTG_GINTSTS_RXFLVL) != 0) {
|
||||
if ((gintsts & USB_OTG_GINTSTS_RXFLVL) != 0U) {
|
||||
// 1. Read the Receive status pop register
|
||||
volatile unsigned int rxst = USBx->GRXSTSP;
|
||||
int status = (rxst & USB_OTG_GRXSTSP_PKTSTS) >> 17;
|
||||
|
@ -772,7 +748,7 @@ void usb_irqhandler(void) {
|
|||
USBx_DEVICE->DCTL |= USB_OTG_DCTL_CGONAK | USB_OTG_DCTL_CGINAK;
|
||||
}
|
||||
|
||||
if ((gintsts & USB_OTG_GINTSTS_SRQINT) != 0) {
|
||||
if ((gintsts & USB_OTG_GINTSTS_SRQINT) != 0U) {
|
||||
// we want to do "A-device host negotiation protocol" since we are the A-device
|
||||
/*print("start request\n");
|
||||
puth(USBx->GOTGCTL);
|
||||
|
@ -783,76 +759,76 @@ void usb_irqhandler(void) {
|
|||
}
|
||||
|
||||
// out endpoint hit
|
||||
if ((gintsts & USB_OTG_GINTSTS_OEPINT) != 0) {
|
||||
if ((gintsts & USB_OTG_GINTSTS_OEPINT) != 0U) {
|
||||
#ifdef DEBUG_USB
|
||||
print(" 0:");
|
||||
puth(USBx_OUTEP(0)->DOEPINT);
|
||||
puth(USBx_OUTEP(0U)->DOEPINT);
|
||||
print(" 2:");
|
||||
puth(USBx_OUTEP(2)->DOEPINT);
|
||||
puth(USBx_OUTEP(2U)->DOEPINT);
|
||||
print(" 3:");
|
||||
puth(USBx_OUTEP(3)->DOEPINT);
|
||||
puth(USBx_OUTEP(3U)->DOEPINT);
|
||||
print(" ");
|
||||
puth(USBx_OUTEP(3)->DOEPCTL);
|
||||
puth(USBx_OUTEP(3U)->DOEPCTL);
|
||||
print(" 4:");
|
||||
puth(USBx_OUTEP(4)->DOEPINT);
|
||||
print(" OUT ENDPOINT\n");
|
||||
#endif
|
||||
|
||||
if ((USBx_OUTEP(2)->DOEPINT & USB_OTG_DOEPINT_XFRC) != 0) {
|
||||
if ((USBx_OUTEP(2U)->DOEPINT & USB_OTG_DOEPINT_XFRC) != 0U) {
|
||||
#ifdef DEBUG_USB
|
||||
print(" OUT2 PACKET XFRC\n");
|
||||
#endif
|
||||
USBx_OUTEP(2)->DOEPTSIZ = (1UL << 19) | 0x40U;
|
||||
USBx_OUTEP(2)->DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK;
|
||||
USBx_OUTEP(2U)->DOEPTSIZ = (1UL << 19) | 0x40U;
|
||||
USBx_OUTEP(2U)->DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK;
|
||||
}
|
||||
|
||||
if ((USBx_OUTEP(3)->DOEPINT & USB_OTG_DOEPINT_XFRC) != 0) {
|
||||
if ((USBx_OUTEP(3U)->DOEPINT & USB_OTG_DOEPINT_XFRC) != 0U) {
|
||||
#ifdef DEBUG_USB
|
||||
print(" OUT3 PACKET XFRC\n");
|
||||
#endif
|
||||
// NAK cleared by process_can (if tx buffers have room)
|
||||
outep3_processing = false;
|
||||
refresh_can_tx_slots_available();
|
||||
} else if ((USBx_OUTEP(3)->DOEPINT & 0x2000) != 0) {
|
||||
} else if ((USBx_OUTEP(3U)->DOEPINT & 0x2000U) != 0U) {
|
||||
#ifdef DEBUG_USB
|
||||
print(" OUT3 PACKET WTF\n");
|
||||
#endif
|
||||
// if NAK was set trigger this, unknown interrupt
|
||||
// TODO: why was this here? fires when TX buffers when we can't clear NAK
|
||||
// USBx_OUTEP(3)->DOEPTSIZ = (1U << 19) | 0x40U;
|
||||
// USBx_OUTEP(3)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
|
||||
} else if ((USBx_OUTEP(3)->DOEPINT) != 0) {
|
||||
// USBx_OUTEP(3U)->DOEPTSIZ = (1U << 19) | 0x40U;
|
||||
// USBx_OUTEP(3U)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
|
||||
} else if ((USBx_OUTEP(3U)->DOEPINT) != 0U) {
|
||||
#ifdef DEBUG_USB
|
||||
print("OUTEP3 error ");
|
||||
puth(USBx_OUTEP(3)->DOEPINT);
|
||||
puth(USBx_OUTEP(3U)->DOEPINT);
|
||||
print("\n");
|
||||
#endif
|
||||
} else {
|
||||
// USBx_OUTEP(3)->DOEPINT is 0, ok to skip
|
||||
// USBx_OUTEP(3U)->DOEPINT is 0, ok to skip
|
||||
}
|
||||
|
||||
if ((USBx_OUTEP(0)->DOEPINT & USB_OTG_DIEPINT_XFRC) != 0) {
|
||||
if ((USBx_OUTEP(0U)->DOEPINT & USB_OTG_DIEPINT_XFRC) != 0U) {
|
||||
// ready for next packet
|
||||
USBx_OUTEP(0)->DOEPTSIZ = USB_OTG_DOEPTSIZ_STUPCNT | (USB_OTG_DOEPTSIZ_PKTCNT & (1UL << 19)) | (1U << 3);
|
||||
USBx_OUTEP(0U)->DOEPTSIZ = USB_OTG_DOEPTSIZ_STUPCNT | (USB_OTG_DOEPTSIZ_PKTCNT & (1UL << 19)) | (1U << 3);
|
||||
}
|
||||
|
||||
// respond to setup packets
|
||||
if ((USBx_OUTEP(0)->DOEPINT & USB_OTG_DOEPINT_STUP) != 0) {
|
||||
if ((USBx_OUTEP(0U)->DOEPINT & USB_OTG_DOEPINT_STUP) != 0U) {
|
||||
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;
|
||||
USBx_OUTEP(0U)->DOEPINT = USBx_OUTEP(0U)->DOEPINT;
|
||||
USBx_OUTEP(2U)->DOEPINT = USBx_OUTEP(2U)->DOEPINT;
|
||||
USBx_OUTEP(3U)->DOEPINT = USBx_OUTEP(3U)->DOEPINT;
|
||||
}
|
||||
|
||||
// interrupt endpoint hit (Page 1221)
|
||||
if ((gintsts & USB_OTG_GINTSTS_IEPINT) != 0) {
|
||||
if ((gintsts & USB_OTG_GINTSTS_IEPINT) != 0U) {
|
||||
#ifdef DEBUG_USB
|
||||
print(" ");
|
||||
puth(USBx_INEP(0)->DIEPINT);
|
||||
puth(USBx_INEP(0U)->DIEPINT);
|
||||
print(" ");
|
||||
puth(USBx_INEP(1)->DIEPINT);
|
||||
puth(USBx_INEP(1U)->DIEPINT);
|
||||
print(" IN ENDPOINT\n");
|
||||
#endif
|
||||
|
||||
|
@ -872,25 +848,25 @@ void usb_irqhandler(void) {
|
|||
switch (current_int0_alt_setting) {
|
||||
case 0: ////// Bulk config
|
||||
// *** IN token received when TxFIFO is empty
|
||||
if ((USBx_INEP(1)->DIEPINT & USB_OTG_DIEPMSK_ITTXFEMSK) != 0) {
|
||||
if ((USBx_INEP(1U)->DIEPINT & USB_OTG_DIEPMSK_ITTXFEMSK) != 0U) {
|
||||
#ifdef DEBUG_USB
|
||||
print(" IN PACKET QUEUE\n");
|
||||
#endif
|
||||
// TODO: always assuming max len, can we get the length?
|
||||
USB_WritePacket((void *)resp, comms_can_read(resp, 0x40), 1);
|
||||
USB_WritePacket((void *)response, comms_can_read(response, 0x40), 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case 1: ////// Interrupt config
|
||||
// *** IN token received when TxFIFO is empty
|
||||
if ((USBx_INEP(1)->DIEPINT & USB_OTG_DIEPMSK_ITTXFEMSK) != 0) {
|
||||
if ((USBx_INEP(1U)->DIEPINT & USB_OTG_DIEPMSK_ITTXFEMSK) != 0U) {
|
||||
#ifdef DEBUG_USB
|
||||
print(" IN PACKET QUEUE\n");
|
||||
#endif
|
||||
// TODO: always assuming max len, can we get the length?
|
||||
int len = comms_can_read(resp, 0x40);
|
||||
int len = comms_can_read(response, 0x40);
|
||||
if (len > 0) {
|
||||
USB_WritePacket((void *)resp, len, 1);
|
||||
USB_WritePacket((void *)response, len, 1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -899,12 +875,12 @@ void usb_irqhandler(void) {
|
|||
break;
|
||||
}
|
||||
|
||||
if ((USBx_INEP(0)->DIEPINT & USB_OTG_DIEPMSK_ITTXFEMSK) != 0) {
|
||||
if ((USBx_INEP(0U)->DIEPINT & USB_OTG_DIEPMSK_ITTXFEMSK) != 0U) {
|
||||
#ifdef DEBUG_USB
|
||||
print(" IN PACKET QUEUE\n");
|
||||
#endif
|
||||
|
||||
if ((ep0_txlen != 0U) && ((USBx_INEP(0)->DTXFSTS & USB_OTG_DTXFSTS_INEPTFSAV) >= 0x40U)) {
|
||||
if ((ep0_txlen != 0U) && ((USBx_INEP(0U)->DTXFSTS & USB_OTG_DTXFSTS_INEPTFSAV) >= 0x40U)) {
|
||||
uint16_t len = MIN(ep0_txlen, 0x40);
|
||||
USB_WritePacket(ep0_txdata, len, 0);
|
||||
ep0_txdata = &ep0_txdata[len];
|
||||
|
@ -912,14 +888,14 @@ void usb_irqhandler(void) {
|
|||
if (ep0_txlen == 0U) {
|
||||
ep0_txdata = NULL;
|
||||
USBx_DEVICE->DIEPEMPMSK &= ~1;
|
||||
USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
|
||||
USBx_OUTEP(0U)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// clear interrupts
|
||||
USBx_INEP(0)->DIEPINT = USBx_INEP(0)->DIEPINT; // Why ep0?
|
||||
USBx_INEP(1)->DIEPINT = USBx_INEP(1)->DIEPINT;
|
||||
USBx_INEP(0U)->DIEPINT = USBx_INEP(0U)->DIEPINT; // Why ep0?
|
||||
USBx_INEP(1U)->DIEPINT = USBx_INEP(1U)->DIEPINT;
|
||||
}
|
||||
|
||||
// clear all interrupts we handled
|
||||
|
@ -932,9 +908,9 @@ void usb_irqhandler(void) {
|
|||
|
||||
void can_tx_comms_resume_usb(void) {
|
||||
ENTER_CRITICAL();
|
||||
if (!outep3_processing && (USBx_OUTEP(3)->DOEPCTL & USB_OTG_DOEPCTL_NAKSTS) != 0) {
|
||||
USBx_OUTEP(3)->DOEPTSIZ = (32UL << 19) | 0x800U;
|
||||
USBx_OUTEP(3)->DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK;
|
||||
if (!outep3_processing && (USBx_OUTEP(3U)->DOEPCTL & USB_OTG_DOEPCTL_NAKSTS) != 0U) {
|
||||
USBx_OUTEP(3U)->DOEPTSIZ = (32UL << 19) | 0x800U;
|
||||
USBx_OUTEP(3U)->DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK;
|
||||
}
|
||||
EXIT_CRITICAL();
|
||||
}
|
||||
|
|
|
@ -1,9 +1,3 @@
|
|||
// TODO: why doesn't it define these?
|
||||
#ifdef STM32F2
|
||||
#define IWDG_PR_PR_Msk 0x7U
|
||||
#define IWDG_RLR_RL_Msk 0xFFFU
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
WATCHDOG_50_MS = (400U - 1U),
|
||||
WATCHDOG_500_MS = 4000U,
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#define FAULT_INTERRUPT_RATE_CAN_2 (1UL << 3)
|
||||
#define FAULT_INTERRUPT_RATE_CAN_3 (1UL << 4)
|
||||
#define FAULT_INTERRUPT_RATE_TACH (1UL << 5)
|
||||
#define FAULT_INTERRUPT_RATE_GMLAN (1UL << 6)
|
||||
#define FAULT_INTERRUPT_RATE_GMLAN (1UL << 6) // deprecated
|
||||
#define FAULT_INTERRUPT_RATE_INTERRUPTS (1UL << 7)
|
||||
#define FAULT_INTERRUPT_RATE_SPI_DMA (1UL << 8)
|
||||
#define FAULT_INTERRUPT_RATE_SPI_CS (1UL << 9)
|
||||
|
|
|
@ -15,3 +15,4 @@ if __name__ == "__main__":
|
|||
print("flashing", s)
|
||||
with Panda(serial=s) as p:
|
||||
p.flash()
|
||||
exit(1 if len(serials) == 0 else 0)
|
||||
|
|
187
board/flasher.h
187
board/flasher.h
|
@ -4,10 +4,6 @@ bool unlocked = false;
|
|||
|
||||
void spi_init(void);
|
||||
|
||||
#ifdef uart_ring
|
||||
void debug_ring_callback(uart_ring *ring) {}
|
||||
#endif
|
||||
|
||||
int comms_control_handler(ControlPacket_t *req, uint8_t *resp) {
|
||||
int resp_len = 0;
|
||||
|
||||
|
@ -50,23 +46,19 @@ int comms_control_handler(ControlPacket_t *req, uint8_t *resp) {
|
|||
break;
|
||||
// **** 0xc3: fetch MCU UID
|
||||
case 0xc3:
|
||||
#ifdef UID_BASE
|
||||
(void)memcpy(resp, ((uint8_t *)UID_BASE), 12);
|
||||
resp_len = 12;
|
||||
#endif
|
||||
(void)memcpy(resp, ((uint8_t *)UID_BASE), 12);
|
||||
resp_len = 12;
|
||||
break;
|
||||
// **** 0xd0: fetch serial number
|
||||
case 0xd0:
|
||||
#ifndef STM32F2
|
||||
// addresses are OTP
|
||||
if (req->param1 == 1) {
|
||||
memcpy(resp, (void *)DEVICE_SERIAL_NUMBER_ADDRESS, 0x10);
|
||||
resp_len = 0x10;
|
||||
} else {
|
||||
get_provision_chunk(resp);
|
||||
resp_len = PROVISION_CHUNK_LEN;
|
||||
}
|
||||
#endif
|
||||
// addresses are OTP
|
||||
if (req->param1 == 1) {
|
||||
memcpy(resp, (void *)DEVICE_SERIAL_NUMBER_ADDRESS, 0x10);
|
||||
resp_len = 0x10;
|
||||
} else {
|
||||
get_provision_chunk(resp);
|
||||
resp_len = PROVISION_CHUNK_LEN;
|
||||
}
|
||||
break;
|
||||
// **** 0xd1: enter bootloader mode
|
||||
case 0xd1:
|
||||
|
@ -124,172 +116,13 @@ void comms_endpoint2_write(const uint8_t *data, uint32_t len) {
|
|||
}
|
||||
|
||||
|
||||
int spi_cb_rx(uint8_t *data, int len, uint8_t *data_out) {
|
||||
UNUSED(len);
|
||||
ControlPacket_t control_req;
|
||||
|
||||
int resp_len = 0;
|
||||
switch (data[0]) {
|
||||
case 0:
|
||||
// control transfer
|
||||
control_req.request = ((USB_Setup_TypeDef *)(data+4))->b.bRequest;
|
||||
control_req.param1 = ((USB_Setup_TypeDef *)(data+4))->b.wValue.w;
|
||||
control_req.param2 = ((USB_Setup_TypeDef *)(data+4))->b.wIndex.w;
|
||||
control_req.length = ((USB_Setup_TypeDef *)(data+4))->b.wLength.w;
|
||||
|
||||
resp_len = comms_control_handler(&control_req, data_out);
|
||||
break;
|
||||
case 2:
|
||||
// ep 2, flash!
|
||||
comms_endpoint2_write(data+4, data[2]);
|
||||
break;
|
||||
}
|
||||
return resp_len;
|
||||
}
|
||||
|
||||
#ifdef PEDAL
|
||||
|
||||
#include "stm32fx/llbxcan.h"
|
||||
#define CANx CAN1
|
||||
|
||||
#define CAN_BL_INPUT 0x1
|
||||
#define CAN_BL_OUTPUT 0x2
|
||||
|
||||
void CAN1_TX_IRQ_Handler(void) {
|
||||
// clear interrupt
|
||||
CANx->TSR |= CAN_TSR_RQCP0;
|
||||
}
|
||||
|
||||
#define ISOTP_BUF_SIZE 0x110
|
||||
|
||||
uint8_t isotp_buf[ISOTP_BUF_SIZE];
|
||||
uint8_t *isotp_buf_ptr = NULL;
|
||||
int isotp_buf_remain = 0;
|
||||
|
||||
uint8_t isotp_buf_out[ISOTP_BUF_SIZE];
|
||||
uint8_t *isotp_buf_out_ptr = NULL;
|
||||
int isotp_buf_out_remain = 0;
|
||||
int isotp_buf_out_idx = 0;
|
||||
|
||||
void bl_can_send(uint8_t *odat) {
|
||||
// wait for send
|
||||
while (!(CANx->TSR & CAN_TSR_TME0));
|
||||
|
||||
// send continue
|
||||
CANx->sTxMailBox[0].TDLR = ((uint32_t*)odat)[0];
|
||||
CANx->sTxMailBox[0].TDHR = ((uint32_t*)odat)[1];
|
||||
CANx->sTxMailBox[0].TDTR = 8;
|
||||
CANx->sTxMailBox[0].TIR = (CAN_BL_OUTPUT << 21) | 1;
|
||||
}
|
||||
|
||||
void CAN1_RX0_IRQ_Handler(void) {
|
||||
while (CANx->RF0R & CAN_RF0R_FMP0) {
|
||||
if ((CANx->sFIFOMailBox[0].RIR>>21) == CAN_BL_INPUT) {
|
||||
uint8_t dat[8];
|
||||
for (int i = 0; i < 8; i++) {
|
||||
dat[i] = GET_MAILBOX_BYTE(&CANx->sFIFOMailBox[0], i);
|
||||
}
|
||||
uint8_t odat[8];
|
||||
uint8_t type = dat[0] & 0xF0;
|
||||
if (type == 0x30) {
|
||||
// continue
|
||||
while (isotp_buf_out_remain > 0) {
|
||||
// wait for send
|
||||
while (!(CANx->TSR & CAN_TSR_TME0));
|
||||
|
||||
odat[0] = 0x20 | isotp_buf_out_idx;
|
||||
memcpy(odat+1, isotp_buf_out_ptr, 7);
|
||||
isotp_buf_out_remain -= 7;
|
||||
isotp_buf_out_ptr += 7;
|
||||
isotp_buf_out_idx++;
|
||||
|
||||
bl_can_send(odat);
|
||||
}
|
||||
} else if (type == 0x20) {
|
||||
if (isotp_buf_remain > 0) {
|
||||
memcpy(isotp_buf_ptr, dat+1, 7);
|
||||
isotp_buf_ptr += 7;
|
||||
isotp_buf_remain -= 7;
|
||||
}
|
||||
if (isotp_buf_remain <= 0) {
|
||||
int len = isotp_buf_ptr - isotp_buf + isotp_buf_remain;
|
||||
|
||||
// call the function
|
||||
memset(isotp_buf_out, 0, ISOTP_BUF_SIZE);
|
||||
isotp_buf_out_remain = spi_cb_rx(isotp_buf, len, isotp_buf_out);
|
||||
isotp_buf_out_ptr = isotp_buf_out;
|
||||
isotp_buf_out_idx = 0;
|
||||
|
||||
// send initial
|
||||
if (isotp_buf_out_remain <= 7) {
|
||||
odat[0] = isotp_buf_out_remain;
|
||||
memcpy(odat+1, isotp_buf_out_ptr, isotp_buf_out_remain);
|
||||
} else {
|
||||
odat[0] = 0x10 | (isotp_buf_out_remain>>8);
|
||||
odat[1] = isotp_buf_out_remain & 0xFF;
|
||||
memcpy(odat+2, isotp_buf_out_ptr, 6);
|
||||
isotp_buf_out_remain -= 6;
|
||||
isotp_buf_out_ptr += 6;
|
||||
isotp_buf_out_idx++;
|
||||
}
|
||||
|
||||
bl_can_send(odat);
|
||||
}
|
||||
} else if (type == 0x10) {
|
||||
int len = ((dat[0]&0xF)<<8) | dat[1];
|
||||
|
||||
// setup buffer
|
||||
isotp_buf_ptr = isotp_buf;
|
||||
memcpy(isotp_buf_ptr, dat+2, 6);
|
||||
|
||||
if (len < (ISOTP_BUF_SIZE-0x10)) {
|
||||
isotp_buf_ptr += 6;
|
||||
isotp_buf_remain = len-6;
|
||||
}
|
||||
|
||||
memset(odat, 0, 8);
|
||||
odat[0] = 0x30;
|
||||
bl_can_send(odat);
|
||||
}
|
||||
}
|
||||
// next
|
||||
CANx->RF0R |= CAN_RF0R_RFOM0;
|
||||
}
|
||||
}
|
||||
|
||||
void CAN1_SCE_IRQ_Handler(void) {
|
||||
llcan_clear_send(CANx);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void soft_flasher_start(void) {
|
||||
#ifdef PEDAL
|
||||
REGISTER_INTERRUPT(CAN1_TX_IRQn, CAN1_TX_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_1)
|
||||
REGISTER_INTERRUPT(CAN1_RX0_IRQn, CAN1_RX0_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_1)
|
||||
REGISTER_INTERRUPT(CAN1_SCE_IRQn, CAN1_SCE_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_1)
|
||||
#endif
|
||||
|
||||
print("\n\n\n************************ FLASHER START ************************\n");
|
||||
|
||||
enter_bootloader_mode = 0;
|
||||
|
||||
flasher_peripherals_init();
|
||||
|
||||
// pedal has the canloader
|
||||
#ifdef PEDAL
|
||||
RCC->APB1ENR |= RCC_APB1ENR_CAN1EN;
|
||||
|
||||
// B8,B9: CAN 1
|
||||
set_gpio_alternate(GPIOB, 8, GPIO_AF9_CAN1);
|
||||
set_gpio_alternate(GPIOB, 9, GPIO_AF9_CAN1);
|
||||
current_board->enable_can_transceiver(1, true);
|
||||
|
||||
// init can
|
||||
llcan_set_speed(CANx, 5000, false, false);
|
||||
llcan_init(CANx);
|
||||
#endif
|
||||
|
||||
gpio_usart2_init();
|
||||
gpio_usb_init();
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// When changing these structs, python/__init__.py needs to be kept up to date!
|
||||
|
||||
#define HEALTH_PACKET_VERSION 15
|
||||
#define HEALTH_PACKET_VERSION 16
|
||||
struct __attribute__((packed)) health_t {
|
||||
uint32_t uptime_pkt;
|
||||
uint32_t voltage_pkt;
|
||||
|
@ -9,7 +9,6 @@ struct __attribute__((packed)) health_t {
|
|||
uint32_t safety_rx_invalid_pkt;
|
||||
uint32_t tx_buffer_overflow_pkt;
|
||||
uint32_t rx_buffer_overflow_pkt;
|
||||
uint32_t gmlan_send_errs_pkt;
|
||||
uint32_t faults_pkt;
|
||||
uint8_t ignition_line_pkt;
|
||||
uint8_t ignition_can_pkt;
|
||||
|
@ -21,10 +20,10 @@ struct __attribute__((packed)) health_t {
|
|||
uint8_t power_save_enabled_pkt;
|
||||
uint8_t heartbeat_lost_pkt;
|
||||
uint16_t alternative_experience_pkt;
|
||||
float interrupt_load;
|
||||
float interrupt_load_pkt;
|
||||
uint8_t fan_power;
|
||||
uint8_t safety_rx_checks_invalid;
|
||||
uint16_t spi_checksum_error_count;
|
||||
uint8_t safety_rx_checks_invalid_pkt;
|
||||
uint16_t spi_checksum_error_count_pkt;
|
||||
uint8_t fan_stall_count;
|
||||
uint16_t sbu1_voltage_mV;
|
||||
uint16_t sbu2_voltage_mV;
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
import os
|
||||
import struct
|
||||
from functools import wraps
|
||||
from typing import Optional
|
||||
|
||||
from panda import Panda, PandaDFU
|
||||
from panda.python.constants import McuType
|
||||
|
@ -57,7 +56,7 @@ class PandaJungle(Panda):
|
|||
fn = os.path.join(FW_PATH, self._mcu_type.config.app_fn.replace("panda", "panda_jungle"))
|
||||
super().flash(fn=fn, code=code, reconnect=reconnect)
|
||||
|
||||
def recover(self, timeout: Optional[int] = 60, reset: bool = True) -> bool:
|
||||
def recover(self, timeout: int | None = 60, reset: bool = True) -> bool:
|
||||
dfu_serial = self.get_dfu_serial()
|
||||
|
||||
if reset:
|
||||
|
@ -81,6 +80,12 @@ class PandaJungle(Panda):
|
|||
return McuType.F4
|
||||
elif hw_type in PandaJungle.H7_DEVICES:
|
||||
return McuType.H7
|
||||
else:
|
||||
# have to assume F4, see comment in Panda.connect
|
||||
# initially Jungle V1 has HW type: bytearray(b'')
|
||||
if hw_type == b'' or self._assume_f4_mcu:
|
||||
return McuType.F4
|
||||
|
||||
raise ValueError(f"unknown HW type: {hw_type}")
|
||||
|
||||
def up_to_date(self, fn=None) -> bool:
|
||||
|
|
|
@ -49,8 +49,6 @@ struct board {
|
|||
|
||||
// CAN modes
|
||||
#define CAN_MODE_NORMAL 0U
|
||||
#define CAN_MODE_GMLAN_CAN2 1U
|
||||
#define CAN_MODE_GMLAN_CAN3 2U
|
||||
#define CAN_MODE_OBD_CAN2 3U
|
||||
|
||||
// Harness states
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// ///////////////////////// //
|
||||
// Jungle board v1 (STM32F4) //
|
||||
// ///////////////////////// //
|
||||
|
||||
void board_v1_set_led(uint8_t color, bool enabled) {
|
||||
switch (color) {
|
||||
|
@ -154,7 +157,7 @@ void board_v1_init(void) {
|
|||
|
||||
void board_v1_tick(void) {}
|
||||
|
||||
const board board_v1 = {
|
||||
board board_v1 = {
|
||||
.has_canfd = false,
|
||||
.has_sbu_sense = false,
|
||||
.avdd_mV = 3300U,
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
// ///////////////////////// //
|
||||
// Jungle board v2 (STM32H7) //
|
||||
// ///////////////////////// //
|
||||
|
||||
const gpio_t power_pins[] = {
|
||||
gpio_t power_pins[] = {
|
||||
{.bank = GPIOA, .pin = 0},
|
||||
{.bank = GPIOA, .pin = 1},
|
||||
{.bank = GPIOF, .pin = 12},
|
||||
|
@ -8,7 +11,7 @@ const gpio_t power_pins[] = {
|
|||
{.bank = GPIOB, .pin = 2},
|
||||
};
|
||||
|
||||
const gpio_t sbu1_ignition_pins[] = {
|
||||
gpio_t sbu1_ignition_pins[] = {
|
||||
{.bank = GPIOD, .pin = 0},
|
||||
{.bank = GPIOD, .pin = 5},
|
||||
{.bank = GPIOD, .pin = 12},
|
||||
|
@ -17,7 +20,7 @@ const gpio_t sbu1_ignition_pins[] = {
|
|||
{.bank = GPIOE, .pin = 9},
|
||||
};
|
||||
|
||||
const gpio_t sbu1_relay_pins[] = {
|
||||
gpio_t sbu1_relay_pins[] = {
|
||||
{.bank = GPIOD, .pin = 1},
|
||||
{.bank = GPIOD, .pin = 6},
|
||||
{.bank = GPIOD, .pin = 11},
|
||||
|
@ -26,7 +29,7 @@ const gpio_t sbu1_relay_pins[] = {
|
|||
{.bank = GPIOE, .pin = 10},
|
||||
};
|
||||
|
||||
const gpio_t sbu2_ignition_pins[] = {
|
||||
gpio_t sbu2_ignition_pins[] = {
|
||||
{.bank = GPIOD, .pin = 3},
|
||||
{.bank = GPIOD, .pin = 8},
|
||||
{.bank = GPIOD, .pin = 9},
|
||||
|
@ -35,7 +38,7 @@ const gpio_t sbu2_ignition_pins[] = {
|
|||
{.bank = GPIOE, .pin = 11},
|
||||
};
|
||||
|
||||
const gpio_t sbu2_relay_pins[] = {
|
||||
gpio_t sbu2_relay_pins[] = {
|
||||
{.bank = GPIOD, .pin = 4},
|
||||
{.bank = GPIOD, .pin = 10},
|
||||
{.bank = GPIOD, .pin = 13},
|
||||
|
@ -44,7 +47,7 @@ const gpio_t sbu2_relay_pins[] = {
|
|||
{.bank = GPIOE, .pin = 12},
|
||||
};
|
||||
|
||||
const adc_channel_t sbu1_channels[] = {
|
||||
adc_channel_t sbu1_channels[] = {
|
||||
{.adc = ADC3, .channel = 12},
|
||||
{.adc = ADC3, .channel = 2},
|
||||
{.adc = ADC3, .channel = 4},
|
||||
|
@ -53,7 +56,7 @@ const adc_channel_t sbu1_channels[] = {
|
|||
{.adc = ADC3, .channel = 10},
|
||||
};
|
||||
|
||||
const adc_channel_t sbu2_channels[] = {
|
||||
adc_channel_t sbu2_channels[] = {
|
||||
{.adc = ADC1, .channel = 13},
|
||||
{.adc = ADC3, .channel = 3},
|
||||
{.adc = ADC3, .channel = 5},
|
||||
|
@ -304,7 +307,7 @@ void board_v2_init(void) {
|
|||
|
||||
void board_v2_tick(void) {}
|
||||
|
||||
const board board_v2 = {
|
||||
board board_v2 = {
|
||||
.has_canfd = true,
|
||||
.has_sbu_sense = true,
|
||||
.avdd_mV = 3300U,
|
||||
|
|
|
@ -15,3 +15,5 @@ if __name__ == "__main__":
|
|||
print("flashing", s)
|
||||
with PandaJungle(serial=s) as p:
|
||||
p.flash()
|
||||
|
||||
exit(1 if len(serials) == 0 else 0)
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
#include "board/config.h"
|
||||
|
||||
#include "board/safety.h"
|
||||
#include "board/drivers/gmlan_alt.h"
|
||||
|
||||
#include "board/drivers/pwm.h"
|
||||
#include "board/drivers/usb.h"
|
||||
|
|
|
@ -24,3 +24,4 @@ if __name__ == "__main__":
|
|||
for s in dfu_serials:
|
||||
print("flashing", s)
|
||||
PandaJungleDFU(s).recover()
|
||||
exit(1 if len(dfu_serials) == 0 else 0)
|
||||
|
|
|
@ -4,6 +4,6 @@ from panda import PandaJungle
|
|||
if __name__ == "__main__":
|
||||
for p in PandaJungle.list():
|
||||
pp = PandaJungle(p)
|
||||
print("%s: %s" % (pp.get_serial()[0], pp.get_version()))
|
||||
print(f"{pp.get_serial()[0]}: {pp.get_version()}")
|
||||
|
||||
|
||||
|
|
67
board/main.c
67
board/main.c
|
@ -3,7 +3,6 @@
|
|||
|
||||
#include "drivers/pwm.h"
|
||||
#include "drivers/usb.h"
|
||||
#include "drivers/gmlan_alt.h"
|
||||
#include "drivers/simple_watchdog.h"
|
||||
#include "drivers/bootkick.h"
|
||||
|
||||
|
@ -34,7 +33,6 @@
|
|||
|
||||
bool check_started(void) {
|
||||
bool started = current_board->check_ignition() || ignition_can;
|
||||
ignition_seen |= started;
|
||||
return started;
|
||||
}
|
||||
|
||||
|
@ -145,8 +143,10 @@ void __attribute__ ((noinline)) enable_fpu(void) {
|
|||
|
||||
// called at 8Hz
|
||||
uint8_t loop_counter = 0U;
|
||||
uint8_t prev_harness_status = HARNESS_STATUS_NC;
|
||||
void tick_handler(void) {
|
||||
if (TICK_TIMER->SR != 0) {
|
||||
if (TICK_TIMER->SR != 0U) {
|
||||
|
||||
// siren
|
||||
current_board->set_siren((loop_counter & 1U) && (siren_enabled || (siren_countdown > 0U)));
|
||||
|
||||
|
@ -156,6 +156,17 @@ void tick_handler(void) {
|
|||
harness_tick();
|
||||
simple_watchdog_kick();
|
||||
|
||||
// re-init everything that uses harness status
|
||||
if (harness.status != prev_harness_status) {
|
||||
prev_harness_status = harness.status;
|
||||
can_set_orientation(harness.status == HARNESS_STATUS_FLIPPED);
|
||||
|
||||
// re-init everything that uses harness status
|
||||
can_init_all();
|
||||
set_safety_mode(current_safety_mode, current_safety_param);
|
||||
set_power_save_state(power_save_status);
|
||||
}
|
||||
|
||||
// decimated to 1Hz
|
||||
if (loop_counter == 0U) {
|
||||
can_live = pending_can_live;
|
||||
|
@ -187,7 +198,7 @@ void tick_handler(void) {
|
|||
bootkick_tick(check_started(), recent_heartbeat);
|
||||
|
||||
// increase heartbeat counter and cap it at the uint32 limit
|
||||
if (heartbeat_counter < __UINT32_MAX__) {
|
||||
if (heartbeat_counter < UINT32_MAX) {
|
||||
heartbeat_counter += 1U;
|
||||
}
|
||||
|
||||
|
@ -280,38 +291,6 @@ void tick_handler(void) {
|
|||
TICK_TIMER->SR = 0;
|
||||
}
|
||||
|
||||
void EXTI_IRQ_Handler(void) {
|
||||
if (check_exti_irq()) {
|
||||
exti_irq_clear();
|
||||
clock_init();
|
||||
|
||||
set_power_save_state(POWER_SAVE_STATUS_DISABLED);
|
||||
deepsleep_allowed = false;
|
||||
heartbeat_counter = 0U;
|
||||
usb_soft_disconnect(false);
|
||||
|
||||
NVIC_EnableIRQ(TICK_TIMER_IRQ);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t rtc_counter = 0;
|
||||
void RTC_WKUP_IRQ_Handler(void) {
|
||||
exti_irq_clear();
|
||||
clock_init();
|
||||
|
||||
rtc_counter++;
|
||||
if ((rtc_counter % 2U) == 0U) {
|
||||
current_board->set_led(LED_BLUE, false);
|
||||
} else {
|
||||
current_board->set_led(LED_BLUE, true);
|
||||
}
|
||||
|
||||
if (rtc_counter == __UINT8_MAX__) {
|
||||
rtc_counter = 1U;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main(void) {
|
||||
// Init interrupt table
|
||||
init_interrupts(true);
|
||||
|
@ -413,22 +392,6 @@ int main(void) {
|
|||
}
|
||||
#endif
|
||||
} else {
|
||||
if (deepsleep_allowed && !usb_enumerated && !check_started() && ignition_seen && (heartbeat_counter > 20U)) {
|
||||
usb_soft_disconnect(true);
|
||||
fan_set_power(0U);
|
||||
NVIC_DisableIRQ(TICK_TIMER_IRQ);
|
||||
delay(512000U);
|
||||
|
||||
// Init IRQs for CAN transceiver and ignition line
|
||||
exti_irq_init();
|
||||
|
||||
// Init RTC Wakeup event on EXTI22
|
||||
REGISTER_INTERRUPT(RTC_WKUP_IRQn, RTC_WKUP_IRQ_Handler, 10U, FAULT_INTERRUPT_RATE_EXTI)
|
||||
rtc_wakeup_init();
|
||||
|
||||
// STOP mode
|
||||
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
|
||||
}
|
||||
__WFI();
|
||||
SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
|
||||
}
|
||||
|
|
|
@ -9,8 +9,8 @@ int get_health_pkt(void *dat) {
|
|||
struct health_t * health = (struct health_t*)dat;
|
||||
|
||||
health->uptime_pkt = uptime_cnt;
|
||||
health->voltage_pkt = adc_get_mV(ADCCHAN_VIN) * VIN_READOUT_DIVIDER;
|
||||
health->current_pkt = current_board->read_current();
|
||||
health->voltage_pkt = current_board->read_voltage_mV();
|
||||
health->current_pkt = current_board->read_current_mA();
|
||||
|
||||
// Use the GPIO pin to determine ignition or use a CAN based logic
|
||||
health->ignition_line_pkt = (uint8_t)(current_board->check_ignition());
|
||||
|
@ -21,21 +21,20 @@ int get_health_pkt(void *dat) {
|
|||
health->safety_rx_invalid_pkt = safety_rx_invalid;
|
||||
health->tx_buffer_overflow_pkt = tx_buffer_overflow;
|
||||
health->rx_buffer_overflow_pkt = rx_buffer_overflow;
|
||||
health->gmlan_send_errs_pkt = gmlan_send_errs;
|
||||
health->car_harness_status_pkt = harness.status;
|
||||
health->safety_mode_pkt = (uint8_t)(current_safety_mode);
|
||||
health->safety_param_pkt = current_safety_param;
|
||||
health->alternative_experience_pkt = alternative_experience;
|
||||
health->power_save_enabled_pkt = power_save_status == POWER_SAVE_STATUS_ENABLED;
|
||||
health->heartbeat_lost_pkt = heartbeat_lost;
|
||||
health->safety_rx_checks_invalid = safety_rx_checks_invalid;
|
||||
health->safety_rx_checks_invalid_pkt = safety_rx_checks_invalid;
|
||||
|
||||
health->spi_checksum_error_count = spi_checksum_error_count;
|
||||
health->spi_checksum_error_count_pkt = spi_checksum_error_count;
|
||||
|
||||
health->fault_status_pkt = fault_status;
|
||||
health->faults_pkt = faults;
|
||||
|
||||
health->interrupt_load = interrupt_load;
|
||||
health->interrupt_load_pkt = interrupt_load;
|
||||
|
||||
health->fan_power = fan_state.power;
|
||||
health->fan_stall_count = fan_state.total_stall_count;
|
||||
|
@ -48,12 +47,6 @@ int get_health_pkt(void *dat) {
|
|||
return sizeof(*health);
|
||||
}
|
||||
|
||||
int get_rtc_pkt(void *dat) {
|
||||
timestamp_t t = rtc_get_time();
|
||||
(void)memcpy(dat, &t, sizeof(t));
|
||||
return sizeof(t);
|
||||
}
|
||||
|
||||
// send on serial, first byte to select the ring
|
||||
void comms_endpoint2_write(const uint8_t *data, uint32_t len) {
|
||||
uart_ring *ur = get_ring_by_number(data[0]);
|
||||
|
@ -71,7 +64,6 @@ void comms_endpoint2_write(const uint8_t *data, uint32_t len) {
|
|||
int comms_control_handler(ControlPacket_t *req, uint8_t *resp) {
|
||||
unsigned int resp_len = 0;
|
||||
uart_ring *ur = NULL;
|
||||
timestamp_t t;
|
||||
uint32_t time;
|
||||
|
||||
#ifdef DEBUG_COMMS
|
||||
|
@ -82,52 +74,6 @@ int comms_control_handler(ControlPacket_t *req, uint8_t *resp) {
|
|||
#endif
|
||||
|
||||
switch (req->request) {
|
||||
// **** 0xa0: get rtc time
|
||||
case 0xa0:
|
||||
resp_len = get_rtc_pkt(resp);
|
||||
break;
|
||||
// **** 0xa1: set rtc year
|
||||
case 0xa1:
|
||||
t = rtc_get_time();
|
||||
t.year = req->param1;
|
||||
rtc_set_time(t);
|
||||
break;
|
||||
// **** 0xa2: set rtc month
|
||||
case 0xa2:
|
||||
t = rtc_get_time();
|
||||
t.month = req->param1;
|
||||
rtc_set_time(t);
|
||||
break;
|
||||
// **** 0xa3: set rtc day
|
||||
case 0xa3:
|
||||
t = rtc_get_time();
|
||||
t.day = req->param1;
|
||||
rtc_set_time(t);
|
||||
break;
|
||||
// **** 0xa4: set rtc weekday
|
||||
case 0xa4:
|
||||
t = rtc_get_time();
|
||||
t.weekday = req->param1;
|
||||
rtc_set_time(t);
|
||||
break;
|
||||
// **** 0xa5: set rtc hour
|
||||
case 0xa5:
|
||||
t = rtc_get_time();
|
||||
t.hour = req->param1;
|
||||
rtc_set_time(t);
|
||||
break;
|
||||
// **** 0xa6: set rtc minute
|
||||
case 0xa6:
|
||||
t = rtc_get_time();
|
||||
t.minute = req->param1;
|
||||
rtc_set_time(t);
|
||||
break;
|
||||
// **** 0xa7: set rtc second
|
||||
case 0xa7:
|
||||
t = rtc_get_time();
|
||||
t.second = req->param1;
|
||||
rtc_set_time(t);
|
||||
break;
|
||||
// **** 0xa8: get microsecond timer
|
||||
case 0xa8:
|
||||
time = microsecond_timer_get();
|
||||
|
@ -264,9 +210,9 @@ int comms_control_handler(ControlPacket_t *req, uint8_t *resp) {
|
|||
case 0xd8:
|
||||
NVIC_SystemReset();
|
||||
break;
|
||||
// **** 0xdb: set GMLAN (white/grey) or OBD CAN (black) multiplexing mode
|
||||
// **** 0xdb: set OBD CAN multiplexing mode
|
||||
case 0xdb:
|
||||
if(current_board->has_obd){
|
||||
if (current_board->has_obd) {
|
||||
if (req->param1 == 1U) {
|
||||
// Enable OBD CAN
|
||||
current_board->set_can_mode(CAN_MODE_OBD_CAN2);
|
||||
|
@ -360,7 +306,7 @@ int comms_control_handler(ControlPacket_t *req, uint8_t *resp) {
|
|||
break;
|
||||
// **** 0xe5: set CAN loopback (for testing)
|
||||
case 0xe5:
|
||||
can_loopback = (req->param1 > 0U);
|
||||
can_loopback = req->param1 > 0U;
|
||||
can_init_all();
|
||||
break;
|
||||
// **** 0xe6: set custom clock source period
|
||||
|
@ -428,10 +374,6 @@ int comms_control_handler(ControlPacket_t *req, uint8_t *resp) {
|
|||
UNUSED(ret);
|
||||
}
|
||||
break;
|
||||
// **** 0xfb: allow highest power saving mode (stop) to be entered
|
||||
case 0xfb:
|
||||
deepsleep_allowed = true;
|
||||
break;
|
||||
// **** 0xfc: set CAN FD non-ISO mode
|
||||
case 0xfc:
|
||||
if ((req->param1 < PANDA_CAN_CNT) && current_board->has_canfd) {
|
||||
|
|
|
@ -6,13 +6,12 @@ void puth4(unsigned int i);
|
|||
void hexdump(const void *a, int l);
|
||||
typedef struct board board;
|
||||
typedef struct harness_configuration harness_configuration;
|
||||
void can_flip_buses(uint8_t bus1, uint8_t bus2);
|
||||
void pwm_init(TIM_TypeDef *TIM, uint8_t channel);
|
||||
void pwm_set(TIM_TypeDef *TIM, uint8_t channel, uint8_t percentage);
|
||||
|
||||
// ********************* Globals **********************
|
||||
uint8_t hw_type = 0;
|
||||
const board *current_board;
|
||||
board *current_board;
|
||||
uint32_t uptime_cnt = 0;
|
||||
bool green_led_enabled = false;
|
||||
|
||||
|
@ -21,10 +20,6 @@ uint32_t heartbeat_counter = 0;
|
|||
bool heartbeat_lost = false;
|
||||
bool heartbeat_disabled = false; // set over USB
|
||||
|
||||
// Enter deep sleep mode
|
||||
bool deepsleep_allowed = false;
|
||||
bool ignition_seen = false;
|
||||
|
||||
// siren state
|
||||
bool siren_enabled = false;
|
||||
uint32_t siren_countdown = 0; // siren plays while countdown > 0
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
obj/*
|
|
@ -1,28 +0,0 @@
|
|||
# pedal
|
||||
|
||||
This is the firmware for the comma pedal.
|
||||
|
||||
The comma pedal is a gas pedal interceptor for Honda/Acura and Toyota/Lexus. It allows you to "virtually" press the pedal and borrows a lot from panda.
|
||||
|
||||
== Test Plan ==
|
||||
|
||||
* Startup
|
||||
** Confirm STATE_FAULT_STARTUP
|
||||
* Timeout
|
||||
** Send value
|
||||
** Confirm value is output
|
||||
** Stop sending messages
|
||||
** Confirm value is passthru after 100ms
|
||||
** Confirm STATE_FAULT_TIMEOUT
|
||||
* Random values
|
||||
** Send random 6 byte messages
|
||||
** Confirm random values cause passthru
|
||||
** Confirm STATE_FAULT_BAD_CHECKSUM
|
||||
* Same message lockout
|
||||
** Send same message repeated
|
||||
** Confirm timeout behavior
|
||||
* Don't set enable
|
||||
** Confirm no output
|
||||
* Set enable and values
|
||||
** Confirm output
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
import copy
|
||||
|
||||
Import('build_project')
|
||||
|
||||
build_projects = {}
|
||||
|
||||
build_projects["pedal"] = {
|
||||
"MAIN": "main.c",
|
||||
"BOOTSTUB": "../bootstub.c",
|
||||
"STARTUP_FILE": "../stm32fx/startup_stm32f205xx.s",
|
||||
"LINKER_SCRIPT": "../stm32fx/stm32f2_flash.ld",
|
||||
"APP_START_ADDRESS": "0x8004000",
|
||||
"PROJECT_FLAGS": [
|
||||
"-mcpu=cortex-m3",
|
||||
"-msoft-float",
|
||||
"-DSTM32F2",
|
||||
"-DSTM32F205xx",
|
||||
"-O2",
|
||||
"-DPEDAL",
|
||||
],
|
||||
}
|
||||
|
||||
# build with the USB driver enabled
|
||||
build_projects["pedal_usb"] = copy.deepcopy(build_projects["pedal"])
|
||||
build_projects["pedal_usb"]["PROJECT_FLAGS"].append("-DPEDAL_USB")
|
||||
|
||||
for project_name, project in build_projects.items():
|
||||
build_project(project_name, project, [])
|
|
@ -1,8 +0,0 @@
|
|||
#!/usr/bin/env sh
|
||||
set -e
|
||||
|
||||
cd ..
|
||||
scons -u -j$(nproc)
|
||||
cd pedal
|
||||
|
||||
../../tests/pedal/enter_canloader.py obj/pedal.bin.signed
|
|
@ -1,316 +0,0 @@
|
|||
// ********************* Includes *********************
|
||||
//#define PEDAL_USB
|
||||
#include "../config.h"
|
||||
|
||||
#include "early_init.h"
|
||||
#include "crc.h"
|
||||
|
||||
#define CAN CAN1
|
||||
|
||||
#ifdef PEDAL_USB
|
||||
#include "drivers/usb.h"
|
||||
#else
|
||||
// no serial either
|
||||
void print(const char *a) {
|
||||
UNUSED(a);
|
||||
}
|
||||
void puth(unsigned int i) {
|
||||
UNUSED(i);
|
||||
}
|
||||
void puth2(unsigned int i) {
|
||||
UNUSED(i);
|
||||
}
|
||||
#endif
|
||||
|
||||
#define ENTER_BOOTLOADER_MAGIC 0xdeadbeefU
|
||||
uint32_t enter_bootloader_mode;
|
||||
|
||||
// cppcheck-suppress unusedFunction ; used in headers not included in cppcheck
|
||||
void __initialize_hardware_early(void) {
|
||||
early_initialization();
|
||||
}
|
||||
|
||||
// ********************* serial debugging *********************
|
||||
|
||||
#ifdef PEDAL_USB
|
||||
|
||||
void debug_ring_callback(uart_ring *ring) {
|
||||
char rcv;
|
||||
while (get_char(ring, &rcv) != 0) {
|
||||
(void)put_char(ring, rcv);
|
||||
}
|
||||
}
|
||||
|
||||
int comms_can_read(uint8_t *data, uint32_t max_len) {
|
||||
UNUSED(data);
|
||||
UNUSED(max_len);
|
||||
return 0;
|
||||
}
|
||||
void comms_can_write(const uint8_t *data, uint32_t len) {
|
||||
UNUSED(data);
|
||||
UNUSED(len);
|
||||
}
|
||||
void comms_endpoint2_write(const uint8_t *data, uint32_t len) {
|
||||
UNUSED(data);
|
||||
UNUSED(len);
|
||||
}
|
||||
void refresh_can_tx_slots_available(void) {}
|
||||
|
||||
int comms_control_handler(ControlPacket_t *req, uint8_t *resp) {
|
||||
unsigned int resp_len = 0;
|
||||
uart_ring *ur = NULL;
|
||||
switch (req->request) {
|
||||
// **** 0xc1: get hardware type
|
||||
case 0xc1:
|
||||
resp[0] = hw_type;
|
||||
resp_len = 1;
|
||||
break;
|
||||
// **** 0xe0: uart read
|
||||
case 0xe0:
|
||||
ur = get_ring_by_number(req->param1);
|
||||
if (!ur) {
|
||||
break;
|
||||
}
|
||||
// read
|
||||
while ((resp_len < MIN(req->length, USBPACKET_MAX_SIZE)) &&
|
||||
get_char(ur, (char*)&resp[resp_len])) {
|
||||
++resp_len;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
print("NO HANDLER ");
|
||||
puth(req->request);
|
||||
print("\n");
|
||||
break;
|
||||
}
|
||||
return resp_len;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// ***************************** can port *****************************
|
||||
|
||||
// addresses to be used on CAN
|
||||
#define CAN_GAS_INPUT 0x200
|
||||
#define CAN_GAS_OUTPUT 0x201UL
|
||||
#define CAN_GAS_SIZE 6
|
||||
#define COUNTER_CYCLE 0xFU
|
||||
|
||||
void CAN1_TX_IRQ_Handler(void) {
|
||||
// clear interrupt
|
||||
CAN->TSR |= CAN_TSR_RQCP0;
|
||||
}
|
||||
|
||||
// two independent values
|
||||
uint16_t gas_set_0 = 0;
|
||||
uint16_t gas_set_1 = 0;
|
||||
|
||||
#define MAX_TIMEOUT 10U
|
||||
uint32_t timeout = 0;
|
||||
uint32_t current_index = 0;
|
||||
|
||||
#define NO_FAULT 0U
|
||||
#define FAULT_BAD_CHECKSUM 1U
|
||||
#define FAULT_SEND 2U
|
||||
#define FAULT_SCE 3U
|
||||
#define FAULT_STARTUP 4U
|
||||
#define FAULT_TIMEOUT 5U
|
||||
#define FAULT_INVALID 6U
|
||||
uint8_t state = FAULT_STARTUP;
|
||||
const uint8_t crc_poly = 0xD5U; // standard crc8
|
||||
|
||||
void CAN1_RX0_IRQ_Handler(void) {
|
||||
while ((CAN->RF0R & CAN_RF0R_FMP0) != 0) {
|
||||
#ifdef DEBUG
|
||||
print("CAN RX\n");
|
||||
#endif
|
||||
int address = CAN->sFIFOMailBox[0].RIR >> 21;
|
||||
if (address == CAN_GAS_INPUT) {
|
||||
// softloader entry
|
||||
if (GET_MAILBOX_BYTES_04(&CAN->sFIFOMailBox[0]) == 0xdeadfaceU) {
|
||||
if (GET_MAILBOX_BYTES_48(&CAN->sFIFOMailBox[0]) == 0x0ab00b1e) {
|
||||
enter_bootloader_mode = ENTER_SOFTLOADER_MAGIC;
|
||||
NVIC_SystemReset();
|
||||
} else if (GET_MAILBOX_BYTES_48(&CAN->sFIFOMailBox[0]) == 0x02b00b1e) {
|
||||
enter_bootloader_mode = ENTER_BOOTLOADER_MAGIC;
|
||||
NVIC_SystemReset();
|
||||
} else {
|
||||
print("Failed entering Softloader or Bootloader\n");
|
||||
}
|
||||
}
|
||||
|
||||
// normal packet
|
||||
uint8_t dat[8];
|
||||
for (int i=0; i<8; i++) {
|
||||
dat[i] = GET_MAILBOX_BYTE(&CAN->sFIFOMailBox[0], i);
|
||||
}
|
||||
uint16_t value_0 = (dat[0] << 8) | dat[1];
|
||||
uint16_t value_1 = (dat[2] << 8) | dat[3];
|
||||
bool enable = ((dat[4] >> 7) & 1U) != 0U;
|
||||
uint8_t index = dat[4] & COUNTER_CYCLE;
|
||||
if (crc_checksum(dat, CAN_GAS_SIZE - 1, crc_poly) == dat[5]) {
|
||||
if (((current_index + 1U) & COUNTER_CYCLE) == index) {
|
||||
#ifdef DEBUG
|
||||
print("setting gas ");
|
||||
puth(value_0);
|
||||
print("\n");
|
||||
#endif
|
||||
if (enable) {
|
||||
gas_set_0 = value_0;
|
||||
gas_set_1 = value_1;
|
||||
} else {
|
||||
// clear the fault state if values are 0
|
||||
if ((value_0 == 0U) && (value_1 == 0U)) {
|
||||
state = NO_FAULT;
|
||||
} else {
|
||||
state = FAULT_INVALID;
|
||||
}
|
||||
gas_set_0 = 0;
|
||||
gas_set_1 = 0;
|
||||
}
|
||||
// clear the timeout
|
||||
timeout = 0;
|
||||
}
|
||||
current_index = index;
|
||||
} else {
|
||||
// wrong checksum = fault
|
||||
state = FAULT_BAD_CHECKSUM;
|
||||
}
|
||||
}
|
||||
// next
|
||||
CAN->RF0R |= CAN_RF0R_RFOM0;
|
||||
}
|
||||
}
|
||||
|
||||
void CAN1_SCE_IRQ_Handler(void) {
|
||||
state = FAULT_SCE;
|
||||
llcan_clear_send(CAN);
|
||||
}
|
||||
|
||||
uint32_t pdl0 = 0;
|
||||
uint32_t pdl1 = 0;
|
||||
unsigned int pkt_idx = 0;
|
||||
|
||||
int led_value = 0;
|
||||
|
||||
void TIM3_IRQ_Handler(void) {
|
||||
#ifdef DEBUG
|
||||
puth(TIM3->CNT);
|
||||
print(" ");
|
||||
puth(pdl0);
|
||||
print(" ");
|
||||
puth(pdl1);
|
||||
print("\n");
|
||||
#endif
|
||||
|
||||
// check timer for sending the user pedal and clearing the CAN
|
||||
if ((CAN->TSR & CAN_TSR_TME0) == CAN_TSR_TME0) {
|
||||
uint8_t dat[8];
|
||||
dat[0] = (pdl0 >> 8) & 0xFFU;
|
||||
dat[1] = (pdl0 >> 0) & 0xFFU;
|
||||
dat[2] = (pdl1 >> 8) & 0xFFU;
|
||||
dat[3] = (pdl1 >> 0) & 0xFFU;
|
||||
dat[4] = ((state & 0xFU) << 4) | pkt_idx;
|
||||
dat[5] = crc_checksum(dat, CAN_GAS_SIZE - 1, crc_poly);
|
||||
CAN->sTxMailBox[0].TDLR = dat[0] | (dat[1] << 8) | (dat[2] << 16) | (dat[3] << 24);
|
||||
CAN->sTxMailBox[0].TDHR = dat[4] | (dat[5] << 8);
|
||||
CAN->sTxMailBox[0].TDTR = 6; // len of packet is 5
|
||||
CAN->sTxMailBox[0].TIR = (CAN_GAS_OUTPUT << 21) | 1U;
|
||||
++pkt_idx;
|
||||
pkt_idx &= COUNTER_CYCLE;
|
||||
} else {
|
||||
// old can packet hasn't sent!
|
||||
state = FAULT_SEND;
|
||||
#ifdef DEBUG
|
||||
print("CAN MISS\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
// blink the LED
|
||||
current_board->set_led(LED_GREEN, led_value);
|
||||
led_value = !led_value;
|
||||
|
||||
TIM3->SR = 0;
|
||||
|
||||
// up timeout for gas set
|
||||
if (timeout == MAX_TIMEOUT) {
|
||||
state = FAULT_TIMEOUT;
|
||||
} else {
|
||||
timeout += 1U;
|
||||
}
|
||||
}
|
||||
|
||||
// ***************************** main code *****************************
|
||||
|
||||
void pedal(void) {
|
||||
// read/write
|
||||
pdl0 = adc_get_raw(ADCCHAN_ACCEL0);
|
||||
pdl1 = adc_get_raw(ADCCHAN_ACCEL1);
|
||||
|
||||
// write the pedal to the DAC
|
||||
if (state == NO_FAULT) {
|
||||
dac_set(0, MAX(gas_set_0, pdl0));
|
||||
dac_set(1, MAX(gas_set_1, pdl1));
|
||||
} else {
|
||||
dac_set(0, pdl0);
|
||||
dac_set(1, pdl1);
|
||||
}
|
||||
|
||||
watchdog_feed();
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
// Init interrupt table
|
||||
init_interrupts(true);
|
||||
|
||||
REGISTER_INTERRUPT(CAN1_TX_IRQn, CAN1_TX_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_1)
|
||||
REGISTER_INTERRUPT(CAN1_RX0_IRQn, CAN1_RX0_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_1)
|
||||
REGISTER_INTERRUPT(CAN1_SCE_IRQn, CAN1_SCE_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_1)
|
||||
|
||||
// Should run at around 732Hz (see init below)
|
||||
REGISTER_INTERRUPT(TIM3_IRQn, TIM3_IRQ_Handler, 1000U, FAULT_INTERRUPT_RATE_TIM3)
|
||||
|
||||
disable_interrupts();
|
||||
|
||||
// init devices
|
||||
clock_init();
|
||||
peripherals_init();
|
||||
detect_board_type();
|
||||
|
||||
// init board
|
||||
current_board->init();
|
||||
|
||||
#ifdef PEDAL_USB
|
||||
// enable USB
|
||||
usb_init();
|
||||
#endif
|
||||
|
||||
// pedal stuff
|
||||
dac_init();
|
||||
adc_init();
|
||||
|
||||
// init can
|
||||
bool llcan_speed_set = llcan_set_speed(CAN, 5000, false, false);
|
||||
if (!llcan_speed_set) {
|
||||
print("Failed to set llcan speed");
|
||||
}
|
||||
|
||||
bool ret = llcan_init(CAN);
|
||||
UNUSED(ret);
|
||||
|
||||
// 48mhz / 65536 ~= 732
|
||||
timer_init(TIM3, 15);
|
||||
NVIC_EnableIRQ(TIM3_IRQn);
|
||||
|
||||
watchdog_init(WATCHDOG_50_MS);
|
||||
|
||||
print("**** INTERRUPTS ON ****\n");
|
||||
enable_interrupts();
|
||||
|
||||
// main pedal loop
|
||||
while (1) {
|
||||
pedal();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
// ******************** Prototypes ********************
|
||||
void print(const char *a);
|
||||
void puth(unsigned int i);
|
||||
void puth2(unsigned int i);
|
||||
void puth4(unsigned int i);
|
||||
typedef struct board board;
|
||||
typedef struct harness_configuration harness_configuration;
|
||||
|
||||
// ********************* Globals **********************
|
||||
uint8_t hw_type = 0;
|
||||
const board *current_board;
|
|
@ -1,11 +0,0 @@
|
|||
#!/usr/bin/env sh
|
||||
set -e
|
||||
|
||||
DFU_UTIL="dfu-util"
|
||||
|
||||
cd ..
|
||||
scons -u -j$(nproc)
|
||||
cd pedal
|
||||
|
||||
$DFU_UTIL -d 0483:df11 -a 0 -s 0x08004000 -D obj/pedal.bin.signed
|
||||
$DFU_UTIL -d 0483:df11 -a 0 -s 0x08000000:leave -D obj/bootstub.pedal.bin
|
|
@ -11,9 +11,3 @@ void get_provision_chunk(uint8_t *resp) {
|
|||
(void)memcpy(resp, "unprovisioned\x00\x00\x00testing123\x00\x00\xa3\xa6\x99\xec", 0x20);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t chunk[PROVISION_CHUNK_LEN];
|
||||
bool is_provisioned(void) {
|
||||
(void)memcpy(chunk, (uint8_t *)PROVISION_CHUNK_ADDRESS, PROVISION_CHUNK_LEN);
|
||||
return (memcmp(chunk, unprovisioned_text, 0x20) != 0);
|
||||
}
|
||||
|
|
|
@ -24,3 +24,4 @@ if __name__ == "__main__":
|
|||
for s in dfu_serials:
|
||||
print("flashing", s)
|
||||
PandaDFU(s).recover()
|
||||
exit(1 if len(dfu_serials) == 0 else 0)
|
||||
|
|
|
@ -94,8 +94,8 @@ bool get_longitudinal_allowed(void) {
|
|||
// Given a CRC-8 poly, generate a static lookup table to use with a fast CRC-8
|
||||
// algorithm. Called at init time for safety modes using CRC-8.
|
||||
void gen_crc_lookup_table_8(uint8_t poly, uint8_t crc_lut[]) {
|
||||
for (int i = 0; i < 256; i++) {
|
||||
uint8_t crc = i;
|
||||
for (uint16_t i = 0U; i <= 0xFFU; i++) {
|
||||
uint8_t crc = (uint8_t)i;
|
||||
for (int j = 0; j < 8; j++) {
|
||||
if ((crc & 0x80U) != 0U) {
|
||||
crc = (uint8_t)((crc << 1) ^ poly);
|
||||
|
@ -327,8 +327,6 @@ int set_safety_hooks(uint16_t mode, uint16_t param) {
|
|||
// reset state set by safety mode
|
||||
safety_mode_cnt = 0U;
|
||||
relay_malfunction = false;
|
||||
enable_gas_interceptor = false;
|
||||
gas_interceptor_prev = 0;
|
||||
gas_pressed = false;
|
||||
gas_pressed_prev = false;
|
||||
brake_pressed = false;
|
||||
|
@ -543,10 +541,6 @@ bool longitudinal_brake_checks(int desired_brake, const LongitudinalLimits limit
|
|||
return violation;
|
||||
}
|
||||
|
||||
bool longitudinal_interceptor_checks(const CANPacket_t *to_send) {
|
||||
return !get_longitudinal_allowed() && (GET_BYTE(to_send, 0) || GET_BYTE(to_send, 1));
|
||||
}
|
||||
|
||||
// Safety checks for torque-based steering commands
|
||||
bool steer_torque_cmd_checks(int desired_torque, int steer_req, const SteeringLimits limits) {
|
||||
bool violation = false;
|
||||
|
|
|
@ -123,11 +123,12 @@ RxCheck chrysler_ram_hd_rx_checks[] = {
|
|||
const uint32_t CHRYSLER_PARAM_RAM_DT = 1U; // set for Ram DT platform
|
||||
const uint32_t CHRYSLER_PARAM_RAM_HD = 2U; // set for Ram HD platform
|
||||
|
||||
enum {
|
||||
typedef enum {
|
||||
CHRYSLER_RAM_DT,
|
||||
CHRYSLER_RAM_HD,
|
||||
CHRYSLER_PACIFICA, // plus Jeep
|
||||
} chrysler_platform = CHRYSLER_PACIFICA;
|
||||
} ChryslerPlatform;
|
||||
ChryslerPlatform chrysler_platform = CHRYSLER_PACIFICA;
|
||||
const ChryslerAddrs *chrysler_addrs = &CHRYSLER_ADDRS;
|
||||
|
||||
static uint32_t chrysler_get_checksum(const CANPacket_t *to_push) {
|
||||
|
@ -185,7 +186,7 @@ static void chrysler_rx_hook(const CANPacket_t *to_push) {
|
|||
// enter controls on rising edge of ACC, exit controls on ACC off
|
||||
const int das_3_bus = (chrysler_platform == CHRYSLER_PACIFICA) ? 0 : 2;
|
||||
if ((bus == das_3_bus) && (addr == chrysler_addrs->DAS_3)) {
|
||||
bool cruise_engaged = GET_BIT(to_push, 21U) == 1U;
|
||||
bool cruise_engaged = GET_BIT(to_push, 21U);
|
||||
pcm_cruise_check(cruise_engaged);
|
||||
}
|
||||
|
||||
|
@ -226,7 +227,7 @@ static bool chrysler_tx_hook(const CANPacket_t *to_send) {
|
|||
const SteeringLimits limits = (chrysler_platform == CHRYSLER_PACIFICA) ? CHRYSLER_STEERING_LIMITS :
|
||||
(chrysler_platform == CHRYSLER_RAM_DT) ? CHRYSLER_RAM_DT_STEERING_LIMITS : CHRYSLER_RAM_HD_STEERING_LIMITS;
|
||||
|
||||
bool steer_req = (chrysler_platform == CHRYSLER_PACIFICA) ? (GET_BIT(to_send, 4U) != 0U) : ((GET_BYTE(to_send, 3) & 0x7U) == 2U);
|
||||
bool steer_req = (chrysler_platform == CHRYSLER_PACIFICA) ? GET_BIT(to_send, 4U) : (GET_BYTE(to_send, 3) & 0x7U) == 2U;
|
||||
if (steer_torque_cmd_checks(desired_torque, steer_req, limits)) {
|
||||
tx = false;
|
||||
}
|
||||
|
|
|
@ -59,8 +59,10 @@ const CanMsg FORD_CANFD_LONG_TX_MSGS[] = {
|
|||
// this may be the cause of blocked messages
|
||||
RxCheck ford_rx_checks[] = {
|
||||
{.msg = {{FORD_BrakeSysFeatures, 0, 8, .check_checksum = true, .max_counter = 15U, .quality_flag=true, .frequency = 50U}, { 0 }, { 0 }}},
|
||||
// TODO: FORD_EngVehicleSpThrottle2 has a counter that skips by 2, understand and enable counter check
|
||||
{.msg = {{FORD_EngVehicleSpThrottle2, 0, 8, .check_checksum = true, .quality_flag=true, .frequency = 50U}, { 0 }, { 0 }}},
|
||||
// FORD_EngVehicleSpThrottle2 has a counter that either randomly skips or by 2, likely ECU bug
|
||||
// Some hybrid models also experience a bug where this checksum mismatches for one or two frames under heavy acceleration with ACC
|
||||
// It has been confirmed that the Bronco Sport's camera only disallows ACC for bad quality flags, not counters or checksums, so we match that
|
||||
{.msg = {{FORD_EngVehicleSpThrottle2, 0, 8, .check_checksum = false, .quality_flag=true, .frequency = 50U}, { 0 }, { 0 }}},
|
||||
{.msg = {{FORD_Yaw_Data_FD1, 0, 8, .check_checksum = true, .max_counter = 255U, .quality_flag=true, .frequency = 100U}, { 0 }, { 0 }}},
|
||||
// These messages have no counter or checksum
|
||||
{.msg = {{FORD_EngBrakeData, 0, 8, .frequency = 10U}, { 0 }, { 0 }}},
|
||||
|
@ -90,9 +92,6 @@ static uint32_t ford_get_checksum(const CANPacket_t *to_push) {
|
|||
if (addr == FORD_BrakeSysFeatures) {
|
||||
// Signal: VehVActlBrk_No_Cs
|
||||
chksum = GET_BYTE(to_push, 3);
|
||||
} else if (addr == FORD_EngVehicleSpThrottle2) {
|
||||
// Signal: VehVActlEng_No_Cs
|
||||
chksum = GET_BYTE(to_push, 1);
|
||||
} else if (addr == FORD_Yaw_Data_FD1) {
|
||||
// Signal: VehRollYawW_No_Cs
|
||||
chksum = GET_BYTE(to_push, 4);
|
||||
|
@ -110,11 +109,6 @@ static uint32_t ford_compute_checksum(const CANPacket_t *to_push) {
|
|||
chksum += GET_BYTE(to_push, 2) >> 6; // VehVActlBrk_D_Qf
|
||||
chksum += (GET_BYTE(to_push, 2) >> 2) & 0xFU; // VehVActlBrk_No_Cnt
|
||||
chksum = 0xFFU - chksum;
|
||||
} else if (addr == FORD_EngVehicleSpThrottle2) {
|
||||
chksum += (GET_BYTE(to_push, 2) >> 3) & 0xFU; // VehVActlEng_No_Cnt
|
||||
chksum += (GET_BYTE(to_push, 4) >> 5) & 0x3U; // VehVActlEng_D_Qf
|
||||
chksum += GET_BYTE(to_push, 6) + GET_BYTE(to_push, 7); // Veh_V_ActlEng
|
||||
chksum = 0xFFU - chksum;
|
||||
} else if (addr == FORD_Yaw_Data_FD1) {
|
||||
chksum += GET_BYTE(to_push, 0) + GET_BYTE(to_push, 1); // VehRol_W_Actl
|
||||
chksum += GET_BYTE(to_push, 2) + GET_BYTE(to_push, 3); // VehYaw_W_Actl
|
||||
|
@ -280,7 +274,7 @@ static bool ford_tx_hook(const CANPacket_t *to_send) {
|
|||
// Signal: AccBrkTot_A_Rq
|
||||
int accel = ((GET_BYTE(to_send, 0) & 0x1FU) << 8) | GET_BYTE(to_send, 1);
|
||||
// Signal: CmbbDeny_B_Actl
|
||||
int cmbb_deny = GET_BIT(to_send, 37U);
|
||||
bool cmbb_deny = GET_BIT(to_send, 37U);
|
||||
|
||||
bool violation = false;
|
||||
violation |= longitudinal_accel_checks(accel, FORD_LONG_LIMITS);
|
||||
|
@ -288,7 +282,7 @@ static bool ford_tx_hook(const CANPacket_t *to_send) {
|
|||
violation |= longitudinal_gas_checks(gas_pred, FORD_LONG_LIMITS);
|
||||
|
||||
// Safety check for stock AEB
|
||||
violation |= cmbb_deny != 0; // do not prevent stock AEB actuation
|
||||
violation |= cmbb_deny; // do not prevent stock AEB actuation
|
||||
|
||||
if (violation) {
|
||||
tx = false;
|
||||
|
@ -302,8 +296,8 @@ static bool ford_tx_hook(const CANPacket_t *to_send) {
|
|||
// Violation if resume button is pressed while controls not allowed, or
|
||||
// if cancel button is pressed when cruise isn't engaged.
|
||||
bool violation = false;
|
||||
violation |= (GET_BIT(to_send, 8U) == 1U) && !cruise_engaged_prev; // Signal: CcAslButtnCnclPress (cancel)
|
||||
violation |= (GET_BIT(to_send, 25U) == 1U) && !controls_allowed; // Signal: CcAsllButtnResPress (resume)
|
||||
violation |= GET_BIT(to_send, 8U) && !cruise_engaged_prev; // Signal: CcAslButtnCnclPress (cancel)
|
||||
violation |= GET_BIT(to_send, 25U) && !controls_allowed; // Signal: CcAsllButtnResPress (resume)
|
||||
|
||||
if (violation) {
|
||||
tx = false;
|
||||
|
|
|
@ -29,8 +29,7 @@ const int GM_STANDSTILL_THRSLD = 10; // 0.311kph
|
|||
|
||||
const CanMsg GM_ASCM_TX_MSGS[] = {{0x180, 0, 4}, {0x409, 0, 7}, {0x40A, 0, 7}, {0x2CB, 0, 8}, {0x370, 0, 6}, // pt bus
|
||||
{0xA1, 1, 7}, {0x306, 1, 8}, {0x308, 1, 7}, {0x310, 1, 2}, // obs bus
|
||||
{0x315, 2, 5}, // ch bus
|
||||
{0x104c006c, 3, 3}, {0x10400060, 3, 5}}; // gmlan
|
||||
{0x315, 2, 5}}; // ch bus
|
||||
|
||||
const CanMsg GM_CAM_TX_MSGS[] = {{0x180, 0, 4}, // pt bus
|
||||
{0x1E1, 2, 7}, {0x184, 2, 8}}; // camera bus
|
||||
|
@ -60,7 +59,11 @@ enum {
|
|||
GM_BTN_CANCEL = 6,
|
||||
};
|
||||
|
||||
enum {GM_ASCM, GM_CAM} gm_hw = GM_ASCM;
|
||||
typedef enum {
|
||||
GM_ASCM,
|
||||
GM_CAM
|
||||
} GmHardware;
|
||||
GmHardware gm_hw = GM_ASCM;
|
||||
bool gm_cam_long = false;
|
||||
bool gm_pcm_cruise = false;
|
||||
|
||||
|
@ -108,7 +111,7 @@ static void gm_rx_hook(const CANPacket_t *to_push) {
|
|||
}
|
||||
|
||||
if ((addr == 0xC9) && (gm_hw == GM_CAM)) {
|
||||
brake_pressed = GET_BIT(to_push, 40U) != 0U;
|
||||
brake_pressed = GET_BIT(to_push, 40U);
|
||||
}
|
||||
|
||||
if (addr == 0x1C4) {
|
||||
|
@ -153,7 +156,7 @@ static bool gm_tx_hook(const CANPacket_t *to_send) {
|
|||
int desired_torque = ((GET_BYTE(to_send, 0) & 0x7U) << 8) + GET_BYTE(to_send, 1);
|
||||
desired_torque = to_signed(desired_torque, 11);
|
||||
|
||||
bool steer_req = (GET_BIT(to_send, 3U) != 0U);
|
||||
bool steer_req = GET_BIT(to_send, 3U);
|
||||
|
||||
if (steer_torque_cmd_checks(desired_torque, steer_req, GM_STEERING_LIMITS)) {
|
||||
tx = false;
|
||||
|
@ -162,7 +165,7 @@ static bool gm_tx_hook(const CANPacket_t *to_send) {
|
|||
|
||||
// GAS/REGEN: safety check
|
||||
if (addr == 0x2CB) {
|
||||
bool apply = GET_BIT(to_send, 0U) != 0U;
|
||||
bool apply = GET_BIT(to_send, 0U);
|
||||
int gas_regen = ((GET_BYTE(to_send, 2) & 0x7FU) << 5) + ((GET_BYTE(to_send, 3) & 0xF8U) >> 3);
|
||||
|
||||
bool violation = false;
|
||||
|
@ -204,7 +207,7 @@ static int gm_fwd_hook(int bus_num, int addr) {
|
|||
// block lkas message and acc messages if gm_cam_long, forward all others
|
||||
bool is_lkas_msg = (addr == 0x180);
|
||||
bool is_acc_msg = (addr == 0x315) || (addr == 0x2CB) || (addr == 0x370);
|
||||
int block_msg = is_lkas_msg || (is_acc_msg && gm_cam_long);
|
||||
bool block_msg = is_lkas_msg || (is_acc_msg && gm_cam_long);
|
||||
if (!block_msg) {
|
||||
bus_fwd = 0;
|
||||
}
|
||||
|
|
|
@ -1,16 +1,9 @@
|
|||
const CanMsg HONDA_N_TX_MSGS[] = {{0xE4, 0, 5}, {0x194, 0, 4}, {0x1FA, 0, 8}, {0x30C, 0, 8}, {0x33D, 0, 5}};
|
||||
const CanMsg HONDA_N_INTERCEPTOR_TX_MSGS[] = {{0xE4, 0, 5}, {0x194, 0, 4}, {0x1FA, 0, 8}, {0x200, 0, 6}, {0x30C, 0, 8}, {0x33D, 0, 5}};
|
||||
const CanMsg HONDA_BOSCH_TX_MSGS[] = {{0xE4, 0, 5}, {0xE5, 0, 8}, {0x296, 1, 4}, {0x33D, 0, 5}, {0x33DA, 0, 5}, {0x33DB, 0, 8}}; // Bosch
|
||||
const CanMsg HONDA_BOSCH_LONG_TX_MSGS[] = {{0xE4, 1, 5}, {0x1DF, 1, 8}, {0x1EF, 1, 8}, {0x1FA, 1, 8}, {0x30C, 1, 8}, {0x33D, 1, 5}, {0x33DA, 1, 5}, {0x33DB, 1, 8}, {0x39F, 1, 8}, {0x18DAB0F1, 1, 8}}; // Bosch w/ gas and brakes
|
||||
const CanMsg HONDA_RADARLESS_TX_MSGS[] = {{0xE4, 0, 5}, {0x296, 2, 4}, {0x33D, 0, 8}}; // Bosch radarless
|
||||
const CanMsg HONDA_RADARLESS_LONG_TX_MSGS[] = {{0xE4, 0, 5}, {0x33D, 0, 8}, {0x1C8, 0, 8}, {0x30C, 0, 8}}; // Bosch radarless w/ gas and brakes
|
||||
|
||||
// panda interceptor threshold needs to be equivalent to openpilot threshold to avoid controls mismatches
|
||||
// If thresholds are mismatched then it is possible for panda to see the gas fall and rise while openpilot is in the pre-enabled state
|
||||
// Threshold calculated from DBC gains: round(((83.3 / 0.253984064) + (83.3 / 0.126992032)) / 2) = 492
|
||||
const int HONDA_GAS_INTERCEPTOR_THRESHOLD = 492;
|
||||
#define HONDA_GET_INTERCEPTOR(msg) (((GET_BYTE((msg), 0) << 8) + GET_BYTE((msg), 1) + (GET_BYTE((msg), 2) << 8) + GET_BYTE((msg), 3)) / 2U) // avg between 2 tracks
|
||||
|
||||
const LongitudinalLimits HONDA_BOSCH_LONG_LIMITS = {
|
||||
.max_accel = 200, // accel is used for brakes
|
||||
.min_accel = -350,
|
||||
|
@ -47,11 +40,6 @@ RxCheck honda_common_rx_checks[] = {
|
|||
HONDA_COMMON_RX_CHECKS(0)
|
||||
};
|
||||
|
||||
RxCheck honda_common_interceptor_rx_checks[] = {
|
||||
HONDA_COMMON_RX_CHECKS(0)
|
||||
{.msg = {{0x201, 0, 6, .check_checksum = false, .max_counter = 15U, .frequency = 50U}, { 0 }, { 0 }}},
|
||||
};
|
||||
|
||||
RxCheck honda_common_alt_brake_rx_checks[] = {
|
||||
HONDA_COMMON_RX_CHECKS(0)
|
||||
HONDA_ALT_BRAKE_ADDR_CHECK(0)
|
||||
|
@ -62,11 +50,6 @@ RxCheck honda_nidec_alt_rx_checks[] = {
|
|||
HONDA_COMMON_NO_SCM_FEEDBACK_RX_CHECKS(0)
|
||||
};
|
||||
|
||||
RxCheck honda_nidec_alt_interceptor_rx_checks[] = {
|
||||
HONDA_COMMON_NO_SCM_FEEDBACK_RX_CHECKS(0)
|
||||
{.msg = {{0x201, 0, 6, .check_checksum = false, .max_counter = 15U, .frequency = 50U}, { 0 }, { 0 }}},
|
||||
};
|
||||
|
||||
// Bosch has pt on bus 1, verified 0x1A6 does not exist
|
||||
RxCheck honda_bosch_rx_checks[] = {
|
||||
HONDA_COMMON_RX_CHECKS(1)
|
||||
|
@ -81,7 +64,6 @@ const uint16_t HONDA_PARAM_ALT_BRAKE = 1;
|
|||
const uint16_t HONDA_PARAM_BOSCH_LONG = 2;
|
||||
const uint16_t HONDA_PARAM_NIDEC_ALT = 4;
|
||||
const uint16_t HONDA_PARAM_RADARLESS = 8;
|
||||
const uint16_t HONDA_PARAM_GAS_INTERCEPTOR = 16;
|
||||
|
||||
enum {
|
||||
HONDA_BTN_NONE = 0,
|
||||
|
@ -97,7 +79,8 @@ bool honda_alt_brake_msg = false;
|
|||
bool honda_fwd_brake = false;
|
||||
bool honda_bosch_long = false;
|
||||
bool honda_bosch_radarless = false;
|
||||
enum {HONDA_NIDEC, HONDA_BOSCH} honda_hw = HONDA_NIDEC;
|
||||
typedef enum {HONDA_NIDEC, HONDA_BOSCH} HondaHw;
|
||||
HondaHw honda_hw = HONDA_NIDEC;
|
||||
|
||||
|
||||
int honda_get_pt_bus(void) {
|
||||
|
@ -114,11 +97,11 @@ static uint32_t honda_compute_checksum(const CANPacket_t *to_push) {
|
|||
uint8_t checksum = 0U;
|
||||
unsigned int addr = GET_ADDR(to_push);
|
||||
while (addr > 0U) {
|
||||
checksum += (addr & 0xFU); addr >>= 4;
|
||||
checksum += (uint8_t)(addr & 0xFU); addr >>= 4;
|
||||
}
|
||||
for (int j = 0; j < len; j++) {
|
||||
uint8_t byte = GET_BYTE(to_push, j);
|
||||
checksum += (byte & 0xFU) + (byte >> 4U);
|
||||
checksum += (uint8_t)(byte & 0xFU) + (byte >> 4U);
|
||||
if (j == (len - 1)) {
|
||||
checksum -= (byte & 0xFU); // remove checksum in message
|
||||
}
|
||||
|
@ -127,26 +110,15 @@ static uint32_t honda_compute_checksum(const CANPacket_t *to_push) {
|
|||
}
|
||||
|
||||
static uint8_t honda_get_counter(const CANPacket_t *to_push) {
|
||||
int addr = GET_ADDR(to_push);
|
||||
|
||||
uint8_t cnt = 0U;
|
||||
if (addr == 0x201) {
|
||||
// Signal: COUNTER_PEDAL
|
||||
cnt = GET_BYTE(to_push, 4) & 0x0FU;
|
||||
} else {
|
||||
int counter_byte = GET_LEN(to_push) - 1U;
|
||||
cnt = (GET_BYTE(to_push, counter_byte) >> 4U) & 0x3U;
|
||||
}
|
||||
return cnt;
|
||||
int counter_byte = GET_LEN(to_push) - 1U;
|
||||
return (GET_BYTE(to_push, counter_byte) >> 4U) & 0x3U;
|
||||
}
|
||||
|
||||
static void honda_rx_hook(const CANPacket_t *to_push) {
|
||||
const bool pcm_cruise = ((honda_hw == HONDA_BOSCH) && !honda_bosch_long) || \
|
||||
((honda_hw == HONDA_NIDEC) && !enable_gas_interceptor);
|
||||
const bool pcm_cruise = ((honda_hw == HONDA_BOSCH) && !honda_bosch_long) || (honda_hw == HONDA_NIDEC);
|
||||
int pt_bus = honda_get_pt_bus();
|
||||
|
||||
int addr = GET_ADDR(to_push);
|
||||
int len = GET_LEN(to_push);
|
||||
int bus = GET_BUS(to_push);
|
||||
|
||||
// sample speed
|
||||
|
@ -166,7 +138,7 @@ static void honda_rx_hook(const CANPacket_t *to_push) {
|
|||
|
||||
// enter controls when PCM enters cruise state
|
||||
if (pcm_cruise && (addr == 0x17C)) {
|
||||
const bool cruise_engaged = GET_BIT(to_push, 38U) != 0U;
|
||||
const bool cruise_engaged = GET_BIT(to_push, 38U);
|
||||
// engage on rising edge
|
||||
if (cruise_engaged && !cruise_engaged_prev) {
|
||||
controls_allowed = true;
|
||||
|
@ -207,34 +179,25 @@ static void honda_rx_hook(const CANPacket_t *to_push) {
|
|||
// accord, crv: 0x1BE
|
||||
if (honda_alt_brake_msg) {
|
||||
if (addr == 0x1BE) {
|
||||
brake_pressed = GET_BIT(to_push, 4U) != 0U;
|
||||
brake_pressed = GET_BIT(to_push, 4U);
|
||||
}
|
||||
} else {
|
||||
if (addr == 0x17C) {
|
||||
// also if brake switch is 1 for two CAN frames, as brake pressed is delayed
|
||||
const bool brake_switch = GET_BIT(to_push, 32U) != 0U;
|
||||
brake_pressed = (GET_BIT(to_push, 53U) != 0U) || (brake_switch && honda_brake_switch_prev);
|
||||
const bool brake_switch = GET_BIT(to_push, 32U);
|
||||
brake_pressed = (GET_BIT(to_push, 53U)) || (brake_switch && honda_brake_switch_prev);
|
||||
honda_brake_switch_prev = brake_switch;
|
||||
}
|
||||
}
|
||||
|
||||
// length check because bosch hardware also uses this id (0x201 w/ len = 8)
|
||||
if ((addr == 0x201) && (len == 6) && enable_gas_interceptor) {
|
||||
int gas_interceptor = HONDA_GET_INTERCEPTOR(to_push);
|
||||
gas_pressed = gas_interceptor > HONDA_GAS_INTERCEPTOR_THRESHOLD;
|
||||
gas_interceptor_prev = gas_interceptor;
|
||||
}
|
||||
|
||||
if (!enable_gas_interceptor) {
|
||||
if (addr == 0x17C) {
|
||||
gas_pressed = GET_BYTE(to_push, 0) != 0U;
|
||||
}
|
||||
if (addr == 0x17C) {
|
||||
gas_pressed = GET_BYTE(to_push, 0) != 0U;
|
||||
}
|
||||
|
||||
// disable stock Honda AEB in alternative experience
|
||||
if (!(alternative_experience & ALT_EXP_DISABLE_STOCK_AEB)) {
|
||||
if ((bus == 2) && (addr == 0x1FA)) {
|
||||
bool honda_stock_aeb = GET_BIT(to_push, 29U) != 0U;
|
||||
bool honda_stock_aeb = GET_BIT(to_push, 29U);
|
||||
int honda_stock_brake = (GET_BYTE(to_push, 0) << 2) | (GET_BYTE(to_push, 1) >> 6);
|
||||
|
||||
// Forward AEB when stock braking is higher than openpilot braking
|
||||
|
@ -346,13 +309,6 @@ static bool honda_tx_hook(const CANPacket_t *to_send) {
|
|||
}
|
||||
}
|
||||
|
||||
// GAS: safety check (interceptor)
|
||||
if (addr == 0x200) {
|
||||
if (longitudinal_interceptor_checks(to_send)) {
|
||||
tx = false;
|
||||
}
|
||||
}
|
||||
|
||||
// FORCE CANCEL: safety check only relevant when spamming the cancel button in Bosch HW
|
||||
// ensuring that only the cancel button press is sent (VAL 2) when controls are off.
|
||||
// This avoids unintended engagements while still allowing resume spam
|
||||
|
@ -380,24 +336,18 @@ static safety_config honda_nidec_init(uint16_t param) {
|
|||
honda_alt_brake_msg = false;
|
||||
honda_bosch_long = false;
|
||||
honda_bosch_radarless = false;
|
||||
enable_gas_interceptor = GET_FLAG(param, HONDA_PARAM_GAS_INTERCEPTOR);
|
||||
|
||||
safety_config ret;
|
||||
|
||||
bool enable_nidec_alt = GET_FLAG(param, HONDA_PARAM_NIDEC_ALT);
|
||||
if (enable_nidec_alt) {
|
||||
enable_gas_interceptor ? SET_RX_CHECKS(honda_nidec_alt_interceptor_rx_checks, ret) : \
|
||||
SET_RX_CHECKS(honda_nidec_alt_rx_checks, ret);
|
||||
} else {
|
||||
enable_gas_interceptor ? SET_RX_CHECKS(honda_common_interceptor_rx_checks, ret) : \
|
||||
SET_RX_CHECKS(honda_common_rx_checks, ret);
|
||||
}
|
||||
|
||||
if (enable_gas_interceptor) {
|
||||
SET_TX_MSGS(HONDA_N_INTERCEPTOR_TX_MSGS, ret);
|
||||
bool enable_nidec_alt = GET_FLAG(param, HONDA_PARAM_NIDEC_ALT);
|
||||
|
||||
if (enable_nidec_alt) {
|
||||
SET_RX_CHECKS(honda_nidec_alt_rx_checks, ret);
|
||||
} else {
|
||||
SET_TX_MSGS(HONDA_N_TX_MSGS, ret);
|
||||
SET_RX_CHECKS(honda_common_rx_checks, ret);
|
||||
}
|
||||
SET_TX_MSGS(HONDA_N_TX_MSGS, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -465,8 +415,8 @@ static int honda_bosch_fwd_hook(int bus_num, int addr) {
|
|||
bus_fwd = 2;
|
||||
}
|
||||
if (bus_num == 2) {
|
||||
int is_lkas_msg = (addr == 0xE4) || (addr == 0xE5) || (addr == 0x33D) || (addr == 0x33DA) || (addr == 0x33DB);
|
||||
int is_acc_msg = ((addr == 0x1C8) || (addr == 0x30C)) && honda_bosch_radarless && honda_bosch_long;
|
||||
bool is_lkas_msg = (addr == 0xE4) || (addr == 0xE5) || (addr == 0x33D) || (addr == 0x33DA) || (addr == 0x33DB);
|
||||
bool is_acc_msg = ((addr == 0x1C8) || (addr == 0x30C)) && honda_bosch_radarless && honda_bosch_long;
|
||||
bool block_msg = is_lkas_msg || is_acc_msg;
|
||||
if (!block_msg) {
|
||||
bus_fwd = 0;
|
||||
|
|
|
@ -178,7 +178,7 @@ static void hyundai_rx_hook(const CANPacket_t *to_push) {
|
|||
// ACC steering wheel buttons
|
||||
if (addr == 0x4F1) {
|
||||
int cruise_button = GET_BYTE(to_push, 0) & 0x7U;
|
||||
int main_button = GET_BIT(to_push, 3U);
|
||||
bool main_button = GET_BIT(to_push, 3U);
|
||||
hyundai_common_cruise_buttons_check(cruise_button, main_button);
|
||||
}
|
||||
|
||||
|
@ -221,10 +221,10 @@ static bool hyundai_tx_hook(const CANPacket_t *to_send) {
|
|||
// FCA11: Block any potential actuation
|
||||
if (addr == 0x38D) {
|
||||
int CR_VSM_DecCmd = GET_BYTE(to_send, 1);
|
||||
int FCA_CmdAct = GET_BIT(to_send, 20U);
|
||||
int CF_VSM_DecCmdAct = GET_BIT(to_send, 31U);
|
||||
bool FCA_CmdAct = GET_BIT(to_send, 20U);
|
||||
bool CF_VSM_DecCmdAct = GET_BIT(to_send, 31U);
|
||||
|
||||
if ((CR_VSM_DecCmd != 0) || (FCA_CmdAct != 0) || (CF_VSM_DecCmdAct != 0)) {
|
||||
if ((CR_VSM_DecCmd != 0) || FCA_CmdAct || CF_VSM_DecCmdAct) {
|
||||
tx = false;
|
||||
}
|
||||
}
|
||||
|
@ -235,14 +235,14 @@ static bool hyundai_tx_hook(const CANPacket_t *to_send) {
|
|||
int desired_accel_val = ((GET_BYTE(to_send, 5) << 3) | (GET_BYTE(to_send, 4) >> 5)) - 1023U;
|
||||
|
||||
int aeb_decel_cmd = GET_BYTE(to_send, 2);
|
||||
int aeb_req = GET_BIT(to_send, 54U);
|
||||
bool aeb_req = GET_BIT(to_send, 54U);
|
||||
|
||||
bool violation = false;
|
||||
|
||||
violation |= longitudinal_accel_checks(desired_accel_raw, HYUNDAI_LONG_LIMITS);
|
||||
violation |= longitudinal_accel_checks(desired_accel_val, HYUNDAI_LONG_LIMITS);
|
||||
violation |= (aeb_decel_cmd != 0);
|
||||
violation |= (aeb_req != 0);
|
||||
violation |= aeb_req;
|
||||
|
||||
if (violation) {
|
||||
tx = false;
|
||||
|
@ -252,7 +252,7 @@ static bool hyundai_tx_hook(const CANPacket_t *to_send) {
|
|||
// LKA STEER: safety check
|
||||
if (addr == 0x340) {
|
||||
int desired_torque = ((GET_BYTES(to_send, 0, 4) >> 16) & 0x7ffU) - 1024U;
|
||||
bool steer_req = GET_BIT(to_send, 27U) != 0U;
|
||||
bool steer_req = GET_BIT(to_send, 27U);
|
||||
|
||||
const SteeringLimits limits = hyundai_alt_limits ? HYUNDAI_STEERING_LIMITS_ALT : HYUNDAI_STEERING_LIMITS;
|
||||
if (steer_torque_cmd_checks(desired_torque, steer_req, limits)) {
|
||||
|
|
|
@ -170,7 +170,7 @@ static void hyundai_canfd_rx_hook(const CANPacket_t *to_push) {
|
|||
// cruise buttons
|
||||
const int button_addr = hyundai_canfd_alt_buttons ? 0x1aa : 0x1cf;
|
||||
if (addr == button_addr) {
|
||||
int main_button = 0;
|
||||
bool main_button = false;
|
||||
int cruise_button = 0;
|
||||
if (addr == 0x1cf) {
|
||||
cruise_button = GET_BYTE(to_push, 2) & 0x7U;
|
||||
|
@ -186,15 +186,15 @@ static void hyundai_canfd_rx_hook(const CANPacket_t *to_push) {
|
|||
if ((addr == 0x35) && hyundai_ev_gas_signal) {
|
||||
gas_pressed = GET_BYTE(to_push, 5) != 0U;
|
||||
} else if ((addr == 0x105) && hyundai_hybrid_gas_signal) {
|
||||
gas_pressed = (GET_BIT(to_push, 103U) != 0U) || (GET_BYTE(to_push, 13) != 0U) || (GET_BIT(to_push, 112U) != 0U);
|
||||
gas_pressed = GET_BIT(to_push, 103U) || (GET_BYTE(to_push, 13) != 0U) || GET_BIT(to_push, 112U);
|
||||
} else if ((addr == 0x100) && !hyundai_ev_gas_signal && !hyundai_hybrid_gas_signal) {
|
||||
gas_pressed = GET_BIT(to_push, 176U) != 0U;
|
||||
gas_pressed = GET_BIT(to_push, 176U);
|
||||
} else {
|
||||
}
|
||||
|
||||
// brake press
|
||||
if (addr == 0x175) {
|
||||
brake_pressed = GET_BIT(to_push, 81U) != 0U;
|
||||
brake_pressed = GET_BIT(to_push, 81U);
|
||||
}
|
||||
|
||||
// vehicle moving
|
||||
|
@ -235,7 +235,7 @@ static bool hyundai_canfd_tx_hook(const CANPacket_t *to_send) {
|
|||
const int steer_addr = (hyundai_canfd_hda2 && !hyundai_longitudinal) ? hyundai_canfd_hda2_get_lkas_addr() : 0x12a;
|
||||
if (addr == steer_addr) {
|
||||
int desired_torque = (((GET_BYTE(to_send, 6) & 0xFU) << 7U) | (GET_BYTE(to_send, 5) >> 1U)) - 1024U;
|
||||
bool steer_req = GET_BIT(to_send, 52U) != 0U;
|
||||
bool steer_req = GET_BIT(to_send, 52U);
|
||||
|
||||
if (steer_torque_cmd_checks(desired_torque, steer_req, HYUNDAI_CANFD_STEERING_LIMITS)) {
|
||||
tx = false;
|
||||
|
|
|
@ -45,7 +45,7 @@ void hyundai_common_init(uint16_t param) {
|
|||
#endif
|
||||
}
|
||||
|
||||
void hyundai_common_cruise_state_check(const int cruise_engaged) {
|
||||
void hyundai_common_cruise_state_check(const bool cruise_engaged) {
|
||||
// some newer HKG models can re-enable after spamming cancel button,
|
||||
// so keep track of user button presses to deny engagement if no interaction
|
||||
|
||||
|
@ -62,9 +62,8 @@ void hyundai_common_cruise_state_check(const int cruise_engaged) {
|
|||
}
|
||||
}
|
||||
|
||||
void hyundai_common_cruise_buttons_check(const int cruise_button, const int main_button) {
|
||||
if ((cruise_button == HYUNDAI_BTN_RESUME) || (cruise_button == HYUNDAI_BTN_SET) || (cruise_button == HYUNDAI_BTN_CANCEL) ||
|
||||
(main_button != 0)) {
|
||||
void hyundai_common_cruise_buttons_check(const int cruise_button, const bool main_button) {
|
||||
if ((cruise_button == HYUNDAI_BTN_RESUME) || (cruise_button == HYUNDAI_BTN_SET) || (cruise_button == HYUNDAI_BTN_CANCEL) || main_button) {
|
||||
hyundai_last_button_interaction = 0U;
|
||||
} else {
|
||||
hyundai_last_button_interaction = MIN(hyundai_last_button_interaction + 1U, HYUNDAI_PREV_BUTTON_SAMPLES);
|
||||
|
|
|
@ -129,7 +129,7 @@ static int nissan_fwd_hook(int bus_num, int addr) {
|
|||
int bus_fwd = -1;
|
||||
|
||||
if (bus_num == 0) {
|
||||
int block_msg = (addr == 0x280); // CANCEL_MSG
|
||||
bool block_msg = (addr == 0x280); // CANCEL_MSG
|
||||
if (!block_msg) {
|
||||
bus_fwd = 2; // ADAS
|
||||
}
|
||||
|
@ -137,7 +137,7 @@ static int nissan_fwd_hook(int bus_num, int addr) {
|
|||
|
||||
if (bus_num == 2) {
|
||||
// 0x169 is LKAS, 0x2b1 LKAS_HUD, 0x4cc LKAS_HUD_INFO_MSG
|
||||
int block_msg = ((addr == 0x169) || (addr == 0x2b1) || (addr == 0x4cc));
|
||||
bool block_msg = ((addr == 0x169) || (addr == 0x2b1) || (addr == 0x4cc));
|
||||
if (!block_msg) {
|
||||
bus_fwd = 0; // V-CAN
|
||||
}
|
||||
|
|
|
@ -152,7 +152,7 @@ static void subaru_rx_hook(const CANPacket_t *to_push) {
|
|||
|
||||
// enter controls on rising edge of ACC, exit controls on ACC off
|
||||
if ((addr == MSG_SUBARU_CruiseControl) && (bus == alt_main_bus)) {
|
||||
bool cruise_engaged = GET_BIT(to_push, 41U) != 0U;
|
||||
bool cruise_engaged = GET_BIT(to_push, 41U);
|
||||
pcm_cruise_check(cruise_engaged);
|
||||
}
|
||||
|
||||
|
@ -169,7 +169,7 @@ static void subaru_rx_hook(const CANPacket_t *to_push) {
|
|||
}
|
||||
|
||||
if ((addr == MSG_SUBARU_Brake_Status) && (bus == alt_main_bus)) {
|
||||
brake_pressed = GET_BIT(to_push, 62U) != 0U;
|
||||
brake_pressed = GET_BIT(to_push, 62U);
|
||||
}
|
||||
|
||||
if ((addr == MSG_SUBARU_Throttle) && (bus == SUBARU_MAIN_BUS)) {
|
||||
|
@ -189,7 +189,7 @@ static bool subaru_tx_hook(const CANPacket_t *to_send) {
|
|||
int desired_torque = ((GET_BYTES(to_send, 0, 4) >> 16) & 0x1FFFU);
|
||||
desired_torque = -1 * to_signed(desired_torque, 13);
|
||||
|
||||
bool steer_req = GET_BIT(to_send, 29U) != 0U;
|
||||
bool steer_req = GET_BIT(to_send, 29U);
|
||||
|
||||
const SteeringLimits limits = subaru_gen2 ? SUBARU_GEN2_STEERING_LIMITS : SUBARU_STEERING_LIMITS;
|
||||
violation |= steer_torque_cmd_checks(desired_torque, steer_req, limits);
|
||||
|
@ -204,7 +204,7 @@ static bool subaru_tx_hook(const CANPacket_t *to_send) {
|
|||
// check es_distance cruise_throttle limits
|
||||
if (addr == MSG_SUBARU_ES_Distance) {
|
||||
int cruise_throttle = (GET_BYTES(to_send, 2, 2) & 0x1FFFU);
|
||||
bool cruise_cancel = GET_BIT(to_send, 56U) != 0U;
|
||||
bool cruise_cancel = GET_BIT(to_send, 56U);
|
||||
|
||||
if (subaru_longitudinal) {
|
||||
violation |= longitudinal_gas_checks(cruise_throttle, SUBARU_LONG_LIMITS);
|
||||
|
|
|
@ -56,7 +56,7 @@ static void subaru_preglobal_rx_hook(const CANPacket_t *to_push) {
|
|||
|
||||
// enter controls on rising edge of ACC, exit controls on ACC off
|
||||
if (addr == MSG_SUBARU_PG_CruiseControl) {
|
||||
bool cruise_engaged = GET_BIT(to_push, 49U) != 0U;
|
||||
bool cruise_engaged = GET_BIT(to_push, 49U);
|
||||
pcm_cruise_check(cruise_engaged);
|
||||
}
|
||||
|
||||
|
@ -86,7 +86,7 @@ static bool subaru_preglobal_tx_hook(const CANPacket_t *to_send) {
|
|||
int desired_torque = ((GET_BYTES(to_send, 0, 4) >> 8) & 0x1FFFU);
|
||||
desired_torque = -1 * to_signed(desired_torque, 13);
|
||||
|
||||
bool steer_req = (GET_BIT(to_send, 24U) != 0U);
|
||||
bool steer_req = GET_BIT(to_send, 24U);
|
||||
|
||||
if (steer_torque_cmd_checks(desired_torque, steer_req, SUBARU_PG_STEERING_LIMITS)) {
|
||||
tx = false;
|
||||
|
@ -104,7 +104,7 @@ static int subaru_preglobal_fwd_hook(int bus_num, int addr) {
|
|||
}
|
||||
|
||||
if (bus_num == SUBARU_PG_CAM_BUS) {
|
||||
int block_msg = ((addr == MSG_SUBARU_PG_ES_Distance) || (addr == MSG_SUBARU_PG_ES_LKAS));
|
||||
bool block_msg = ((addr == MSG_SUBARU_PG_ES_Distance) || (addr == MSG_SUBARU_PG_ES_LKAS));
|
||||
if (!block_msg) {
|
||||
bus_fwd = SUBARU_PG_MAIN_BUS; // Main CAN
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ const LongitudinalLimits TESLA_LONG_LIMITS = {
|
|||
|
||||
const int TESLA_FLAG_POWERTRAIN = 1;
|
||||
const int TESLA_FLAG_LONGITUDINAL_CONTROL = 2;
|
||||
const int TESLA_FLAG_RAVEN = 4;
|
||||
|
||||
const CanMsg TESLA_TX_MSGS[] = {
|
||||
{0x488, 0, 4}, // DAS_steeringControl
|
||||
|
@ -41,6 +42,16 @@ RxCheck tesla_rx_checks[] = {
|
|||
{.msg = {{0x318, 0, 8, .frequency = 10U}, { 0 }, { 0 }}}, // GTW_carState
|
||||
};
|
||||
|
||||
RxCheck tesla_raven_rx_checks[] = {
|
||||
{.msg = {{0x2b9, 2, 8, .frequency = 25U}, { 0 }, { 0 }}}, // DAS_control
|
||||
{.msg = {{0x131, 2, 8, .frequency = 100U}, { 0 }, { 0 }}}, // EPAS3P_sysStatus
|
||||
{.msg = {{0x108, 0, 8, .frequency = 100U}, { 0 }, { 0 }}}, // DI_torque1
|
||||
{.msg = {{0x118, 0, 6, .frequency = 100U}, { 0 }, { 0 }}}, // DI_torque2
|
||||
{.msg = {{0x20a, 0, 8, .frequency = 50U}, { 0 }, { 0 }}}, // BrakeMessage
|
||||
{.msg = {{0x368, 0, 8, .frequency = 10U}, { 0 }, { 0 }}}, // DI_state
|
||||
{.msg = {{0x318, 0, 8, .frequency = 10U}, { 0 }, { 0 }}}, // GTW_carState
|
||||
};
|
||||
|
||||
RxCheck tesla_pt_rx_checks[] = {
|
||||
{.msg = {{0x106, 0, 8, .frequency = 100U}, { 0 }, { 0 }}}, // DI_torque1
|
||||
{.msg = {{0x116, 0, 6, .frequency = 100U}, { 0 }, { 0 }}}, // DI_torque2
|
||||
|
@ -51,6 +62,7 @@ RxCheck tesla_pt_rx_checks[] = {
|
|||
|
||||
bool tesla_longitudinal = false;
|
||||
bool tesla_powertrain = false; // Are we the second panda intercepting the powertrain bus?
|
||||
bool tesla_raven = false;
|
||||
|
||||
bool tesla_stock_aeb = false;
|
||||
|
||||
|
@ -58,16 +70,16 @@ static void tesla_rx_hook(const CANPacket_t *to_push) {
|
|||
int bus = GET_BUS(to_push);
|
||||
int addr = GET_ADDR(to_push);
|
||||
|
||||
if(bus == 0) {
|
||||
if (!tesla_powertrain) {
|
||||
if(addr == 0x370) {
|
||||
// Steering angle: (0.1 * val) - 819.2 in deg.
|
||||
// Store it 1/10 deg to match steering request
|
||||
int angle_meas_new = (((GET_BYTE(to_push, 4) & 0x3FU) << 8) | GET_BYTE(to_push, 5)) - 8192U;
|
||||
update_sample(&angle_meas, angle_meas_new);
|
||||
}
|
||||
if (!tesla_powertrain) {
|
||||
if((!tesla_raven && (addr == 0x370) && (bus == 0)) || (tesla_raven && (addr == 0x131) && (bus == 2))) {
|
||||
// Steering angle: (0.1 * val) - 819.2 in deg.
|
||||
// Store it 1/10 deg to match steering request
|
||||
int angle_meas_new = (((GET_BYTE(to_push, 4) & 0x3FU) << 8) | GET_BYTE(to_push, 5)) - 8192U;
|
||||
update_sample(&angle_meas, angle_meas_new);
|
||||
}
|
||||
}
|
||||
|
||||
if(bus == 0) {
|
||||
if(addr == (tesla_powertrain ? 0x116 : 0x118)) {
|
||||
// Vehicle speed: ((0.05 * val) - 25) * MPH_TO_MPS
|
||||
float speed = (((((GET_BYTE(to_push, 3) & 0x0FU) << 8) | (GET_BYTE(to_push, 2))) * 0.05) - 25) * 0.447;
|
||||
|
@ -206,12 +218,15 @@ static int tesla_fwd_hook(int bus_num, int addr) {
|
|||
static safety_config tesla_init(uint16_t param) {
|
||||
tesla_powertrain = GET_FLAG(param, TESLA_FLAG_POWERTRAIN);
|
||||
tesla_longitudinal = GET_FLAG(param, TESLA_FLAG_LONGITUDINAL_CONTROL);
|
||||
tesla_raven = GET_FLAG(param, TESLA_FLAG_RAVEN);
|
||||
|
||||
tesla_stock_aeb = false;
|
||||
|
||||
safety_config ret;
|
||||
if (tesla_powertrain) {
|
||||
ret = BUILD_SAFETY_CFG(tesla_pt_rx_checks, TESLA_PT_TX_MSGS);
|
||||
} else if (tesla_raven) {
|
||||
ret = BUILD_SAFETY_CFG(tesla_raven_rx_checks, TESLA_TX_MSGS);
|
||||
} else {
|
||||
ret = BUILD_SAFETY_CFG(tesla_rx_checks, TESLA_TX_MSGS);
|
||||
}
|
||||
|
|
|
@ -37,24 +37,23 @@ const LongitudinalLimits TOYOTA_LONG_LIMITS = {
|
|||
.min_accel = -3500, // -3.5 m/s2
|
||||
};
|
||||
|
||||
// panda interceptor threshold needs to be equivalent to openpilot threshold to avoid controls mismatches
|
||||
// If thresholds are mismatched then it is possible for panda to see the gas fall and rise while openpilot is in the pre-enabled state
|
||||
// Threshold calculated from DBC gains: round((((15 + 75.555) / 0.159375) + ((15 + 151.111) / 0.159375)) / 2) = 805
|
||||
const int TOYOTA_GAS_INTERCEPTOR_THRSLD = 805;
|
||||
#define TOYOTA_GET_INTERCEPTOR(msg) (((GET_BYTE((msg), 0) << 8) + GET_BYTE((msg), 1) + (GET_BYTE((msg), 2) << 8) + GET_BYTE((msg), 3)) / 2U) // avg between 2 tracks
|
||||
// Stock longitudinal
|
||||
#define TOYOTA_COMMON_TX_MSGS \
|
||||
{0x2E4, 0, 5}, {0x191, 0, 8}, {0x412, 0, 8}, {0x343, 0, 8}, {0x1D2, 0, 8}, /* LKAS + LTA + ACC & PCM cancel cmds */ \
|
||||
|
||||
#define TOYOTA_COMMON_TX_MSGS \
|
||||
#define TOYOTA_COMMON_LONG_TX_MSGS \
|
||||
TOYOTA_COMMON_TX_MSGS \
|
||||
{0x283, 0, 7}, {0x2E6, 0, 8}, {0x2E7, 0, 8}, {0x33E, 0, 7}, {0x344, 0, 8}, {0x365, 0, 7}, {0x366, 0, 7}, {0x4CB, 0, 8}, /* DSU bus 0 */ \
|
||||
{0x128, 1, 6}, {0x141, 1, 4}, {0x160, 1, 8}, {0x161, 1, 7}, {0x470, 1, 4}, /* DSU bus 1 */ \
|
||||
{0x2E4, 0, 5}, {0x191, 0, 8}, {0x411, 0, 8}, {0x412, 0, 8}, {0x343, 0, 8}, {0x1D2, 0, 8}, /* LKAS + ACC */ \
|
||||
{0x411, 0, 8}, /* PCS_HUD */ \
|
||||
{0x750, 0, 8}, /* radar diagnostic address */ \
|
||||
|
||||
const CanMsg TOYOTA_TX_MSGS[] = {
|
||||
TOYOTA_COMMON_TX_MSGS
|
||||
};
|
||||
|
||||
const CanMsg TOYOTA_INTERCEPTOR_TX_MSGS[] = {
|
||||
TOYOTA_COMMON_TX_MSGS
|
||||
{0x200, 0, 6}, // gas interceptor
|
||||
const CanMsg TOYOTA_LONG_TX_MSGS[] = {
|
||||
TOYOTA_COMMON_LONG_TX_MSGS
|
||||
};
|
||||
|
||||
#define TOYOTA_COMMON_RX_CHECKS(lta) \
|
||||
|
@ -68,21 +67,11 @@ RxCheck toyota_lka_rx_checks[] = {
|
|||
TOYOTA_COMMON_RX_CHECKS(false)
|
||||
};
|
||||
|
||||
RxCheck toyota_lka_interceptor_rx_checks[] = {
|
||||
TOYOTA_COMMON_RX_CHECKS(false)
|
||||
{.msg = {{0x201, 0, 6, .check_checksum = false, .max_counter = 15U, .frequency = 50U}, { 0 }, { 0 }}},
|
||||
};
|
||||
|
||||
// Check the quality flag for angle measurement when using LTA, since it's not set on TSS-P cars
|
||||
RxCheck toyota_lta_rx_checks[] = {
|
||||
TOYOTA_COMMON_RX_CHECKS(true)
|
||||
};
|
||||
|
||||
RxCheck toyota_lta_interceptor_rx_checks[] = {
|
||||
TOYOTA_COMMON_RX_CHECKS(true)
|
||||
{.msg = {{0x201, 0, 6, .check_checksum = false, .max_counter = 15U, .frequency = 50U}, { 0 }, { 0 }}},
|
||||
};
|
||||
|
||||
// safety param flags
|
||||
// first byte is for EPS factor, second is for flags
|
||||
const uint32_t TOYOTA_PARAM_OFFSET = 8U;
|
||||
|
@ -90,7 +79,6 @@ const uint32_t TOYOTA_EPS_FACTOR = (1UL << TOYOTA_PARAM_OFFSET) - 1U;
|
|||
const uint32_t TOYOTA_PARAM_ALT_BRAKE = 1UL << TOYOTA_PARAM_OFFSET;
|
||||
const uint32_t TOYOTA_PARAM_STOCK_LONGITUDINAL = 2UL << TOYOTA_PARAM_OFFSET;
|
||||
const uint32_t TOYOTA_PARAM_LTA = 4UL << TOYOTA_PARAM_OFFSET;
|
||||
const uint32_t TOYOTA_PARAM_GAS_INTERCEPTOR = 8UL << TOYOTA_PARAM_OFFSET;
|
||||
|
||||
bool toyota_alt_brake = false;
|
||||
bool toyota_stock_longitudinal = false;
|
||||
|
@ -112,23 +100,12 @@ static uint32_t toyota_get_checksum(const CANPacket_t *to_push) {
|
|||
return (uint8_t)(GET_BYTE(to_push, checksum_byte));
|
||||
}
|
||||
|
||||
static uint8_t toyota_get_counter(const CANPacket_t *to_push) {
|
||||
int addr = GET_ADDR(to_push);
|
||||
|
||||
uint8_t cnt = 0U;
|
||||
if (addr == 0x201) {
|
||||
// Signal: COUNTER_PEDAL
|
||||
cnt = GET_BYTE(to_push, 4) & 0x0FU;
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
static bool toyota_get_quality_flag_valid(const CANPacket_t *to_push) {
|
||||
int addr = GET_ADDR(to_push);
|
||||
|
||||
bool valid = false;
|
||||
if (addr == 0x260) {
|
||||
valid = GET_BIT(to_push, 3U) == 0U; // STEER_ANGLE_INITIALIZING
|
||||
valid = !GET_BIT(to_push, 3U); // STEER_ANGLE_INITIALIZING
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
@ -159,7 +136,7 @@ static void toyota_rx_hook(const CANPacket_t *to_push) {
|
|||
|
||||
// LTA request angle should match current angle while inactive, clipped to max accepted angle.
|
||||
// note that angle can be relative to init angle on some TSS2 platforms, LTA has the same offset
|
||||
bool steer_angle_initializing = GET_BIT(to_push, 3U) != 0U;
|
||||
bool steer_angle_initializing = GET_BIT(to_push, 3U);
|
||||
if (!steer_angle_initializing) {
|
||||
int angle_meas_new = (GET_BYTE(to_push, 3) << 8U) | GET_BYTE(to_push, 4);
|
||||
angle_meas_new = CLAMP(to_signed(angle_meas_new, 16), -TOYOTA_LTA_MAX_ANGLE, TOYOTA_LTA_MAX_ANGLE);
|
||||
|
@ -171,13 +148,11 @@ static void toyota_rx_hook(const CANPacket_t *to_push) {
|
|||
// exit controls on rising edge of gas press
|
||||
if (addr == 0x1D2) {
|
||||
// 5th bit is CRUISE_ACTIVE
|
||||
bool cruise_engaged = GET_BIT(to_push, 5U) != 0U;
|
||||
bool cruise_engaged = GET_BIT(to_push, 5U);
|
||||
pcm_cruise_check(cruise_engaged);
|
||||
|
||||
// sample gas pedal
|
||||
if (!enable_gas_interceptor) {
|
||||
gas_pressed = GET_BIT(to_push, 4U) == 0U;
|
||||
}
|
||||
gas_pressed = !GET_BIT(to_push, 4U);
|
||||
}
|
||||
|
||||
// sample speed
|
||||
|
@ -197,19 +172,14 @@ static void toyota_rx_hook(const CANPacket_t *to_push) {
|
|||
// most cars have brake_pressed on 0x226, corolla and rav4 on 0x224
|
||||
if (((addr == 0x224) && toyota_alt_brake) || ((addr == 0x226) && !toyota_alt_brake)) {
|
||||
uint8_t bit = (addr == 0x224) ? 5U : 37U;
|
||||
brake_pressed = GET_BIT(to_push, bit) != 0U;
|
||||
brake_pressed = GET_BIT(to_push, bit);
|
||||
}
|
||||
|
||||
// sample gas interceptor
|
||||
if ((addr == 0x201) && enable_gas_interceptor) {
|
||||
int gas_interceptor = TOYOTA_GET_INTERCEPTOR(to_push);
|
||||
gas_pressed = gas_interceptor > TOYOTA_GAS_INTERCEPTOR_THRSLD;
|
||||
|
||||
// TODO: remove this, only left in for gas_interceptor_prev test
|
||||
gas_interceptor_prev = gas_interceptor;
|
||||
bool stock_ecu_detected = addr == 0x2E4; // STEERING_LKA
|
||||
if (!toyota_stock_longitudinal && (addr == 0x343)) {
|
||||
stock_ecu_detected = true; // ACC_CONTROL
|
||||
}
|
||||
|
||||
generic_rx_checks((addr == 0x2E4));
|
||||
generic_rx_checks(stock_ecu_detected);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -220,14 +190,6 @@ static bool toyota_tx_hook(const CANPacket_t *to_send) {
|
|||
|
||||
// Check if msg is sent on BUS 0
|
||||
if (bus == 0) {
|
||||
|
||||
// GAS PEDAL: safety check
|
||||
if (addr == 0x200) {
|
||||
if (longitudinal_interceptor_checks(to_send)) {
|
||||
tx = false;
|
||||
}
|
||||
}
|
||||
|
||||
// ACCEL: safety check on byte 1-2
|
||||
if (addr == 0x343) {
|
||||
int desired_accel = (GET_BYTE(to_send, 0) << 8) | GET_BYTE(to_send, 1);
|
||||
|
@ -238,7 +200,7 @@ static bool toyota_tx_hook(const CANPacket_t *to_send) {
|
|||
|
||||
// only ACC messages that cancel are allowed when openpilot is not controlling longitudinal
|
||||
if (toyota_stock_longitudinal) {
|
||||
bool cancel_req = GET_BIT(to_send, 24U) != 0U;
|
||||
bool cancel_req = GET_BIT(to_send, 24U);
|
||||
if (!cancel_req) {
|
||||
violation = true;
|
||||
}
|
||||
|
@ -264,8 +226,8 @@ static bool toyota_tx_hook(const CANPacket_t *to_send) {
|
|||
// LTA angle steering check
|
||||
if (addr == 0x191) {
|
||||
// check the STEER_REQUEST, STEER_REQUEST_2, TORQUE_WIND_DOWN, STEER_ANGLE_CMD signals
|
||||
bool lta_request = GET_BIT(to_send, 0U) != 0U;
|
||||
bool lta_request2 = GET_BIT(to_send, 25U) != 0U;
|
||||
bool lta_request = GET_BIT(to_send, 0U);
|
||||
bool lta_request2 = GET_BIT(to_send, 25U);
|
||||
int torque_wind_down = GET_BYTE(to_send, 5);
|
||||
int lta_angle = (GET_BYTE(to_send, 1) << 8) | GET_BYTE(to_send, 2);
|
||||
lta_angle = to_signed(lta_angle, 16);
|
||||
|
@ -313,7 +275,7 @@ static bool toyota_tx_hook(const CANPacket_t *to_send) {
|
|||
if (addr == 0x2E4) {
|
||||
int desired_torque = (GET_BYTE(to_send, 1) << 8) | GET_BYTE(to_send, 2);
|
||||
desired_torque = to_signed(desired_torque, 16);
|
||||
bool steer_req = GET_BIT(to_send, 0U) != 0U;
|
||||
bool steer_req = GET_BIT(to_send, 0U);
|
||||
// When using LTA (angle control), assert no actuation on LKA message
|
||||
if (!toyota_lta) {
|
||||
if (steer_torque_cmd_checks(desired_torque, steer_req, TOYOTA_STEERING_LIMITS)) {
|
||||
|
@ -327,6 +289,15 @@ static bool toyota_tx_hook(const CANPacket_t *to_send) {
|
|||
}
|
||||
}
|
||||
|
||||
// UDS: Only tester present ("\x0F\x02\x3E\x00\x00\x00\x00\x00") allowed on diagnostics address
|
||||
if (addr == 0x750) {
|
||||
// this address is sub-addressed. only allow tester present to radar (0xF)
|
||||
bool invalid_uds_msg = (GET_BYTES(to_send, 0, 4) != 0x003E020FU) || (GET_BYTES(to_send, 4, 4) != 0x0U);
|
||||
if (invalid_uds_msg) {
|
||||
tx = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return tx;
|
||||
}
|
||||
|
||||
|
@ -334,22 +305,17 @@ static safety_config toyota_init(uint16_t param) {
|
|||
toyota_alt_brake = GET_FLAG(param, TOYOTA_PARAM_ALT_BRAKE);
|
||||
toyota_stock_longitudinal = GET_FLAG(param, TOYOTA_PARAM_STOCK_LONGITUDINAL);
|
||||
toyota_lta = GET_FLAG(param, TOYOTA_PARAM_LTA);
|
||||
enable_gas_interceptor = GET_FLAG(param, TOYOTA_PARAM_GAS_INTERCEPTOR);
|
||||
toyota_dbc_eps_torque_factor = param & TOYOTA_EPS_FACTOR;
|
||||
|
||||
// Gas interceptor should not be used if openpilot is not controlling longitudinal
|
||||
safety_config ret;
|
||||
if (toyota_stock_longitudinal) {
|
||||
enable_gas_interceptor = false;
|
||||
SET_TX_MSGS(TOYOTA_TX_MSGS, ret);
|
||||
} else {
|
||||
SET_TX_MSGS(TOYOTA_LONG_TX_MSGS, ret);
|
||||
}
|
||||
|
||||
safety_config ret;
|
||||
if (toyota_lta) {
|
||||
ret = enable_gas_interceptor ? BUILD_SAFETY_CFG(toyota_lta_interceptor_rx_checks, TOYOTA_INTERCEPTOR_TX_MSGS) : \
|
||||
BUILD_SAFETY_CFG(toyota_lta_rx_checks, TOYOTA_TX_MSGS);
|
||||
} else {
|
||||
ret = enable_gas_interceptor ? BUILD_SAFETY_CFG(toyota_lka_interceptor_rx_checks, TOYOTA_INTERCEPTOR_TX_MSGS) : \
|
||||
BUILD_SAFETY_CFG(toyota_lka_rx_checks, TOYOTA_TX_MSGS);
|
||||
}
|
||||
toyota_lta ? SET_RX_CHECKS(toyota_lta_rx_checks, ret) : \
|
||||
SET_RX_CHECKS(toyota_lka_rx_checks, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -364,10 +330,10 @@ static int toyota_fwd_hook(int bus_num, int addr) {
|
|||
if (bus_num == 2) {
|
||||
// block stock lkas messages and stock acc messages (if OP is doing ACC)
|
||||
// in TSS2, 0x191 is LTA which we need to block to avoid controls collision
|
||||
int is_lkas_msg = ((addr == 0x2E4) || (addr == 0x412) || (addr == 0x191));
|
||||
bool is_lkas_msg = ((addr == 0x2E4) || (addr == 0x412) || (addr == 0x191));
|
||||
// in TSS2 the camera does ACC as well, so filter 0x343
|
||||
int is_acc_msg = (addr == 0x343);
|
||||
int block_msg = is_lkas_msg || (is_acc_msg && !toyota_stock_longitudinal);
|
||||
bool is_acc_msg = (addr == 0x343);
|
||||
bool block_msg = is_lkas_msg || (is_acc_msg && !toyota_stock_longitudinal);
|
||||
if (!block_msg) {
|
||||
bus_fwd = 0;
|
||||
}
|
||||
|
@ -383,6 +349,5 @@ const safety_hooks toyota_hooks = {
|
|||
.fwd = toyota_fwd_hook,
|
||||
.get_checksum = toyota_get_checksum,
|
||||
.compute_checksum = toyota_compute_checksum,
|
||||
.get_counter = toyota_get_counter,
|
||||
.get_quality_flag_valid = toyota_get_quality_flag_valid,
|
||||
};
|
||||
|
|
|
@ -46,6 +46,7 @@ RxCheck volkswagen_mqb_rx_checks[] = {
|
|||
{.msg = {{MSG_TSK_06, 0, 8, .check_checksum = true, .max_counter = 15U, .frequency = 50U}, { 0 }, { 0 }}},
|
||||
{.msg = {{MSG_MOTOR_20, 0, 8, .check_checksum = true, .max_counter = 15U, .frequency = 50U}, { 0 }, { 0 }}},
|
||||
{.msg = {{MSG_MOTOR_14, 0, 8, .check_checksum = false, .max_counter = 0U, .frequency = 10U}, { 0 }, { 0 }}},
|
||||
{.msg = {{MSG_GRA_ACC_01, 0, 8, .check_checksum = true, .max_counter = 15U, .frequency = 33U}, { 0 }, { 0 }}},
|
||||
};
|
||||
|
||||
uint8_t volkswagen_crc8_lut_8h2f[256]; // Static lookup table for CRC8 poly 0x2F, aka 8H2F/AUTOSAR
|
||||
|
@ -83,6 +84,8 @@ static uint32_t volkswagen_mqb_compute_crc(const CANPacket_t *to_push) {
|
|||
crc ^= (uint8_t[]){0xC4,0xE2,0x4F,0xE4,0xF8,0x2F,0x56,0x81,0x9F,0xE5,0x83,0x44,0x05,0x3F,0x97,0xDF}[counter];
|
||||
} else if (addr == MSG_MOTOR_20) {
|
||||
crc ^= (uint8_t[]){0xE9,0x65,0xAE,0x6B,0x7B,0x35,0xE5,0x5F,0x4E,0xC7,0x86,0xA2,0xBB,0xDD,0xEB,0xB4}[counter];
|
||||
} else if (addr == MSG_GRA_ACC_01) {
|
||||
crc ^= (uint8_t[]){0x6A,0x38,0xB4,0x27,0x22,0xEF,0xE1,0xBB,0xF8,0x80,0x84,0x49,0xC7,0x9E,0x1E,0x2B}[counter];
|
||||
} else {
|
||||
// Undefined CAN message, CRC check expected to fail
|
||||
}
|
||||
|
@ -167,7 +170,7 @@ static void volkswagen_mqb_rx_hook(const CANPacket_t *to_push) {
|
|||
}
|
||||
// Always exit controls on rising edge of Cancel
|
||||
// Signal: GRA_ACC_01.GRA_Abbrechen
|
||||
if (GET_BIT(to_push, 13U) == 1U) {
|
||||
if (GET_BIT(to_push, 13U)) {
|
||||
controls_allowed = false;
|
||||
}
|
||||
}
|
||||
|
@ -207,7 +210,7 @@ static bool volkswagen_mqb_tx_hook(const CANPacket_t *to_send) {
|
|||
desired_torque *= -1;
|
||||
}
|
||||
|
||||
bool steer_req = GET_BIT(to_send, 30U) != 0U;
|
||||
bool steer_req = GET_BIT(to_send, 30U);
|
||||
|
||||
if (steer_torque_cmd_checks(desired_torque, steer_req, VOLKSWAGEN_MQB_STEERING_LIMITS)) {
|
||||
tx = false;
|
||||
|
|
|
@ -141,7 +141,7 @@ static void volkswagen_pq_rx_hook(const CANPacket_t *to_push) {
|
|||
volkswagen_resume_button_prev = resume_button;
|
||||
// Exit controls on rising edge of Cancel, override Set/Resume if present simultaneously
|
||||
// Signal: GRA_ACC_01.GRA_Abbrechen
|
||||
if (GET_BIT(to_push, 9U) == 1U) {
|
||||
if (GET_BIT(to_push, 9U)) {
|
||||
controls_allowed = false;
|
||||
}
|
||||
}
|
||||
|
@ -185,7 +185,7 @@ static bool volkswagen_pq_tx_hook(const CANPacket_t *to_send) {
|
|||
}
|
||||
|
||||
uint32_t hca_status = ((GET_BYTE(to_send, 1) >> 4) & 0xFU);
|
||||
bool steer_req = (hca_status == 5U);
|
||||
bool steer_req = ((hca_status == 5U) || (hca_status == 7U));
|
||||
|
||||
if (steer_torque_cmd_checks(desired_torque, steer_req, VOLKSWAGEN_PQ_STEERING_LIMITS)) {
|
||||
tx = false;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#define GET_BIT(msg, b) (((msg)->data[((b) / 8U)] >> ((b) % 8U)) & 0x1U)
|
||||
#define GET_BIT(msg, b) ((bool)!!(((msg)->data[((b) / 8U)] >> ((b) % 8U)) & 0x1U))
|
||||
#define GET_BYTE(msg, b) ((msg)->data[(b)])
|
||||
#define GET_FLAG(value, mask) (((__typeof__(mask))(value) & (mask)) == (mask))
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
|||
uint32_t GET_BYTES(const CANPacket_t *msg, int start, int len) {
|
||||
uint32_t ret = 0U;
|
||||
for (int i = 0; i < len; i++) {
|
||||
const uint8_t shift = i * 8;
|
||||
const uint32_t shift = i * 8;
|
||||
ret |= (((uint32_t)msg->data[start + i]) << shift);
|
||||
}
|
||||
return ret;
|
||||
|
@ -203,7 +203,6 @@ bool longitudinal_speed_checks(int desired_speed, const LongitudinalLimits limit
|
|||
bool longitudinal_gas_checks(int desired_gas, const LongitudinalLimits limits);
|
||||
bool longitudinal_transmission_rpm_checks(int desired_transmission_rpm, const LongitudinalLimits limits);
|
||||
bool longitudinal_brake_checks(int desired_brake, const LongitudinalLimits limits);
|
||||
bool longitudinal_interceptor_checks(const CANPacket_t *to_send);
|
||||
void pcm_cruise_check(bool cruise_engaged);
|
||||
|
||||
void safety_tick(const safety_config *safety_config);
|
||||
|
@ -211,8 +210,6 @@ void safety_tick(const safety_config *safety_config);
|
|||
// This can be set by the safety hooks
|
||||
bool controls_allowed = false;
|
||||
bool relay_malfunction = false;
|
||||
bool enable_gas_interceptor = false;
|
||||
int gas_interceptor_prev = 0;
|
||||
bool gas_pressed = false;
|
||||
bool gas_pressed_prev = false;
|
||||
bool brake_pressed = false;
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
// ///////////////////////////////////////////////////////////// //
|
||||
// Hardware abstraction layer for all different supported boards //
|
||||
// ///////////////////////////////////////////////////////////// //
|
||||
#include "boards/board_declarations.h"
|
||||
#include "boards/unused_funcs.h"
|
||||
|
||||
// ///// Board definition and detection ///// //
|
||||
#include "stm32f4/lladc.h"
|
||||
#include "drivers/harness.h"
|
||||
#include "drivers/fan.h"
|
||||
#include "stm32f4/llfan.h"
|
||||
#include "drivers/clock_source.h"
|
||||
#include "boards/white.h"
|
||||
#include "boards/grey.h"
|
||||
#include "boards/black.h"
|
||||
#include "boards/uno.h"
|
||||
#include "boards/dos.h"
|
||||
|
||||
void detect_board_type(void) {
|
||||
// SPI lines floating: white (TODO: is this reliable? Not really, we have to enable ESP/GPS to be able to detect this on the UART)
|
||||
set_gpio_output(GPIOC, 14, 1);
|
||||
set_gpio_output(GPIOC, 5, 1);
|
||||
if(!detect_with_pull(GPIOB, 1, PULL_UP) && !detect_with_pull(GPIOB, 7, PULL_UP)){
|
||||
hw_type = HW_TYPE_DOS;
|
||||
current_board = &board_dos;
|
||||
} else if((detect_with_pull(GPIOA, 4, PULL_DOWN)) || (detect_with_pull(GPIOA, 5, PULL_DOWN)) || (detect_with_pull(GPIOA, 6, PULL_DOWN)) || (detect_with_pull(GPIOA, 7, PULL_DOWN))){
|
||||
hw_type = HW_TYPE_WHITE_PANDA;
|
||||
current_board = &board_white;
|
||||
} else if(detect_with_pull(GPIOA, 13, PULL_DOWN)) { // Rev AB deprecated, so no pullup means black. In REV C, A13 is pulled up to 5V with a 10K
|
||||
hw_type = HW_TYPE_GREY_PANDA;
|
||||
current_board = &board_grey;
|
||||
} else if(!detect_with_pull(GPIOB, 15, PULL_UP)) {
|
||||
hw_type = HW_TYPE_UNO;
|
||||
current_board = &board_uno;
|
||||
} else {
|
||||
hw_type = HW_TYPE_BLACK_PANDA;
|
||||
current_board = &board_black;
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
void clock_init(void) {
|
||||
// enable external oscillator
|
||||
register_set_bits(&(RCC->CR), RCC_CR_HSEON);
|
||||
while ((RCC->CR & RCC_CR_HSERDY) == 0);
|
||||
while ((RCC->CR & RCC_CR_HSERDY) == 0U);
|
||||
|
||||
// divide things
|
||||
// AHB = 96MHz
|
||||
|
@ -20,7 +20,7 @@ void clock_init(void) {
|
|||
|
||||
// start PLL
|
||||
register_set_bits(&(RCC->CR), RCC_CR_PLLON);
|
||||
while ((RCC->CR & RCC_CR_PLLRDY) == 0);
|
||||
while ((RCC->CR & RCC_CR_PLLRDY) == 0U);
|
||||
|
||||
// Configure Flash prefetch, Instruction cache, Data cache and wait state
|
||||
// *** without this, it breaks ***
|
|
@ -1,5 +1,5 @@
|
|||
// ********************* Bare interrupt handlers *********************
|
||||
// Only implemented the STM32F413 interrupts for now, the STM32F203 specific ones do not fall into the scope of SIL2
|
||||
// Only implemented the STM32F413 interrupts for now
|
||||
|
||||
void WWDG_IRQHandler(void) {handle_interrupt(WWDG_IRQn);}
|
||||
void PVD_IRQHandler(void) {handle_interrupt(PVD_IRQn);}
|
||||
|
@ -73,28 +73,26 @@ void DMA2_Stream7_IRQHandler(void) {handle_interrupt(DMA2_Stream7_IRQn);}
|
|||
void USART6_IRQHandler(void) {handle_interrupt(USART6_IRQn);}
|
||||
void I2C3_EV_IRQHandler(void) {handle_interrupt(I2C3_EV_IRQn);}
|
||||
void I2C3_ER_IRQHandler(void) {handle_interrupt(I2C3_ER_IRQn);}
|
||||
#ifdef STM32F4
|
||||
void DFSDM1_FLT0_IRQHandler(void) {handle_interrupt(DFSDM1_FLT0_IRQn);}
|
||||
void DFSDM1_FLT1_IRQHandler(void) {handle_interrupt(DFSDM1_FLT1_IRQn);}
|
||||
void CAN3_TX_IRQHandler(void) {handle_interrupt(CAN3_TX_IRQn);}
|
||||
void CAN3_RX0_IRQHandler(void) {handle_interrupt(CAN3_RX0_IRQn);}
|
||||
void CAN3_RX1_IRQHandler(void) {handle_interrupt(CAN3_RX1_IRQn);}
|
||||
void CAN3_SCE_IRQHandler(void) {handle_interrupt(CAN3_SCE_IRQn);}
|
||||
void RNG_IRQHandler(void) {handle_interrupt(RNG_IRQn);}
|
||||
void FPU_IRQHandler(void) {handle_interrupt(FPU_IRQn);}
|
||||
void UART7_IRQHandler(void) {handle_interrupt(UART7_IRQn);}
|
||||
void UART8_IRQHandler(void) {handle_interrupt(UART8_IRQn);}
|
||||
void SPI4_IRQHandler(void) {handle_interrupt(SPI4_IRQn);}
|
||||
void SPI5_IRQHandler(void) {handle_interrupt(SPI5_IRQn);}
|
||||
void SAI1_IRQHandler(void) {handle_interrupt(SAI1_IRQn);}
|
||||
void UART9_IRQHandler(void) {handle_interrupt(UART9_IRQn);}
|
||||
void UART10_IRQHandler(void) {handle_interrupt(UART10_IRQn);}
|
||||
void QUADSPI_IRQHandler(void) {handle_interrupt(QUADSPI_IRQn);}
|
||||
void FMPI2C1_EV_IRQHandler(void) {handle_interrupt(FMPI2C1_EV_IRQn);}
|
||||
void FMPI2C1_ER_IRQHandler(void) {handle_interrupt(FMPI2C1_ER_IRQn);}
|
||||
void LPTIM1_IRQHandler(void) {handle_interrupt(LPTIM1_IRQn);}
|
||||
void DFSDM2_FLT0_IRQHandler(void) {handle_interrupt(DFSDM2_FLT0_IRQn);}
|
||||
void DFSDM2_FLT1_IRQHandler(void) {handle_interrupt(DFSDM2_FLT1_IRQn);}
|
||||
void DFSDM2_FLT2_IRQHandler(void) {handle_interrupt(DFSDM2_FLT2_IRQn);}
|
||||
void DFSDM2_FLT3_IRQHandler(void) {handle_interrupt(DFSDM2_FLT3_IRQn);}
|
||||
#endif
|
||||
void DFSDM1_FLT0_IRQHandler(void) {handle_interrupt(DFSDM1_FLT0_IRQn);}
|
||||
void DFSDM1_FLT1_IRQHandler(void) {handle_interrupt(DFSDM1_FLT1_IRQn);}
|
||||
void CAN3_TX_IRQHandler(void) {handle_interrupt(CAN3_TX_IRQn);}
|
||||
void CAN3_RX0_IRQHandler(void) {handle_interrupt(CAN3_RX0_IRQn);}
|
||||
void CAN3_RX1_IRQHandler(void) {handle_interrupt(CAN3_RX1_IRQn);}
|
||||
void CAN3_SCE_IRQHandler(void) {handle_interrupt(CAN3_SCE_IRQn);}
|
||||
void RNG_IRQHandler(void) {handle_interrupt(RNG_IRQn);}
|
||||
void FPU_IRQHandler(void) {handle_interrupt(FPU_IRQn);}
|
||||
void UART7_IRQHandler(void) {handle_interrupt(UART7_IRQn);}
|
||||
void UART8_IRQHandler(void) {handle_interrupt(UART8_IRQn);}
|
||||
void SPI4_IRQHandler(void) {handle_interrupt(SPI4_IRQn);}
|
||||
void SPI5_IRQHandler(void) {handle_interrupt(SPI5_IRQn);}
|
||||
void SAI1_IRQHandler(void) {handle_interrupt(SAI1_IRQn);}
|
||||
void UART9_IRQHandler(void) {handle_interrupt(UART9_IRQn);}
|
||||
void UART10_IRQHandler(void) {handle_interrupt(UART10_IRQn);}
|
||||
void QUADSPI_IRQHandler(void) {handle_interrupt(QUADSPI_IRQn);}
|
||||
void FMPI2C1_EV_IRQHandler(void) {handle_interrupt(FMPI2C1_EV_IRQn);}
|
||||
void FMPI2C1_ER_IRQHandler(void) {handle_interrupt(FMPI2C1_ER_IRQn);}
|
||||
void LPTIM1_IRQHandler(void) {handle_interrupt(LPTIM1_IRQn);}
|
||||
void DFSDM2_FLT0_IRQHandler(void) {handle_interrupt(DFSDM2_FLT0_IRQn);}
|
||||
void DFSDM2_FLT1_IRQHandler(void) {handle_interrupt(DFSDM2_FLT1_IRQn);}
|
||||
void DFSDM2_FLT2_IRQHandler(void) {handle_interrupt(DFSDM2_FLT2_IRQn);}
|
||||
void DFSDM2_FLT3_IRQHandler(void) {handle_interrupt(DFSDM2_FLT3_IRQn);}
|
|
@ -1,12 +1,3 @@
|
|||
// ACCEL1 = ADC10
|
||||
// ACCEL2 = ADC11
|
||||
// VOLT_S = ADC12
|
||||
// CURR_S = ADC13
|
||||
|
||||
#define ADCCHAN_ACCEL0 10
|
||||
#define ADCCHAN_ACCEL1 11
|
||||
#define ADCCHAN_VIN 12
|
||||
#define ADCCHAN_CURRENT 13
|
||||
|
||||
void register_set(volatile uint32_t *addr, uint32_t val, uint32_t mask);
|
||||
|
|
@ -84,12 +84,10 @@ void llcan_irq_disable(const CAN_TypeDef *CANx) {
|
|||
NVIC_DisableIRQ(CAN2_TX_IRQn);
|
||||
NVIC_DisableIRQ(CAN2_RX0_IRQn);
|
||||
NVIC_DisableIRQ(CAN2_SCE_IRQn);
|
||||
#ifdef CAN3
|
||||
} else if (CANx == CAN3) {
|
||||
NVIC_DisableIRQ(CAN3_TX_IRQn);
|
||||
NVIC_DisableIRQ(CAN3_RX0_IRQn);
|
||||
NVIC_DisableIRQ(CAN3_SCE_IRQn);
|
||||
#endif
|
||||
} else if (CANx == CAN3) {
|
||||
NVIC_DisableIRQ(CAN3_TX_IRQn);
|
||||
NVIC_DisableIRQ(CAN3_RX0_IRQn);
|
||||
NVIC_DisableIRQ(CAN3_SCE_IRQn);
|
||||
} else {
|
||||
}
|
||||
}
|
||||
|
@ -103,12 +101,10 @@ void llcan_irq_enable(const CAN_TypeDef *CANx) {
|
|||
NVIC_EnableIRQ(CAN2_TX_IRQn);
|
||||
NVIC_EnableIRQ(CAN2_RX0_IRQn);
|
||||
NVIC_EnableIRQ(CAN2_SCE_IRQn);
|
||||
#ifdef CAN3
|
||||
} else if (CANx == CAN3) {
|
||||
NVIC_EnableIRQ(CAN3_TX_IRQn);
|
||||
NVIC_EnableIRQ(CAN3_RX0_IRQn);
|
||||
NVIC_EnableIRQ(CAN3_SCE_IRQn);
|
||||
#endif
|
||||
} else if (CANx == CAN3) {
|
||||
NVIC_EnableIRQ(CAN3_TX_IRQn);
|
||||
NVIC_EnableIRQ(CAN3_RX0_IRQn);
|
||||
NVIC_EnableIRQ(CAN3_SCE_IRQn);
|
||||
} else {
|
||||
}
|
||||
}
|
|
@ -5,7 +5,7 @@ void uart_tx_ring(uart_ring *q){
|
|||
// Send out next byte of TX buffer
|
||||
if (q->w_ptr_tx != q->r_ptr_tx) {
|
||||
// Only send if transmit register is empty (aka last byte has been sent)
|
||||
if ((q->uart->SR & USART_SR_TXE) != 0) {
|
||||
if ((q->uart->SR & USART_SR_TXE) != 0U) {
|
||||
q->uart->DR = q->elems_tx[q->r_ptr_tx]; // This clears TXE
|
||||
q->r_ptr_tx = (q->r_ptr_tx + 1U) % q->tx_fifo_size;
|
||||
}
|
||||
|
@ -46,7 +46,7 @@ void uart_rx_ring(uart_ring *q){
|
|||
}
|
||||
|
||||
void uart_send_break(uart_ring *u) {
|
||||
while ((u->uart->CR1 & USART_CR1_SBK) != 0);
|
||||
while ((u->uart->CR1 & USART_CR1_SBK) != 0U);
|
||||
u->uart->CR1 |= USART_CR1_SBK;
|
||||
}
|
||||
|
||||
|
@ -90,32 +90,3 @@ void USART2_IRQ_Handler(void) { uart_interrupt_handler(&uart_ring_debug); }
|
|||
void uart_set_baud(USART_TypeDef *u, unsigned int baud) {
|
||||
u->BRR = USART_BRR_(APB1_FREQ*1000000U, baud);
|
||||
}
|
||||
|
||||
void uart_init(uart_ring *q, int baud) {
|
||||
if(q->uart != NULL){
|
||||
// Register interrupts (max data rate: 115200 baud)
|
||||
if (q->uart == USART2){
|
||||
REGISTER_INTERRUPT(USART2_IRQn, USART2_IRQ_Handler, 150000U, FAULT_INTERRUPT_RATE_UART_2)
|
||||
} else {
|
||||
// UART not used. Skip registering interrupts
|
||||
}
|
||||
|
||||
// Set baud and enable peripheral with TX and RX mode
|
||||
uart_set_baud(q->uart, baud);
|
||||
q->uart->CR1 = USART_CR1_UE | USART_CR1_TE | USART_CR1_RE;
|
||||
if ((q->uart == USART2) || (q->uart == USART3) || (q->uart == UART5)) {
|
||||
q->uart->CR1 |= USART_CR1_RXNEIE;
|
||||
}
|
||||
|
||||
// Enable UART interrupts
|
||||
if (q->uart == USART2){
|
||||
NVIC_EnableIRQ(USART2_IRQn);
|
||||
} else if (q->uart == USART3){
|
||||
NVIC_EnableIRQ(USART3_IRQn);
|
||||
} else if (q->uart == UART5){
|
||||
NVIC_EnableIRQ(UART5_IRQn);
|
||||
} else {
|
||||
// UART not used. Skip enabling interrupts
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,7 +8,7 @@ USB_OTG_GlobalTypeDef *USBx = USB_OTG_FS;
|
|||
#define USBx_PCGCCTL *(__IO uint32_t *)((uint32_t)USBx + USB_OTG_PCGCCTL_BASE)
|
||||
|
||||
#define USBD_FS_TRDT_VALUE 5UL
|
||||
#define USB_OTG_SPEED_FULL 3
|
||||
#define USB_OTG_SPEED_FULL 3UL
|
||||
|
||||
|
||||
void usb_irqhandler(void);
|
||||
|
@ -27,7 +27,7 @@ void usb_init(void) {
|
|||
// full speed PHY, do reset and remove power down
|
||||
/*puth(USBx->GRSTCTL);
|
||||
print(" resetting PHY\n");*/
|
||||
while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_AHBIDL) == 0);
|
||||
while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_AHBIDL) == 0U);
|
||||
//print("AHB idle\n");
|
||||
|
||||
// reset PHY here
|
||||
|
@ -42,7 +42,6 @@ void usb_init(void) {
|
|||
USBx->GUSBCFG |= ((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;
|
||||
|
@ -50,9 +49,6 @@ void usb_init(void) {
|
|||
/* 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;
|
|
@ -36,14 +36,9 @@ void common_init_gpio(void) {
|
|||
|
||||
gpio_usb_init();
|
||||
|
||||
// B8,B9: CAN 1
|
||||
#ifdef STM32F4
|
||||
set_gpio_alternate(GPIOB, 8, GPIO_AF8_CAN1);
|
||||
set_gpio_alternate(GPIOB, 9, GPIO_AF8_CAN1);
|
||||
#else
|
||||
set_gpio_alternate(GPIOB, 8, GPIO_AF9_CAN1);
|
||||
set_gpio_alternate(GPIOB, 9, GPIO_AF9_CAN1);
|
||||
#endif
|
||||
// B8,B9: CAN 1
|
||||
set_gpio_alternate(GPIOB, 8, GPIO_AF8_CAN1);
|
||||
set_gpio_alternate(GPIOB, 9, GPIO_AF8_CAN1);
|
||||
}
|
||||
|
||||
void flasher_peripherals_init(void) {
|
||||
|
@ -71,14 +66,10 @@ void peripherals_init(void) {
|
|||
RCC->AHB2ENR |= RCC_AHB2ENR_OTGFSEN;
|
||||
RCC->APB1ENR |= RCC_APB1ENR_USART2EN;
|
||||
RCC->APB1ENR |= RCC_APB1ENR_USART3EN;
|
||||
#ifndef PEDAL
|
||||
RCC->APB1ENR |= RCC_APB1ENR_UART5EN;
|
||||
#endif
|
||||
RCC->APB1ENR |= RCC_APB1ENR_UART5EN;
|
||||
RCC->APB1ENR |= RCC_APB1ENR_CAN1EN;
|
||||
RCC->APB1ENR |= RCC_APB1ENR_CAN2EN;
|
||||
#ifdef CAN3
|
||||
RCC->APB1ENR |= RCC_APB1ENR_CAN3EN;
|
||||
#endif
|
||||
RCC->APB1ENR |= RCC_APB1ENR_CAN3EN;
|
||||
|
||||
// Analog
|
||||
RCC->APB2ENR |= RCC_APB2ENR_ADC1EN;
|
||||
|
@ -92,7 +83,6 @@ void peripherals_init(void) {
|
|||
RCC->APB1ENR |= RCC_APB1ENR_TIM5EN; // k-line init
|
||||
RCC->APB1ENR |= RCC_APB1ENR_TIM6EN; // interrupt timer
|
||||
RCC->APB2ENR |= RCC_APB2ENR_TIM9EN; // slow loop
|
||||
RCC->APB1ENR |= RCC_APB1ENR_TIM12EN; // gmlan_alt
|
||||
}
|
||||
|
||||
void enable_interrupt_timer(void) {
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue