diff --git a/Jenkinsfile b/Jenkinsfile index 2d4c615dfe..b3b2690861 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -73,56 +73,57 @@ pipeline { } stages { - stage('panda tests') { - parallel { - stage('test dos') { - agent { docker { image 'ghcr.io/commaai/alpine-ssh'; args '--user=root' } } + stage ('Acquire resource locks') { + options { + lock(resource: "pandas") + } + stages { + stage('Build Docker Image') { steps { - phone_steps("panda-dos", [ - ["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 -n0 --durations=0 [2-9]*.py -k 'not test_send_recv'"], - ]) + timeout(time: 20, unit: 'MINUTES') { + script { + sh 'git archive -v -o panda.tar.gz --format=tar.gz HEAD' + dockerImage = docker.build("${env.DOCKER_IMAGE_TAG}") + } + } } } - - stage('test tres') { - agent { docker { image 'ghcr.io/commaai/alpine-ssh'; args '--user=root' } } + stage('jungle tests') { steps { - phone_steps("panda-tres", [ - ["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 -n0 --durations=0 2*.py [5-9]*.py"], - ]) + script { + retry (3) { + docker_run("reset hardware", 3, "python ./tests/hitl/reset_jungles.py") + } + } } } - stage ('Acquire resource locks') { - options { - lock(resource: "pandas") - } - stages { - stage('Build Docker Image') { + stage('parallel tests') { + parallel { + stage('test tres') { + agent { docker { image 'ghcr.io/commaai/alpine-ssh'; args '--user=root' } } steps { - timeout(time: 20, unit: 'MINUTES') { - script { - sh 'git archive -v -o panda.tar.gz --format=tar.gz HEAD' - dockerImage = docker.build("${env.DOCKER_IMAGE_TAG}") - } - } + phone_steps("panda-tres", [ + ["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 -n0 --durations=0 2*.py [5-9]*.py"], + ]) } } - stage('jungle tests') { + + stage('test dos') { + agent { docker { image 'ghcr.io/commaai/alpine-ssh'; args '--user=root' } } steps { - script { - retry (3) { - docker_run("reset hardware", 3, "python ./tests/hitl/reset_jungles.py") - } - } + phone_steps("panda-dos", [ + ["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 -n0 --durations=0 [2-9]*.py -k 'not test_send_recv'"], + ]) } } + stage('bootkick tests') { steps { script { diff --git a/README.md b/README.md index b2830b21ef..b9853e5908 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ Safety modes optionally support `controls_allowed`, which allows or blocks a sub ## Code Rigor -The panda firmware is written for its use in conjuction with [openpilot](https://github.com/commaai/openpilot). The panda firmware, through its safety model, provides and enforces the +The panda firmware is written for its use in conjunction with [openpilot](https://github.com/commaai/openpilot). The panda firmware, through its safety model, provides and enforces the [openpilot safety](https://github.com/commaai/openpilot/blob/master/docs/SAFETY.md). Due to its critical function, it's important that the application code rigor within the `board` folder is held to high standards. These are the [CI regression tests](https://github.com/commaai/panda/actions) we have in place: diff --git a/board/SConscript b/board/SConscript index 93fd47b07e..3ff77648ba 100644 --- a/board/SConscript +++ b/board/SConscript @@ -15,7 +15,4 @@ for project_name, project in build_projects.items(): if ("ENABLE_SPI" in os.environ or "h7" in project_name): flags.append('-DENABLE_SPI') - if "H723" in os.environ: - flags.append('-DSTM32H723') - build_project(project_name, project, flags) diff --git a/board/jungle/main.c b/board/jungle/main.c index 40777d9965..329ee98a1f 100644 --- a/board/jungle/main.c +++ b/board/jungle/main.c @@ -156,10 +156,7 @@ int main(void) { print("\n\n\n************************ MAIN START ************************\n"); // check for non-supported board types - if (hw_type == HW_TYPE_UNKNOWN) { - print("Unsupported board type\n"); - while (1) { /* hang */ } - } + assert_fatal(hw_type != HW_TYPE_UNKNOWN, "Unsupported board type\n"); print("Config:\n"); print(" Board type: 0x"); puth(hw_type); print("\n"); diff --git a/board/libc.h b/board/libc.h index 7f669b95ab..c5f0219350 100644 --- a/board/libc.h +++ b/board/libc.h @@ -5,6 +5,16 @@ void delay(uint32_t a) { for (i = 0; i < a; i++); } +void assert_fatal(bool condition, const char *msg) { + if (!condition) { + print("ASSERT FAILED\n"); + print(msg); + while (1) { + // hang + } + } +} + // cppcheck-suppress misra-c2012-21.2 void *memset(void *str, int c, unsigned int n) { uint8_t *s = str; diff --git a/board/main.c b/board/main.c index b481c28b46..3db278eb50 100644 --- a/board/main.c +++ b/board/main.c @@ -67,12 +67,8 @@ void set_safety_mode(uint16_t mode, uint16_t param) { print("Error: safety set mode failed. Falling back to SILENT\n"); mode_copy = SAFETY_SILENT; err = set_safety_hooks(mode_copy, 0U); - if (err == -1) { - print("Error: Failed setting SILENT mode. Hanging\n"); - while (true) { - // TERMINAL ERROR: we can't continue if SILENT safety mode isn't succesfully set - } - } + // TERMINAL ERROR: we can't continue if SILENT safety mode isn't succesfully set + assert_fatal(err == 0, "Error: Failed setting SILENT mode. Hanging\n"); } safety_tx_blocked = 0; safety_rx_invalid = 0; @@ -314,10 +310,7 @@ int main(void) { print("\n\n\n************************ MAIN START ************************\n"); // check for non-supported board types - if(hw_type == HW_TYPE_UNKNOWN){ - print("Unsupported board type\n"); - while (1) { /* hang */ } - } + assert_fatal(hw_type != HW_TYPE_UNKNOWN, "Unsupported board type"); print("Config:\n"); print(" Board type: 0x"); puth(hw_type); print("\n"); diff --git a/board/stm32h7/board.h b/board/stm32h7/board.h index f5a8e55aa8..e8ea23b252 100644 --- a/board/stm32h7/board.h +++ b/board/stm32h7/board.h @@ -18,36 +18,33 @@ #include "boards/cuatro.h" -uint8_t get_board_id(void) { - return detect_with_pull(GPIOF, 7, PULL_UP) | - (detect_with_pull(GPIOF, 8, PULL_UP) << 1U) | - (detect_with_pull(GPIOF, 9, PULL_UP) << 2U) | - (detect_with_pull(GPIOF, 10, PULL_UP) << 3U); -} - void detect_board_type(void) { - const uint8_t board_id = get_board_id(); + // On STM32H7 pandas, we use two different sets of pins. + const uint8_t id1 = detect_with_pull(GPIOF, 7, PULL_UP) | + (detect_with_pull(GPIOF, 8, PULL_UP) << 1U) | + (detect_with_pull(GPIOF, 9, PULL_UP) << 2U) | + (detect_with_pull(GPIOF, 10, PULL_UP) << 3U); - if (board_id == 0U) { + const uint8_t id2 = detect_with_pull(GPIOD, 4, PULL_UP) | + (detect_with_pull(GPIOD, 5, PULL_UP) << 1U) | + (detect_with_pull(GPIOD, 6, PULL_UP) << 2U) | + (detect_with_pull(GPIOD, 7, PULL_UP) << 3U); + + if (id2 == 3U) { + hw_type = HW_TYPE_CUATRO; + current_board = &board_cuatro; + } else if (id1 == 0U) { hw_type = HW_TYPE_RED_PANDA; current_board = &board_red; - } else if (board_id == 1U) { + } else if (id1 == 1U) { // deprecated //hw_type = HW_TYPE_RED_PANDA_V2; - } else if (board_id == 2U) { + hw_type = HW_TYPE_UNKNOWN; + } else if (id1 == 2U) { hw_type = HW_TYPE_TRES; current_board = &board_tres; - } else if (board_id == 3U) { - hw_type = HW_TYPE_CUATRO; - current_board = &board_tres; } else { hw_type = HW_TYPE_UNKNOWN; print("Hardware type is UNKNOWN!\n"); } - - // TODO: detect this live -#ifdef STM32H723 - hw_type = HW_TYPE_CUATRO; - current_board = &board_cuatro; -#endif } diff --git a/board/stm32h7/clock.h b/board/stm32h7/clock.h index 2e3ab701d8..faf8ad5b1f 100644 --- a/board/stm32h7/clock.h +++ b/board/stm32h7/clock.h @@ -18,12 +18,16 @@ PCLK1: 60MHz (for USART2,3,4,5,7,8) */ void clock_init(void) { - // Set power mode to direct SMPS power supply(depends on the board layout) -#ifndef STM32H723 - register_set(&(PWR->CR3), PWR_CR3_SMPSEN, 0xFU); // powered only by SMPS + // Set power mode to direct SMPS power supply (depends on the board layout) +#ifndef PANDA_JUNGLE + if ((PWR->CR3 & PWR_CR3_SMPSEXTRDY) != 0U) { #else - register_set(&(PWR->CR3), PWR_CR3_LDOEN, 0xFU); + if (true) { #endif + register_set(&(PWR->CR3), PWR_CR3_SMPSEN, 0xFU); // powered only by SMPS + } else { + register_set(&(PWR->CR3), PWR_CR3_LDOEN, 0xFU); + } // Set VOS level (VOS3 to 170Mhz, VOS2 to 300Mhz, VOS1 to 400Mhz, VOS0 to 550Mhz) register_set(&(PWR->D3CR), PWR_D3CR_VOS_1 | PWR_D3CR_VOS_0, 0xC000U); //VOS1, needed for 80Mhz CAN FD while ((PWR->CSR1 & PWR_CSR1_ACTVOSRDY) == 0U);