├── .gitmodules ├── get-version.sh ├── src ├── autobaud.h ├── tusb_edpt_handler.h ├── cdc_uart.h ├── probe_config.c ├── get_serial.h ├── autobaud.pio ├── probe.h ├── get_serial.c ├── probe_config.h ├── tusb_config.h ├── probe_oen.pio ├── probe.pio ├── probe.c ├── FreeRTOSConfig.h ├── sw_dp_pio.c ├── main.c ├── usb_descriptors.c ├── tusb_edpt_handler.c └── cdc_uart.c ├── CMSIS_DAP └── CMSIS │ ├── DAP │ └── Firmware │ │ ├── Validation │ │ └── MDK5 │ │ │ ├── readme.txt │ │ │ ├── test.bat │ │ │ ├── RTE │ │ │ └── Device │ │ │ │ └── ARMCM3 │ │ │ │ ├── system_ARMCM3.c │ │ │ │ └── startup_ARMCM3.s │ │ │ ├── test.c │ │ │ ├── Validation.uvoptx │ │ │ └── test.ini │ │ ├── Template │ │ ├── CMSIS_DAP_v2.inf │ │ └── MDK5 │ │ │ ├── osObjects.h │ │ │ ├── main.c │ │ │ └── USBD_User_HID_0.c │ │ ├── Source │ │ └── DAP_vendor.c │ │ └── Include │ │ └── DAP.h │ └── Core │ └── Include │ ├── cmsis_version.h │ ├── tz_context.h │ ├── cmsis_compiler.h │ ├── mpu_armv7.h │ └── mpu_armv8.h ├── LICENSE ├── include ├── board_pico_config.h ├── board_debug_probe_config.h └── board_example_config.h ├── README.md ├── CMakeLists.txt ├── pico_sdk_import.cmake └── FreeRTOS_Kernel_import.cmake /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "freertos"] 2 | path = freertos 3 | url = https://github.com/FreeRTOS/FreeRTOS-Kernel 4 | -------------------------------------------------------------------------------- /get-version.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | if command -v git &>/dev/null 3 | then 4 | VERSION=$(git describe --exact-match --tags 2> /dev/null || git rev-parse --short HEAD) 5 | else 6 | VERSION="unknown" 7 | fi 8 | 9 | if [ ! -e generated/probe ] 10 | then 11 | mkdir -p generated/probe 12 | fi 13 | 14 | cat > generated/probe/version.h << EOF 15 | #ifndef _PROBE_VERSION_H 16 | #define _PROBE_VERSION_H 17 | 18 | #define PROBE_VERSION "${VERSION}" 19 | 20 | #endif 21 | EOF 22 | -------------------------------------------------------------------------------- /src/autobaud.h: -------------------------------------------------------------------------------- 1 | #ifndef AUTOBAUD_H 2 | #define AUTOBAUD_H 3 | 4 | #include "FreeRTOS.h" 5 | #include "queue.h" 6 | #include "semphr.h" 7 | 8 | #define MAGIC_BAUD 9728 // 0x2600 9 | 10 | typedef enum { 11 | AUTOBAUD_CMD_NONE = 0, 12 | AUTOBAUD_CMD_START = 1, 13 | AUTOBAUD_CMD_STOP = 2, 14 | } autobaud_cmd_t; 15 | 16 | typedef struct { 17 | uint32_t baud; // Estimated baud rate 18 | float validity; // Validity of the estimated baud rate 19 | } BaudInfo_t; 20 | 21 | extern volatile bool autobaud_running; 22 | extern volatile bool autobaud_stopped; 23 | extern QueueHandle_t baudQueue; 24 | extern TaskHandle_t autobaud_taskhandle; 25 | 26 | void autobaud_start(void); 27 | void autobaud_wait_stop(void); 28 | void autobaud_thread(void * param); 29 | 30 | #endif -------------------------------------------------------------------------------- /CMSIS_DAP/CMSIS/DAP/Firmware/Validation/MDK5/readme.txt: -------------------------------------------------------------------------------- 1 | CMSIS-DAP debug unit validation 2 | ------------------------------- 3 | 4 | The following debug functionality is tested: 5 | - execution breakpoint with hit count 6 | - breakpoint on read 7 | - breakpoint on write 8 | - memory read 9 | - memory write 10 | - register read 11 | - register write 12 | - single stepping 13 | - run/stop 14 | 15 | The test is self-contained and can be executed on the hardware target. 16 | 17 | Test results get printed into a test log file. 18 | 19 | To configure the test for specific hardware target: 20 | 1) open the uVision project and select device mounted on hardware target 21 | (automatically selects flash algorithm for download) 22 | 2) select CMSIS-DAP debugger (if not already selected) 23 | 3) build the project 24 | 25 | To run the test on the hardware target: 26 | 1) connect hardware target to CMSIS-DAP debug unit via JTAG/SWD 27 | 2) connect CMSIS-DAP debug unit to be tested to PC via USB 28 | 3) open the uVision project and start debug session 29 | 30 | To run the test on the target in batch mode: 31 | execute test.bat 32 | -------------------------------------------------------------------------------- /CMSIS_DAP/CMSIS/DAP/Firmware/Validation/MDK5/test.bat: -------------------------------------------------------------------------------- 1 | @ECHO off 2 | 3 | REM Usage: test.bat [PATH TO UV4.exe] 4 | 5 | IF "%1"=="" ( 6 | SET UV4_EXE=C:\Keil\UV4\UV4.exe 7 | ) ELSE ( 8 | SET UV4_EXE=%1 9 | ) 10 | ECHO Using %UV4_EXE% 11 | 12 | ECHO. 13 | ECHO Building application... 14 | IF EXIST .\Objects\Validation.axf del .\Objects\Validation.axf 15 | 16 | %UV4_EXE% -b Validation.uvprojx 17 | 18 | IF EXIST .\Objects\Validation.axf ( 19 | ECHO Build succeded 20 | ) ELSE ( 21 | ECHO Build failed 22 | GOTO :done 23 | ) 24 | 25 | ECHO. 26 | ECHO Loading application to hardware target... 27 | %UV4_EXE% -f Validation.uvprojx -t"CMSIS_DAP" 28 | 29 | IF ERRORLEVEL 1 ( 30 | ECHO Flash download failed 31 | GOTO :done 32 | ) 33 | 34 | ECHO. 35 | ECHO Debugging hardware target... 36 | IF EXIST .\test_results.txt del .\test_results.txt 37 | 38 | %UV4_EXE% -d Validation.uvprojx -t"CMSIS_DAP" 39 | 40 | IF EXIST .\test_results.txt ( 41 | TYPE .\test_results.txt 42 | ) ELSE ( 43 | ECHO Test ended abnormally - file test_results.txt was not produced 44 | GOTO :done 45 | ) 46 | 47 | ECHO. 48 | ECHO All tests completed 49 | 50 | :done 51 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Unless otherwise indicated in individual files, this project is licenced as: 2 | 3 | MIT License 4 | 5 | Copyright (c) 2024 Raspberry Pi Ltd 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | -------------------------------------------------------------------------------- /src/tusb_edpt_handler.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2023 Raspberry Pi (Trading) Ltd. 3 | * 4 | * SPDX-License-Identifier: BSD-3-Clause 5 | */ 6 | 7 | #ifndef TUSB_EDPT_HANDLER_H 8 | #define TUSB_EDPT_HANDLER_H 9 | 10 | #include "tusb.h" 11 | 12 | #include "device/usbd_pvt.h" 13 | #include "DAP_config.h" 14 | 15 | #define DAP_INTERFACE_SUBCLASS 0x00 16 | #define DAP_INTERFACE_PROTOCOL 0x00 17 | 18 | typedef struct { 19 | uint8_t data[DAP_PACKET_COUNT][DAP_PACKET_SIZE]; 20 | volatile uint32_t wptr; 21 | volatile uint32_t rptr; 22 | volatile bool wasEmpty; 23 | volatile bool wasFull; 24 | } buffer_t; 25 | 26 | extern TaskHandle_t dap_taskhandle, tud_taskhandle; 27 | 28 | /* Main DAP loop */ 29 | void dap_thread(void *ptr); 30 | 31 | /* Endpoint Handling */ 32 | void dap_edpt_init(void); 33 | uint16_t dap_edpt_open(uint8_t __unused rhport, tusb_desc_interface_t const *itf_desc, uint16_t max_len); 34 | bool dap_edpt_control_xfer_cb(uint8_t __unused rhport, uint8_t stage, tusb_control_request_t const *request); 35 | bool dap_edpt_xfer_cb(uint8_t __unused rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); 36 | 37 | /* Helper Functions */ 38 | bool buffer_full(buffer_t *buffer); 39 | bool buffer_empty(buffer_t *buffer); 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /src/cdc_uart.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2021 Raspberry Pi (Trading) Ltd. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | * 24 | */ 25 | 26 | #ifndef CDC_UART_H 27 | #define CDC_UART_H 28 | 29 | void cdc_thread(void *ptr); 30 | void cdc_uart_init(void); 31 | bool cdc_task(void); 32 | 33 | extern TaskHandle_t uart_taskhandle; 34 | 35 | #endif -------------------------------------------------------------------------------- /src/probe_config.c: -------------------------------------------------------------------------------- 1 | #include "probe_config.h" 2 | #include "pico/binary_info.h" 3 | #include "probe/version.h" 4 | 5 | #define STR_HELPER(x) #x 6 | #define STR(x) STR_HELPER(x) 7 | 8 | 9 | void bi_decl_config() 10 | { 11 | bi_decl(bi_program_version_string(PROBE_VERSION)); 12 | #ifdef PROBE_PIN_RESET 13 | bi_decl(bi_1pin_with_name(PROBE_PIN_RESET, "PROBE RESET")); 14 | #endif 15 | 16 | #ifdef PROBE_PIN_SWCLK 17 | bi_decl(bi_1pin_with_name(PROBE_PIN_SWCLK, "PROBE SWCLK")); 18 | #endif 19 | 20 | #ifdef PROBE_PIN_SWDIO 21 | bi_decl(bi_1pin_with_name(PROBE_PIN_SWDIO, "PROBE SWDIO")); 22 | #endif 23 | 24 | #ifdef PROBE_PIN_SWDI 25 | bi_decl(bi_1pin_with_name(PROBE_PIN_SWDI, "PROBE SWDI")); 26 | #endif 27 | 28 | #ifdef PROBE_PIN_SWDIOEN 29 | bi_decl(bi_1pin_with_name(PROBE_PIN_SWDIOEN, "PROBE SWDIOEN")); 30 | #endif 31 | 32 | #ifdef PROBE_CDC_UART 33 | bi_decl(bi_program_feature("PROBE UART INTERFACE " STR(PROBE_UART_INTERFACE))); 34 | bi_decl(bi_program_feature("PROBE UART BAUDRATE " STR(PROBE_UART_BAUDRATE))); 35 | bi_decl(bi_1pin_with_name(PROBE_UART_TX, "PROBE UART TX")); 36 | bi_decl(bi_1pin_with_name(PROBE_UART_RX, "PROBE UART RX")); 37 | #endif 38 | 39 | #ifdef PROBE_UART_CTS 40 | bi_decl(bi_1pin_with_name(PROBE_UART_CTS, "PROBE UART CTS")); 41 | #endif 42 | #ifdef PROBE_UART_RTS 43 | bi_decl(bi_1pin_with_name(PROBE_UART_RTS, "PROBE UART RTS")); 44 | #endif 45 | #ifdef PROBE_UART_DTR 46 | bi_decl(bi_1pin_with_name(PROBE_UART_DTR, "PROBE UART DTR")); 47 | #endif 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/get_serial.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2021 Federico Zuccardi Merli 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | * 24 | */ 25 | 26 | #ifndef GET_SERIAL_H_ 27 | #define GET_SERIAL_H_ 28 | 29 | /* Contains unique serial number string (NUL terminated) after call to init_usb_serial */ 30 | extern char usb_serial[]; 31 | 32 | /* Fills unique_serial with the flash unique id */ 33 | extern void usb_serial_init(void); 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /src/autobaud.pio: -------------------------------------------------------------------------------- 1 | .program autobaud 2 | 3 | .wrap_target 4 | 5 | falling_edge: 6 | wait 0 pin 0 ; falling edge detected 7 | set x, 0 ; set cycle counter to 0 8 | mov x, ~x ; x = 0xFFFFFFFF, to decrement x 9 | 10 | count_cycles: 11 | jmp pin rising_edge ; if line went high, save current cycle count 12 | jmp x-- count_cycles ; otherwise, decrement and enter loop again 13 | 14 | rising_edge: 15 | mov isr, x ; save elapsed cycle count in ISR 16 | push noblock ; nonblocking push of the ISR content 17 | jmp falling_edge ; repeat sampling process 18 | 19 | .wrap 20 | 21 | % c-sdk { 22 | 23 | // Helper function (for use in C program) to initialize this PIO program 24 | void autobaud_program_init(PIO pio, uint sm, uint offset, uint rx_pin, float div) { 25 | 26 | // Sets up state machine and wrap target. This function is automatically 27 | // generated in autobaud.pio.h. 28 | pio_sm_config c = autobaud_program_get_default_config(offset); 29 | 30 | // No need to set PIO funcsel, as this program is receive-only 31 | sm_config_set_in_pins(&c, rx_pin); 32 | sm_config_set_jmp_pin(&c, rx_pin); 33 | pio_sm_set_consecutive_pindirs(pio, sm, rx_pin, 1, false); 34 | 35 | // Set the clock divider for the state machine 36 | sm_config_set_clkdiv(&c, div); 37 | 38 | // Load configuration and jump to start of the program 39 | pio_sm_init(pio, sm, offset, &c); 40 | } 41 | 42 | %} 43 | -------------------------------------------------------------------------------- /CMSIS_DAP/CMSIS/DAP/Firmware/Template/CMSIS_DAP_v2.inf: -------------------------------------------------------------------------------- 1 | [Version] 2 | Signature = "$Windows NT$" 3 | Class = USBDevice 4 | ClassGUID = {88BAE032-5A81-49f0-BC3D-A4FF138216D6} 5 | Provider = %ManufacturerName% 6 | DriverVer = 04/13/2016, 1.0.0.0 7 | CatalogFile.nt = CMSIS_DAP_v2_x86.cat 8 | CatalogFile.ntx86 = CMSIS_DAP_v2_x86.cat 9 | CatalogFile.ntamd64 = CMSIS_DAP_v2_amd64.cat 10 | 11 | ; ========== Manufacturer/Models sections =========== 12 | 13 | [Manufacturer] 14 | %ManufacturerName% = Devices, NTx86, NTamd64 15 | 16 | [Devices.NTx86] 17 | %DeviceName% = USB_Install, USB\VID_c251&PID_f000 18 | 19 | [Devices.NTamd64] 20 | %DeviceName% = USB_Install, USB\VID_c251&PID_f000 21 | 22 | ; ========== Class definition =========== 23 | 24 | [ClassInstall32] 25 | AddReg = ClassInstall_AddReg 26 | 27 | [ClassInstall_AddReg] 28 | HKR,,,,%ClassName% 29 | HKR,,NoInstallClass,,1 30 | HKR,,IconPath,0x10000,"%%SystemRoot%%\System32\setupapi.dll,-20" 31 | HKR,,LowerLogoVersion,,5.2 32 | 33 | ; =================== Installation =================== 34 | 35 | [USB_Install] 36 | Include = winusb.inf 37 | Needs = WINUSB.NT 38 | 39 | [USB_Install.Services] 40 | Include = winusb.inf 41 | Needs = WINUSB.NT.Services 42 | 43 | [USB_Install.HW] 44 | AddReg = Dev_AddReg 45 | 46 | [Dev_AddReg] 47 | HKR,,DeviceInterfaceGUIDs,0x10000,"{CDB3B5AD-293B-4663-AA36-1AAE46463776}" 48 | 49 | ; =================== Strings =================== 50 | 51 | [Strings] 52 | ClassName = "Universal Serial Bus devices" 53 | ManufacturerName = "KEIL - Tools By ARM" 54 | DeviceName = "CMSIS-DAP v2" 55 | -------------------------------------------------------------------------------- /CMSIS_DAP/CMSIS/Core/Include/cmsis_version.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************//** 2 | * @file cmsis_version.h 3 | * @brief CMSIS Core(M) Version definitions 4 | * @version V5.0.4 5 | * @date 23. July 2019 6 | ******************************************************************************/ 7 | /* 8 | * Copyright (c) 2009-2019 ARM Limited. All rights reserved. 9 | * 10 | * SPDX-License-Identifier: Apache-2.0 11 | * 12 | * Licensed under the Apache License, Version 2.0 (the License); you may 13 | * not use this file except in compliance with the License. 14 | * You may obtain a copy of the License at 15 | * 16 | * www.apache.org/licenses/LICENSE-2.0 17 | * 18 | * Unless required by applicable law or agreed to in writing, software 19 | * distributed under the License is distributed on an AS IS BASIS, WITHOUT 20 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 21 | * See the License for the specific language governing permissions and 22 | * limitations under the License. 23 | */ 24 | 25 | #if defined ( __ICCARM__ ) 26 | #pragma system_include /* treat file as system include file for MISRA check */ 27 | #elif defined (__clang__) 28 | #pragma clang system_header /* treat file as system include file */ 29 | #endif 30 | 31 | #ifndef __CMSIS_VERSION_H 32 | #define __CMSIS_VERSION_H 33 | 34 | /* CMSIS Version definitions */ 35 | #define __CM_CMSIS_VERSION_MAIN ( 5U) /*!< [31:16] CMSIS Core(M) main version */ 36 | #define __CM_CMSIS_VERSION_SUB ( 4U) /*!< [15:0] CMSIS Core(M) sub version */ 37 | #define __CM_CMSIS_VERSION ((__CM_CMSIS_VERSION_MAIN << 16U) | \ 38 | __CM_CMSIS_VERSION_SUB ) /*!< CMSIS Core(M) version number */ 39 | #endif 40 | -------------------------------------------------------------------------------- /CMSIS_DAP/CMSIS/DAP/Firmware/Template/MDK5/osObjects.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013-2017 ARM Limited. All rights reserved. 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the License); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an AS IS BASIS, WITHOUT 14 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * ---------------------------------------------------------------------- 19 | * 20 | * $Date: 1. December 2017 21 | * $Revision: V2.0.0 22 | * 23 | * Project: CMSIS-DAP Template MDK5 24 | * Title: osObjects.h CMSIS-DAP RTOS2 Objects 25 | * 26 | *---------------------------------------------------------------------------*/ 27 | 28 | #ifndef __osObjects_h__ 29 | #define __osObjects_h__ 30 | 31 | #include "cmsis_os2.h" 32 | 33 | #ifdef osObjectsExternal 34 | extern osThreadId_t DAP_ThreadId; 35 | extern osThreadId_t SWO_ThreadId; 36 | #else 37 | const osThreadAttr_t DAP_ThreadAttr = { 38 | .priority = osPriorityNormal 39 | }; 40 | const osThreadAttr_t SWO_ThreadAttr = { 41 | .priority = osPriorityAboveNormal 42 | }; 43 | extern osThreadId_t DAP_ThreadId; 44 | osThreadId_t DAP_ThreadId; 45 | extern osThreadId_t SWO_ThreadId; 46 | osThreadId_t SWO_ThreadId; 47 | #endif 48 | 49 | extern void DAP_Thread (void *argument); 50 | extern void SWO_Thread (void *argument); 51 | 52 | extern void app_main (void *argument); 53 | 54 | #endif /* __osObjects_h__ */ 55 | -------------------------------------------------------------------------------- /include/board_pico_config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2023 Raspberry Pi (Trading) Ltd. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | * 24 | */ 25 | 26 | #ifndef BOARD_PICO_H_ 27 | #define BOARD_PICO_H_ 28 | 29 | #define PROBE_IO_RAW 30 | #define PROBE_CDC_UART 31 | 32 | // PIO config 33 | #define PROBE_SM 0 34 | #define PROBE_PIN_OFFSET 2 35 | #define PROBE_PIN_SWCLK (PROBE_PIN_OFFSET + 0) // 2 36 | #define PROBE_PIN_SWDIO (PROBE_PIN_OFFSET + 1) // 3 37 | // Target reset config 38 | #define PROBE_PIN_RESET 1 39 | 40 | // UART config 41 | #define PROBE_UART_TX 4 42 | #define PROBE_UART_RX 5 43 | #define PROBE_UART_INTERFACE uart1 44 | #define PROBE_UART_BAUDRATE 115200 45 | 46 | #define PROBE_USB_CONNECTED_LED 25 47 | 48 | #define PROBE_PRODUCT_STRING "Debugprobe on Pico (CMSIS-DAP)" 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /src/probe.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2021 Raspberry Pi (Trading) Ltd. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | * 24 | */ 25 | 26 | #ifndef PROBE_H_ 27 | #define PROBE_H_ 28 | 29 | #if defined(PROBE_IO_RAW) || defined(PROBE_IO_SWDI) 30 | #include "probe.pio.h" 31 | #endif 32 | 33 | #if defined(PROBE_IO_OEN) 34 | #include "probe_oen.pio.h" 35 | #endif 36 | 37 | void probe_set_swclk_freq(uint freq_khz); 38 | 39 | // Bit counts in the range 1..256 40 | void probe_write_bits(uint bit_count, uint32_t data_byte); 41 | uint32_t probe_read_bits(uint bit_count); 42 | void probe_hiz_clocks(uint bit_count); 43 | 44 | void probe_read_mode(void); 45 | void probe_write_mode(void); 46 | 47 | void probe_init(void); 48 | void probe_deinit(void); 49 | void probe_assert_reset(bool state); 50 | int probe_reset_level(void); 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /include/board_debug_probe_config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2023 Raspberry Pi (Trading) Ltd. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | * 24 | */ 25 | 26 | #ifndef BOARD_DEBUG_PROBE_H_ 27 | #define BOARD_DEBUG_PROBE_H_ 28 | 29 | #define PROBE_IO_SWDI 30 | #define PROBE_CDC_UART 31 | // No reset pin 32 | 33 | // PIO config 34 | #define PROBE_SM 0 35 | #define PROBE_PIN_OFFSET 12 36 | #define PROBE_PIN_SWCLK (PROBE_PIN_OFFSET + 0) 37 | // For level-shifted input. 38 | #define PROBE_PIN_SWDI (PROBE_PIN_OFFSET + 1) 39 | #define PROBE_PIN_SWDIO (PROBE_PIN_OFFSET + 2) 40 | 41 | // UART config 42 | #define PROBE_UART_TX 4 43 | #define PROBE_UART_RX 5 44 | #define PROBE_UART_INTERFACE uart1 45 | #define PROBE_UART_BAUDRATE 115200 46 | 47 | #define PROBE_USB_CONNECTED_LED 2 48 | #define PROBE_DAP_CONNECTED_LED 15 49 | #define PROBE_DAP_RUNNING_LED 16 50 | #define PROBE_UART_RX_LED 7 51 | #define PROBE_UART_TX_LED 8 52 | 53 | #define PROBE_PRODUCT_STRING "Debug Probe (CMSIS-DAP)" 54 | 55 | #endif 56 | -------------------------------------------------------------------------------- /src/get_serial.c: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2021 Federico Zuccardi Merli 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | * 24 | */ 25 | 26 | #include 27 | #include "pico.h" 28 | #include "pico/unique_id.h" 29 | #include "get_serial.h" 30 | 31 | /* C string for iSerialNumber in USB Device Descriptor, two chars per byte + terminating NUL */ 32 | char usb_serial[PICO_UNIQUE_BOARD_ID_SIZE_BYTES * 2 + 1]; 33 | 34 | /* Why a uint8_t[8] array inside a struct instead of an uint64_t an inquiring mind might wonder */ 35 | static pico_unique_board_id_t uID; 36 | 37 | void usb_serial_init(void) 38 | { 39 | pico_get_unique_board_id(&uID); 40 | 41 | for (int i = 0; i < PICO_UNIQUE_BOARD_ID_SIZE_BYTES * 2; i++) 42 | { 43 | /* Byte index inside the uid array */ 44 | int bi = i / 2; 45 | /* Use high nibble first to keep memory order (just cosmetics) */ 46 | uint8_t nibble = (uID.id[bi] >> 4) & 0x0F; 47 | uID.id[bi] <<= 4; 48 | /* Binary to hex digit */ 49 | usb_serial[i] = nibble < 10 ? nibble + '0' : nibble + 'A' - 10; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/probe_config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2021 Raspberry Pi (Trading) Ltd. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | * 24 | */ 25 | 26 | #ifndef PROBE_CONFIG_H_ 27 | #define PROBE_CONFIG_H_ 28 | 29 | #include "FreeRTOS.h" 30 | #include "task.h" 31 | 32 | #if false 33 | #define probe_info(format,args...) \ 34 | do { \ 35 | vTaskSuspendAll(); \ 36 | printf(format, ## args); \ 37 | xTaskResumeAll(); \ 38 | } while (0) 39 | #else 40 | #define probe_info(format,...) ((void)0) 41 | #endif 42 | 43 | 44 | #if false 45 | #define probe_debug(format,args...) \ 46 | do { \ 47 | vTaskSuspendAll(); \ 48 | printf(format, ## args); \ 49 | xTaskResumeAll(); \ 50 | } while (0) 51 | #else 52 | #define probe_debug(format,...) ((void)0) 53 | #endif 54 | 55 | #if false 56 | #define probe_dump(format,args...)\ 57 | do { \ 58 | vTaskSuspendAll(); \ 59 | printf(format, ## args); \ 60 | xTaskResumeAll(); \ 61 | } while (0) 62 | #else 63 | #define probe_dump(format,...) ((void)0) 64 | #endif 65 | 66 | // TODO tie this up with PICO_BOARD defines in the main SDK 67 | 68 | #ifdef DEBUG_ON_PICO 69 | #include "board_pico_config.h" 70 | #else 71 | #include "board_debug_probe_config.h" 72 | #endif 73 | //#include "board_example_config.h" 74 | 75 | // Add the configuration to binary information 76 | void bi_decl_config(); 77 | 78 | #define PROTO_DAP_V1 1 79 | #define PROTO_DAP_V2 2 80 | 81 | // Interface config 82 | #ifndef PROBE_DEBUG_PROTOCOL 83 | #define PROBE_DEBUG_PROTOCOL PROTO_DAP_V2 84 | #endif 85 | 86 | #endif 87 | -------------------------------------------------------------------------------- /CMSIS_DAP/CMSIS/DAP/Firmware/Template/MDK5/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013-2017 ARM Limited. All rights reserved. 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the License); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an AS IS BASIS, WITHOUT 14 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * ---------------------------------------------------------------------- 19 | * 20 | * $Date: 1. December 2017 21 | * $Revision: V2.0.0 22 | * 23 | * Project: CMSIS-DAP Template MDK5 24 | * Title: main.c CMSIS-DAP Main module 25 | * 26 | *---------------------------------------------------------------------------*/ 27 | 28 | #include "cmsis_os2.h" 29 | #include "osObjects.h" 30 | #include "rl_usb.h" 31 | #include "DAP_config.h" 32 | #include "DAP.h" 33 | 34 | // Application Main program 35 | __NO_RETURN void app_main (void *argument) { 36 | (void)argument; 37 | 38 | DAP_Setup(); // DAP Setup 39 | 40 | USBD_Initialize(0U); // USB Device Initialization 41 | USBD_Connect(0U); // USB Device Connect 42 | 43 | while (!USBD_Configured(0U)); // Wait for USB Device to configure 44 | 45 | LED_CONNECTED_OUT(1U); // Turn on Debugger Connected LED 46 | LED_RUNNING_OUT(1U); // Turn on Target Running LED 47 | Delayms(500U); // Wait for 500ms 48 | LED_RUNNING_OUT(0U); // Turn off Target Running LED 49 | LED_CONNECTED_OUT(0U); // Turn off Debugger Connected LED 50 | 51 | // Create DAP Thread 52 | DAP_ThreadId = osThreadNew(DAP_Thread, NULL, &DAP_ThreadAttr); 53 | 54 | // Create SWO Thread 55 | SWO_ThreadId = osThreadNew(SWO_Thread, NULL, &SWO_ThreadAttr); 56 | 57 | osDelay(osWaitForever); 58 | for (;;) {}; 59 | } 60 | 61 | int main (void) { 62 | 63 | SystemCoreClockUpdate(); 64 | osKernelInitialize(); // Initialize CMSIS-RTOS 65 | osThreadNew(app_main, NULL, NULL); // Create application main thread 66 | if (osKernelGetState() == osKernelReady) { 67 | osKernelStart(); // Start thread execution 68 | } 69 | 70 | for (;;) {}; 71 | } 72 | -------------------------------------------------------------------------------- /CMSIS_DAP/CMSIS/DAP/Firmware/Validation/MDK5/RTE/Device/ARMCM3/system_ARMCM3.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************//** 2 | * @file system_ARMCM3.c 3 | * @brief CMSIS Device System Source File for 4 | * ARMCM3 Device Series 5 | * @version V5.00 6 | * @date 07. September 2016 7 | ******************************************************************************/ 8 | /* 9 | * Copyright (c) 2009-2016 ARM Limited. All rights reserved. 10 | * 11 | * SPDX-License-Identifier: Apache-2.0 12 | * 13 | * Licensed under the Apache License, Version 2.0 (the License); you may 14 | * not use this file except in compliance with the License. 15 | * You may obtain a copy of the License at 16 | * 17 | * www.apache.org/licenses/LICENSE-2.0 18 | * 19 | * Unless required by applicable law or agreed to in writing, software 20 | * distributed under the License is distributed on an AS IS BASIS, WITHOUT 21 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 22 | * See the License for the specific language governing permissions and 23 | * limitations under the License. 24 | */ 25 | 26 | #include "ARMCM3.h" 27 | 28 | /*---------------------------------------------------------------------------- 29 | Define clocks 30 | *----------------------------------------------------------------------------*/ 31 | #define XTAL ( 5000000UL) /* Oscillator frequency */ 32 | 33 | #define SYSTEM_CLOCK (5U * XTAL) 34 | 35 | 36 | /*---------------------------------------------------------------------------- 37 | Externals 38 | *----------------------------------------------------------------------------*/ 39 | #if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U) 40 | extern uint32_t __Vectors; 41 | #endif 42 | 43 | /*---------------------------------------------------------------------------- 44 | System Core Clock Variable 45 | *----------------------------------------------------------------------------*/ 46 | uint32_t SystemCoreClock = SYSTEM_CLOCK; 47 | 48 | 49 | /*---------------------------------------------------------------------------- 50 | System Core Clock update function 51 | *----------------------------------------------------------------------------*/ 52 | void SystemCoreClockUpdate (void) 53 | { 54 | SystemCoreClock = SYSTEM_CLOCK; 55 | } 56 | 57 | /*---------------------------------------------------------------------------- 58 | System initialization function 59 | *----------------------------------------------------------------------------*/ 60 | void SystemInit (void) 61 | { 62 | 63 | #if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U) 64 | SCB->VTOR = (uint32_t) &__Vectors; 65 | #endif 66 | 67 | SystemCoreClock = SYSTEM_CLOCK; 68 | } 69 | -------------------------------------------------------------------------------- /CMSIS_DAP/CMSIS/DAP/Firmware/Validation/MDK5/test.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013-2017 ARM Limited. All rights reserved. 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the License); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an AS IS BASIS, WITHOUT 14 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * ---------------------------------------------------------------------- 19 | * 20 | * $Date: 1. December 2017 21 | * $Revision: V2.0.0 22 | * 23 | * Project: CMSIS-DAP Validation 24 | * Title: test.c CMSIS-DAP debug unit test module 25 | * 26 | *---------------------------------------------------------------------------*/ 27 | 28 | // Debug Variables 29 | volatile int test_state = 0; 30 | volatile int test_success = 0; 31 | volatile int bpTestCounter = 0; 32 | volatile char mem_rw_success = 0; 33 | int test_array1[256] = {0}; 34 | int test_array2[256] = {0}; 35 | 36 | // Breakpoint Test function 37 | static void BP_Test (void) { 38 | int i; 39 | 40 | for (i = 0; i < 10; i++) { 41 | // increment counter so we know on which iteration breakpoint is hit 42 | bpTestCounter++; 43 | test_state++; 44 | } 45 | } 46 | 47 | // Test function 48 | static void Test(void) { 49 | int i; 50 | 51 | test_state++; // 'test_state' = 11 52 | i = test_success; // 'test_success' read access 53 | 54 | test_state++; // 'test_state' = 12 55 | test_success = i; // 'test_success' write access 56 | 57 | test_state++; // 'test_state' = 13 58 | 59 | // test_array1 should have already been written by debugger 60 | // copy test_array1 into test_array2 for future comparison 61 | mem_rw_success = 1; // assume all values were written correctly 62 | for (i = 0; i < 256; i++) { 63 | if (test_array1[i] != (0x1000+i)) { 64 | mem_rw_success = 0; 65 | } 66 | test_array2[i] = test_array1[i]; 67 | } 68 | 69 | test_state++; // 'test_state' = 14 70 | test_state++; // 'test_state' = 15 71 | test_state++; // 'test_state' = 16 72 | // execute 'test_state -= 16' from debugger 73 | test_state++; // 'test_state' = 1 74 | 75 | if (test_state == 1) { 76 | test_success = 1; 77 | } else { 78 | test_success = 0; 79 | } 80 | } 81 | 82 | // 'main' function 83 | int main (void) { 84 | 85 | BP_Test(); 86 | Test(); 87 | 88 | for (;;) {}; 89 | } 90 | -------------------------------------------------------------------------------- /CMSIS_DAP/CMSIS/Core/Include/tz_context.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * @file tz_context.h 3 | * @brief Context Management for Armv8-M TrustZone 4 | * @version V1.0.1 5 | * @date 10. January 2018 6 | ******************************************************************************/ 7 | /* 8 | * Copyright (c) 2017-2018 Arm Limited. All rights reserved. 9 | * 10 | * SPDX-License-Identifier: Apache-2.0 11 | * 12 | * Licensed under the Apache License, Version 2.0 (the License); you may 13 | * not use this file except in compliance with the License. 14 | * You may obtain a copy of the License at 15 | * 16 | * www.apache.org/licenses/LICENSE-2.0 17 | * 18 | * Unless required by applicable law or agreed to in writing, software 19 | * distributed under the License is distributed on an AS IS BASIS, WITHOUT 20 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 21 | * See the License for the specific language governing permissions and 22 | * limitations under the License. 23 | */ 24 | 25 | #if defined ( __ICCARM__ ) 26 | #pragma system_include /* treat file as system include file for MISRA check */ 27 | #elif defined (__clang__) 28 | #pragma clang system_header /* treat file as system include file */ 29 | #endif 30 | 31 | #ifndef TZ_CONTEXT_H 32 | #define TZ_CONTEXT_H 33 | 34 | #include 35 | 36 | #ifndef TZ_MODULEID_T 37 | #define TZ_MODULEID_T 38 | /// \details Data type that identifies secure software modules called by a process. 39 | typedef uint32_t TZ_ModuleId_t; 40 | #endif 41 | 42 | /// \details TZ Memory ID identifies an allocated memory slot. 43 | typedef uint32_t TZ_MemoryId_t; 44 | 45 | /// Initialize secure context memory system 46 | /// \return execution status (1: success, 0: error) 47 | uint32_t TZ_InitContextSystem_S (void); 48 | 49 | /// Allocate context memory for calling secure software modules in TrustZone 50 | /// \param[in] module identifies software modules called from non-secure mode 51 | /// \return value != 0 id TrustZone memory slot identifier 52 | /// \return value 0 no memory available or internal error 53 | TZ_MemoryId_t TZ_AllocModuleContext_S (TZ_ModuleId_t module); 54 | 55 | /// Free context memory that was previously allocated with \ref TZ_AllocModuleContext_S 56 | /// \param[in] id TrustZone memory slot identifier 57 | /// \return execution status (1: success, 0: error) 58 | uint32_t TZ_FreeModuleContext_S (TZ_MemoryId_t id); 59 | 60 | /// Load secure context (called on RTOS thread context switch) 61 | /// \param[in] id TrustZone memory slot identifier 62 | /// \return execution status (1: success, 0: error) 63 | uint32_t TZ_LoadContext_S (TZ_MemoryId_t id); 64 | 65 | /// Store secure context (called on RTOS thread context switch) 66 | /// \param[in] id TrustZone memory slot identifier 67 | /// \return execution status (1: success, 0: error) 68 | uint32_t TZ_StoreContext_S (TZ_MemoryId_t id); 69 | 70 | #endif // TZ_CONTEXT_H 71 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Debugprobe 2 | 3 | Firmware source for the Raspberry Pi Debug Probe SWD/UART accessory. Can also be run on a Raspberry Pi Pico or Pico 2. 4 | 5 | [Raspberry Pi Debug Probe product page](https://www.raspberrypi.com/products/debug-probe/) 6 | 7 | [Raspberry Pi Pico product page](https://www.raspberrypi.com/products/raspberry-pi-pico/) 8 | 9 | [Raspberry Pi Pico 2 product page](https://www.raspberrypi.com/products/raspberry-pi-pico-2/) 10 | 11 | # Documentation 12 | 13 | Debug Probe documentation can be found at the [Raspberry Pi Microcontroller Documentation portal](https://www.raspberrypi.com/documentation/microcontrollers/debug-probe.html#about-the-debug-probe). 14 | 15 | # Hacking 16 | 17 | For the purpose of making changes or studying of the code, you may want to compile the code yourself. 18 | 19 | First, clone the repository: 20 | ``` 21 | git clone https://github.com/raspberrypi/debugprobe 22 | cd debugprobe 23 | ``` 24 | Initialize and update the submodules: 25 | ``` 26 | git submodule update --init --recursive 27 | ``` 28 | Then create and switch to the build directory: 29 | ``` 30 | mkdir build 31 | cd build 32 | ``` 33 | If your environment doesn't contain `PICO_SDK_PATH`, then either add it to your environment variables with `export PICO_SDK_PATH=/path/to/sdk` or add `-DPICO_SDK_PATH=/path/to/sdk` to the arguments to CMake below. 34 | 35 | Run cmake and build the code: 36 | ``` 37 | cmake .. 38 | make 39 | ``` 40 | Done! You should now have a `debugprobe.uf2` that you can upload to your Debug Probe via the UF2 bootloader. 41 | 42 | ## Building for the Pico 1 43 | 44 | If you want to create the version that runs on the Pico, then you need to invoke `cmake` in the sequence above with the `DEBUG_ON_PICO=ON` option: 45 | ``` 46 | cmake -DDEBUG_ON_PICO=ON .. 47 | ``` 48 | This will build with the configuration for the Pico and call the output program `debugprobe_on_pico.uf2`, as opposed to `debugprobe.uf2` for the accessory hardware. 49 | 50 | Note that if you first ran through the whole sequence to compile for the Debug Probe, then you don't need to start back at the top. You can just go back to the `cmake` step and start from there. 51 | 52 | ## Building for the Pico 2 53 | 54 | If using an existing debugprobe clone: 55 | - You must completely regenerate your build directory, or use a different one. 56 | - You must also sync and update submodules. 57 | - `PICO_SDK_PATH` must point to a version 2.0.0 or greater install. 58 | 59 | ``` 60 | git submodule sync 61 | git submodule update --init --recursive 62 | mkdir build-pico2 63 | cd build-pico2 64 | cmake -DDEBUG_ON_PICO=1 -DPICO_BOARD=pico2 ../ 65 | ``` 66 | This will build with the configuration for the Pico 2 and call the output program `debugprobe_on_pico2.uf2`. 67 | 68 | # AutoBaud 69 | 70 | Mode which automatically detects and sets the UART baud rate as data arrives. 71 | 72 | To enable AutoBaud, configure the USB CDC port to the following custom baud rate: 73 | ``` 74 | 9728 (0x2600) 75 | ``` 76 | > **Note:** Some Linux serial tools cannot set custom baud values. PuTTY on Windows and any terminal that supports arbitrary baud rates works. 77 | 78 | Changing the baud rate to any other value disables AutoBaud. 79 | 80 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.12) 2 | 3 | include(pico_sdk_import.cmake) 4 | 5 | set(FREERTOS_KERNEL_PATH ${CMAKE_CURRENT_LIST_DIR}/freertos) 6 | include(FreeRTOS_Kernel_import.cmake) 7 | 8 | project(debugprobe) 9 | 10 | pico_sdk_init() 11 | 12 | if (${PICO_SDK_VERSION_MAJOR} LESS 2) 13 | message(SEND_ERROR "Version 2 of the Pico SDK is required to compile this project. Please update your installation at ${PICO_SDK_PATH}") 14 | endif () 15 | 16 | add_executable(debugprobe 17 | src/probe_config.c 18 | src/main.c 19 | src/usb_descriptors.c 20 | src/probe.c 21 | src/cdc_uart.c 22 | src/get_serial.c 23 | src/sw_dp_pio.c 24 | src/tusb_edpt_handler.c 25 | src/autobaud.c 26 | ) 27 | 28 | target_sources(debugprobe PRIVATE 29 | CMSIS_DAP/CMSIS/DAP/Firmware/Source/DAP.c 30 | CMSIS_DAP/CMSIS/DAP/Firmware/Source/JTAG_DP.c 31 | CMSIS_DAP/CMSIS/DAP/Firmware/Source/DAP_vendor.c 32 | CMSIS_DAP/CMSIS/DAP/Firmware/Source/SWO.c 33 | #CMSIS_DAP/CMSIS/DAP/Firmware/Source/SW_DP.c 34 | ) 35 | 36 | target_include_directories(debugprobe PRIVATE 37 | CMSIS_DAP/CMSIS/DAP/Firmware/Include/ 38 | CMSIS_DAP/CMSIS/Core/Include/ 39 | include/ 40 | ) 41 | 42 | target_compile_options(debugprobe PRIVATE -Wall) 43 | 44 | pico_generate_pio_header(debugprobe ${CMAKE_CURRENT_LIST_DIR}/src/probe.pio) 45 | pico_generate_pio_header(debugprobe ${CMAKE_CURRENT_LIST_DIR}/src/probe_oen.pio) 46 | pico_generate_pio_header(debugprobe ${CMAKE_CURRENT_LIST_DIR}/src/autobaud.pio) 47 | 48 | target_include_directories(debugprobe PRIVATE src) 49 | 50 | # add version 51 | add_custom_target(version 52 | ${CMAKE_SOURCE_DIR}/get-version.sh 53 | WORKING_DIRECTORY ${CMAKE_BINARY_DIR} 54 | ) 55 | 56 | target_include_directories(debugprobe PRIVATE 57 | ${CMAKE_BINARY_DIR}/generated 58 | ) 59 | 60 | add_dependencies(debugprobe version) 61 | 62 | target_compile_definitions (debugprobe PRIVATE 63 | PICO_RP2040_USB_DEVICE_ENUMERATION_FIX=1 64 | ) 65 | 66 | option (DEBUG_ON_PICO "Compile firmware for the Pico instead of Debug Probe" OFF) 67 | if (DEBUG_ON_PICO) 68 | target_compile_definitions (debugprobe PRIVATE 69 | DEBUG_ON_PICO=1 70 | ) 71 | if (PICO_BOARD STREQUAL "pico") 72 | set_target_properties(debugprobe PROPERTIES 73 | OUTPUT_NAME "debugprobe_on_pico" 74 | ) 75 | elseif (PICO_BOARD STREQUAL "pico2") 76 | set_target_properties(debugprobe PROPERTIES 77 | OUTPUT_NAME "debugprobe_on_pico2" 78 | ) 79 | else () 80 | message(SEND_ERROR "Unsupported board ${PICO_BOARD}") 81 | endif () 82 | endif () 83 | 84 | 85 | target_link_libraries(debugprobe PRIVATE 86 | pico_multicore 87 | pico_stdlib 88 | pico_unique_id 89 | tinyusb_device 90 | tinyusb_board 91 | hardware_pio 92 | hardware_dma 93 | hardware_irq 94 | hardware_clocks 95 | FreeRTOS-Kernel 96 | FreeRTOS-Kernel-Heap1 97 | ) 98 | 99 | pico_set_binary_type(debugprobe copy_to_ram) 100 | 101 | pico_add_extra_outputs(debugprobe) 102 | -------------------------------------------------------------------------------- /src/tusb_config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2019 Ha Thach (tinyusb.org) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | * 24 | */ 25 | 26 | #ifndef _TUSB_CONFIG_H_ 27 | #define _TUSB_CONFIG_H_ 28 | 29 | #ifdef __cplusplus 30 | extern "C" { 31 | #endif 32 | 33 | //-------------------------------------------------------------------- 34 | // COMMON CONFIGURATION 35 | //-------------------------------------------------------------------- 36 | 37 | // defined by compiler flags for flexibility 38 | #ifndef CFG_TUSB_MCU 39 | #error CFG_TUSB_MCU must be defined 40 | #endif 41 | 42 | #define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE 43 | 44 | #ifndef CFG_TUSB_OS 45 | #define CFG_TUSB_OS OPT_OS_PICO 46 | #endif 47 | 48 | #ifndef CFG_TUSB_MEM_SECTION 49 | #define CFG_TUSB_MEM_SECTION 50 | #endif 51 | 52 | #ifndef CFG_TUSB_MEM_ALIGN 53 | #define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4))) 54 | #endif 55 | 56 | //-------------------------------------------------------------------- 57 | // DEVICE CONFIGURATION 58 | //-------------------------------------------------------------------- 59 | 60 | #ifndef CFG_TUD_ENDPOINT0_SIZE 61 | #define CFG_TUD_ENDPOINT0_SIZE 64 62 | #endif 63 | 64 | //------------- CLASS -------------// 65 | #define CFG_TUD_HID 1 66 | #define CFG_TUD_CDC 1 67 | #define CFG_TUD_MSC 0 68 | #define CFG_TUD_MIDI 0 69 | #define CFG_TUD_VENDOR 1 70 | 71 | /* 72 | * TX bufsize (actually UART RX) is oversized because the Windows CDC-ACM 73 | * driver submits a grand total of _one_ URB at any one time. 74 | * This means the application must consume the data before the next IN token 75 | * is issued. At high datarates this leads to huge variation in instantaneous 76 | * throughput on USB, so a large runway is needed. 77 | */ 78 | #define CFG_TUD_CDC_RX_BUFSIZE 64 79 | #define CFG_TUD_CDC_TX_BUFSIZE 4096 80 | 81 | #define CFG_TUD_VENDOR_RX_BUFSIZE 8192 82 | #define CFG_TUD_VENDOR_TX_BUFSIZE 8192 83 | 84 | #ifndef TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX 85 | #define TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX 1 86 | #endif 87 | 88 | #ifdef __cplusplus 89 | } 90 | #endif 91 | 92 | #endif /* _TUSB_CONFIG_H_ */ 93 | -------------------------------------------------------------------------------- /pico_sdk_import.cmake: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-3-Clause 2 | # This is a copy of /external/pico_sdk_import.cmake 3 | 4 | # This can be dropped into an external project to help locate this SDK 5 | # It should be include()ed prior to project() 6 | 7 | if (DEFINED ENV{PICO_SDK_PATH} AND (NOT PICO_SDK_PATH)) 8 | set(PICO_SDK_PATH $ENV{PICO_SDK_PATH}) 9 | message("Using PICO_SDK_PATH from environment ('${PICO_SDK_PATH}')") 10 | endif () 11 | 12 | if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT} AND (NOT PICO_SDK_FETCH_FROM_GIT)) 13 | set(PICO_SDK_FETCH_FROM_GIT $ENV{PICO_SDK_FETCH_FROM_GIT}) 14 | message("Using PICO_SDK_FETCH_FROM_GIT from environment ('${PICO_SDK_FETCH_FROM_GIT}')") 15 | endif () 16 | 17 | if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_PATH} AND (NOT PICO_SDK_FETCH_FROM_GIT_PATH)) 18 | set(PICO_SDK_FETCH_FROM_GIT_PATH $ENV{PICO_SDK_FETCH_FROM_GIT_PATH}) 19 | message("Using PICO_SDK_FETCH_FROM_GIT_PATH from environment ('${PICO_SDK_FETCH_FROM_GIT_PATH}')") 20 | endif () 21 | 22 | set(PICO_SDK_PATH "${PICO_SDK_PATH}" CACHE PATH "Path to the Raspberry Pi Pico SDK") 23 | set(PICO_SDK_FETCH_FROM_GIT "${PICO_SDK_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of SDK from git if not otherwise locatable") 24 | set(PICO_SDK_FETCH_FROM_GIT_PATH "${PICO_SDK_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download SDK") 25 | 26 | if (NOT PICO_SDK_PATH) 27 | if (PICO_SDK_FETCH_FROM_GIT) 28 | include(FetchContent) 29 | set(FETCHCONTENT_BASE_DIR_SAVE ${FETCHCONTENT_BASE_DIR}) 30 | if (PICO_SDK_FETCH_FROM_GIT_PATH) 31 | get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_SDK_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}") 32 | endif () 33 | # GIT_SUBMODULES_RECURSE was added in 3.17 34 | if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.17.0") 35 | FetchContent_Declare( 36 | pico_sdk 37 | GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk 38 | GIT_TAG master 39 | GIT_SUBMODULES_RECURSE FALSE 40 | ) 41 | else () 42 | FetchContent_Declare( 43 | pico_sdk 44 | GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk 45 | GIT_TAG master 46 | ) 47 | endif () 48 | 49 | if (NOT pico_sdk) 50 | message("Downloading Raspberry Pi Pico SDK") 51 | FetchContent_Populate(pico_sdk) 52 | set(PICO_SDK_PATH ${pico_sdk_SOURCE_DIR}) 53 | endif () 54 | set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE}) 55 | else () 56 | message(FATAL_ERROR 57 | "SDK location was not specified. Please set PICO_SDK_PATH or set PICO_SDK_FETCH_FROM_GIT to on to fetch from git." 58 | ) 59 | endif () 60 | endif () 61 | 62 | get_filename_component(PICO_SDK_PATH "${PICO_SDK_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}") 63 | if (NOT EXISTS ${PICO_SDK_PATH}) 64 | message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' not found") 65 | endif () 66 | 67 | set(PICO_SDK_INIT_CMAKE_FILE ${PICO_SDK_PATH}/pico_sdk_init.cmake) 68 | if (NOT EXISTS ${PICO_SDK_INIT_CMAKE_FILE}) 69 | message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' does not appear to contain the Raspberry Pi Pico SDK") 70 | endif () 71 | 72 | set(PICO_SDK_PATH ${PICO_SDK_PATH} CACHE PATH "Path to the Raspberry Pi Pico SDK" FORCE) 73 | 74 | include(${PICO_SDK_INIT_CMAKE_FILE}) 75 | -------------------------------------------------------------------------------- /include/board_example_config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2023 Raspberry Pi (Trading) Ltd. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | * 24 | */ 25 | 26 | #ifndef BOARD_EXAMPLE_H_ 27 | #define BOARD_EXAMPLE_H_ 28 | #error "Example board configuration requested - specify PICO_BOARD and re-run CMake." 29 | 30 | /* Select one of these. */ 31 | /* Direct connection - SWCLK/SWDIO on two GPIOs */ 32 | #define PROBE_IO_RAW 33 | /* SWCLK connected to a GPIO, SWDO driven from a GPIO, SWDI sampled via a level shifter */ 34 | #define PROBE_IO_SWDI 35 | /* Level-shifted SWCLK, SWDIO with separate SWDO, SWDI and OE_N pin */ 36 | #define PROBE_IO_OEN 37 | 38 | /* Include CDC interface to bridge to target UART. Omit if not used. */ 39 | #define PROBE_CDC_UART 40 | 41 | /* Board implements hardware flow control for UART RTS/CTS instead of ACM control */ 42 | #define PROBE_UART_HWFC 43 | 44 | /* Target reset GPIO (active-low). Omit if not used.*/ 45 | #define PROBE_PIN_RESET 1 46 | 47 | #define PROBE_SM 0 48 | #define PROBE_PIN_OFFSET 12 49 | /* PIO config for PROBE_IO_RAW */ 50 | #if defined(PROBE_IO_RAW) 51 | #define PROBE_PIN_SWCLK (PROBE_PIN_OFFSET + 0) 52 | #define PROBE_PIN_SWDIO (PROBE_PIN_OFFSET + 1) 53 | #endif 54 | 55 | /* PIO config for PROBE_IO_SWDI */ 56 | #if defined(PROBE_IO_SWDI) 57 | #define PROBE_PIN_SWCLK (PROBE_PIN_OFFSET + 0) 58 | #define PROBE_PIN_SWDIO (PROBE_PIN_OFFSET + 1) 59 | #define PROBE_PIN_SWDI (PROBE_PIN_OFFSET + 2) 60 | #endif 61 | 62 | /* PIO config for PROBE_IO_OEN - note that SWDIOEN and SWCLK are both side_set signals, so must be consecutive. */ 63 | #if defined(PROBE_IO_OEN) 64 | #define PROBE_PIN_SWDIOEN (PROBE_PIN_OFFSET + 0) 65 | #define PROBE_PIN_SWCLK (PROBE_PIN_OFFSET + 1) 66 | #define PROBE_PIN_SWDIO (PROBE_PIN_OFFSET + 2) 67 | #define PROBE_PIN_SWDI (PROBE_PIN_OFFSET + 3) 68 | #endif 69 | 70 | #if defined(PROBE_CDC_UART) 71 | #define PROBE_UART_TX 4 72 | #define PROBE_UART_RX 5 73 | #define PROBE_UART_INTERFACE uart1 74 | #define PROBE_UART_BAUDRATE 115200 75 | 76 | #if defined(PROBE_UART_HWFC) 77 | /* Hardware flow control - see 1.4.3 in the RP2040 datasheet for valid pin settings */ 78 | #define PROBE_UART_CTS 6 79 | #define PROBE_UART_RTS 7 80 | #else 81 | /* Software flow control - RTS and DTR can be omitted if not used */ 82 | #define PROBE_UART_RTS 9 83 | #endif 84 | #define PROBE_UART_DTR 10 85 | 86 | #endif 87 | 88 | /* LED config - some or all of these can be omitted if not used */ 89 | #define PROBE_USB_CONNECTED_LED 2 90 | #define PROBE_DAP_CONNECTED_LED 15 91 | #define PROBE_DAP_RUNNING_LED 16 92 | #define PROBE_UART_RX_LED 7 93 | #define PROBE_UART_TX_LED 8 94 | 95 | #define PROBE_PRODUCT_STRING "Example Debug Probe" 96 | 97 | #endif 98 | -------------------------------------------------------------------------------- /CMSIS_DAP/CMSIS/DAP/Firmware/Source/DAP_vendor.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013-2017 ARM Limited. All rights reserved. 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the License); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an AS IS BASIS, WITHOUT 14 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * ---------------------------------------------------------------------- 19 | * 20 | * $Date: 1. December 2017 21 | * $Revision: V2.0.0 22 | * 23 | * Project: CMSIS-DAP Source 24 | * Title: DAP_vendor.c CMSIS-DAP Vendor Commands 25 | * 26 | *---------------------------------------------------------------------------*/ 27 | 28 | #include "DAP_config.h" 29 | #include "DAP.h" 30 | 31 | //************************************************************************************************** 32 | /** 33 | \defgroup DAP_Vendor_Adapt_gr Adapt Vendor Commands 34 | \ingroup DAP_Vendor_gr 35 | @{ 36 | 37 | The file DAP_vendor.c provides template source code for extension of a Debug Unit with 38 | Vendor Commands. Copy this file to the project folder of the Debug Unit and add the 39 | file to the MDK-ARM project under the file group Configuration. 40 | */ 41 | 42 | /** Process DAP Vendor Command and prepare Response Data 43 | \param request pointer to request data 44 | \param response pointer to response data 45 | \return number of bytes in response (lower 16 bits) 46 | number of bytes in request (upper 16 bits) 47 | */ 48 | uint32_t DAP_ProcessVendorCommand(const uint8_t *request, uint8_t *response) { 49 | uint32_t num = (1U << 16) | 1U; 50 | 51 | *response++ = *request; // copy Command ID 52 | 53 | switch (*request++) { // first byte in request is Command ID 54 | case ID_DAP_Vendor0: 55 | #if 0 // example user command 56 | num += 1U << 16; // increment request count 57 | if (*request == 1U) { // when first command data byte is 1 58 | *response++ = 'X'; // send 'X' as response 59 | num++; // increment response count 60 | } 61 | #endif 62 | break; 63 | 64 | case ID_DAP_Vendor1: break; 65 | case ID_DAP_Vendor2: break; 66 | case ID_DAP_Vendor3: break; 67 | case ID_DAP_Vendor4: break; 68 | case ID_DAP_Vendor5: break; 69 | case ID_DAP_Vendor6: break; 70 | case ID_DAP_Vendor7: break; 71 | case ID_DAP_Vendor8: break; 72 | case ID_DAP_Vendor9: break; 73 | case ID_DAP_Vendor10: break; 74 | case ID_DAP_Vendor11: break; 75 | case ID_DAP_Vendor12: break; 76 | case ID_DAP_Vendor13: break; 77 | case ID_DAP_Vendor14: break; 78 | case ID_DAP_Vendor15: break; 79 | case ID_DAP_Vendor16: break; 80 | case ID_DAP_Vendor17: break; 81 | case ID_DAP_Vendor18: break; 82 | case ID_DAP_Vendor19: break; 83 | case ID_DAP_Vendor20: break; 84 | case ID_DAP_Vendor21: break; 85 | case ID_DAP_Vendor22: break; 86 | case ID_DAP_Vendor23: break; 87 | case ID_DAP_Vendor24: break; 88 | case ID_DAP_Vendor25: break; 89 | case ID_DAP_Vendor26: break; 90 | case ID_DAP_Vendor27: break; 91 | case ID_DAP_Vendor28: break; 92 | case ID_DAP_Vendor29: break; 93 | case ID_DAP_Vendor30: break; 94 | case ID_DAP_Vendor31: break; 95 | } 96 | 97 | return (num); 98 | } 99 | 100 | ///@} 101 | -------------------------------------------------------------------------------- /src/probe_oen.pio: -------------------------------------------------------------------------------- 1 | ; SPDX-License-Identifier: MIT 2 | ; Copyright (c) 2023 Raspberry Pi Ltd 3 | 4 | ; Output-enable active-low variant of the SWD probe 5 | 6 | ; This program is very similar to the one in probe.pio. The only difference is 7 | ; that here write_cmd and turnaround_cmd are split into two separate routines, 8 | ; whose difference is OEn being high/low. 9 | 10 | ; SWDIO_OEn is pin 0, SWCLK pin 1, SWDIO (out) pin 2, SWDI (in) pin 3. 11 | ; Pin 0 and 1 are sideset pins 12 | 13 | .program probe 14 | .side_set 2 opt 15 | 16 | public turnaround_cmd: 17 | pull 18 | turnaround_bitloop: 19 | nop [1] side 0x1 20 | jmp x-- turnaround_bitloop [1] side 0x3 21 | jmp get_next_cmd 22 | 23 | public write_cmd: 24 | pull 25 | write_bitloop: 26 | out pins, 1 [1] side 0x0 ; Data is output by host on negedge 27 | jmp x-- write_bitloop [1] side 0x2 ; ...and captured by target on posedge 28 | ; Fall through to next command 29 | .wrap_target 30 | public get_next_cmd: 31 | pull side 0x1 ; SWCLK initially low, OEn disabled 32 | out x, 8 ; Get bit count 33 | out pindirs, 1 ; Set SWDIO direction 34 | out pc, 5 ; Go to command routine 35 | 36 | read_bitloop: 37 | nop ; Additional delay on taken loop branch 38 | public read_cmd: 39 | in pins, 1 [1] side 0x3 ; Data is captured by host on posedge 40 | jmp x-- read_bitloop side 0x1 41 | push 42 | .wrap ; Wrap to next command 43 | 44 | 45 | ; Implement probe_gpio_init() and probe_sm_init() methods here - set pins, offsets, sidesets etc 46 | % c-sdk { 47 | 48 | static inline void probe_gpio_init() 49 | { 50 | #if defined(PROBE_PIN_RESET) 51 | // Target reset pin: pull up, input to emulate open drain pin 52 | gpio_pull_up(PROBE_PIN_RESET); 53 | // gpio_init will leave the pin cleared and set as input 54 | gpio_init(PROBE_PIN_RESET); 55 | #endif 56 | // Funcsel pins 57 | pio_gpio_init(pio0, PROBE_PIN_SWDIOEN); 58 | pio_gpio_init(pio0, PROBE_PIN_SWCLK); 59 | pio_gpio_init(pio0, PROBE_PIN_SWDIO); 60 | 61 | // Make sure SWDIO has a pullup on it. Idle state is high 62 | gpio_pull_up(PROBE_PIN_SWDIO); 63 | gpio_pull_up(PROBE_PIN_SWDIOEN); 64 | } 65 | 66 | // DAP interface says all pins have to be High-Z when disabled 67 | static inline void probe_gpio_deinit() 68 | { 69 | #if defined(PROBE_PIN_RESET) 70 | gpio_deinit(PROBE_PIN_RESET); 71 | gpio_disable_pulls(PROBE_PIN_RESET); 72 | #endif 73 | gpio_deinit(PROBE_PIN_SWCLK); 74 | gpio_disable_pulls(PROBE_PIN_SWCLK); 75 | // Note for SWDIOEN - make sure the driver output enable is removed before removing drive - leave pull-up enabled 76 | gpio_deinit(PROBE_PIN_SWDIOEN); 77 | gpio_deinit(PROBE_PIN_SWDIO); 78 | gpio_disable_pulls(PROBE_PIN_SWDIO); 79 | } 80 | 81 | static inline void probe_sm_init(pio_sm_config* sm_config) { 82 | 83 | // Set SWDIOEN and SWCLK as sideset pins 84 | sm_config_set_sideset_pins(sm_config, PROBE_PIN_SWDIOEN); 85 | 86 | // Set SWDIO offset 87 | sm_config_set_out_pins(sm_config, PROBE_PIN_SWDIO, 1); 88 | sm_config_set_set_pins(sm_config, PROBE_PIN_SWDIO, 1); 89 | sm_config_set_in_pins(sm_config, PROBE_PIN_SWDI); 90 | 91 | // Set SWDIOEN, SWD and SWDIO pins as output to start. This will be set in the sm 92 | pio_sm_set_consecutive_pindirs(pio0, PROBE_SM, PROBE_PIN_OFFSET, 3, true); 93 | 94 | // shift output right, autopull off, autopull threshold 95 | sm_config_set_out_shift(sm_config, true, false, 0); 96 | // shift input right as swd data is lsb first, autopush off 97 | sm_config_set_in_shift(sm_config, true, false, 0); 98 | } 99 | 100 | %} 101 | -------------------------------------------------------------------------------- /FreeRTOS_Kernel_import.cmake: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-3-clause 2 | # This is a copy of /portable/ThirdParty/GCC/RP2040/FREERTOS_KERNEL_import.cmake 3 | 4 | # This can be dropped into an external project to help locate the FreeRTOS kernel 5 | # It should be include()ed prior to project(). Alternatively this file may 6 | # or the CMakeLists.txt in this directory may be included or added via add_subdirectory 7 | # respectively. 8 | 9 | if (DEFINED ENV{FREERTOS_KERNEL_PATH} AND (NOT FREERTOS_KERNEL_PATH)) 10 | set(FREERTOS_KERNEL_PATH $ENV{FREERTOS_KERNEL_PATH}) 11 | message("Using FREERTOS_KERNEL_PATH from environment ('${FREERTOS_KERNEL_PATH}')") 12 | endif () 13 | 14 | # first pass we look in old tree; second pass we look in new tree 15 | foreach(SEARCH_PASS RANGE 0 1) 16 | if (SEARCH_PASS) 17 | # ports may be moving to submodule in the future 18 | set(FREERTOS_KERNEL_RP2040_RELATIVE_PATH "portable/ThirdParty/Community-Supported-Ports/GCC") 19 | set(FREERTOS_KERNEL_RP2040_BACK_PATH "../../../../..") 20 | else() 21 | set(FREERTOS_KERNEL_RP2040_RELATIVE_PATH "portable/ThirdParty/GCC") 22 | set(FREERTOS_KERNEL_RP2040_BACK_PATH "../../../..") 23 | endif() 24 | 25 | if(PICO_PLATFORM STREQUAL "rp2040") 26 | set(FREERTOS_KERNEL_RP2040_RELATIVE_PATH "${FREERTOS_KERNEL_RP2040_RELATIVE_PATH}/RP2040") 27 | else() 28 | if (PICO_PLATFORM STREQUAL "rp2350-riscv") 29 | set(FREERTOS_KERNEL_RP2040_RELATIVE_PATH "${FREERTOS_KERNEL_RP2040_RELATIVE_PATH}/RP2350_RISC-V") 30 | else() 31 | set(FREERTOS_KERNEL_RP2040_RELATIVE_PATH "${FREERTOS_KERNEL_RP2040_RELATIVE_PATH}/RP2350_ARM_NTZ") 32 | endif() 33 | endif() 34 | 35 | if (NOT FREERTOS_KERNEL_PATH) 36 | # check if we are inside the FreeRTOS kernel tree (i.e. this file has been included directly) 37 | get_filename_component(_ACTUAL_PATH ${CMAKE_CURRENT_LIST_DIR} REALPATH) 38 | get_filename_component(_POSSIBLE_PATH ${CMAKE_CURRENT_LIST_DIR}/${FREERTOS_KERNEL_RP2040_BACK_PATH}/${FREERTOS_KERNEL_RP2040_RELATIVE_PATH} REALPATH) 39 | if (_ACTUAL_PATH STREQUAL _POSSIBLE_PATH) 40 | get_filename_component(FREERTOS_KERNEL_PATH ${CMAKE_CURRENT_LIST_DIR}/${FREERTOS_KERNEL_RP2040_BACK_PATH} REALPATH) 41 | endif() 42 | if (_ACTUAL_PATH STREQUAL _POSSIBLE_PATH) 43 | get_filename_component(FREERTOS_KERNEL_PATH ${CMAKE_CURRENT_LIST_DIR}/${FREERTOS_KERNEL_RP2040_BACK_PATH} REALPATH) 44 | message("Setting FREERTOS_KERNEL_PATH to ${FREERTOS_KERNEL_PATH} based on location of FreeRTOS-Kernel-import.cmake") 45 | break() 46 | elseif (PICO_SDK_PATH AND EXISTS "${PICO_SDK_PATH}/../FreeRTOS-Kernel") 47 | set(FREERTOS_KERNEL_PATH ${PICO_SDK_PATH}/../FreeRTOS-Kernel) 48 | message("Defaulting FREERTOS_KERNEL_PATH as sibling of PICO_SDK_PATH: ${FREERTOS_KERNEL_PATH}") 49 | break() 50 | endif() 51 | endif () 52 | 53 | if (NOT FREERTOS_KERNEL_PATH) 54 | foreach(POSSIBLE_SUFFIX Source FreeRTOS-Kernel FreeRTOS/Source) 55 | # check if FreeRTOS-Kernel exists under directory that included us 56 | set(SEARCH_ROOT ${CMAKE_CURRENT_SOURCE_DIR}) 57 | get_filename_component(_POSSIBLE_PATH ${SEARCH_ROOT}/${POSSIBLE_SUFFIX} REALPATH) 58 | if (EXISTS ${_POSSIBLE_PATH}/${FREERTOS_KERNEL_RP2040_RELATIVE_PATH}/CMakeLists.txt) 59 | get_filename_component(FREERTOS_KERNEL_PATH ${_POSSIBLE_PATH} REALPATH) 60 | message("Setting FREERTOS_KERNEL_PATH to '${FREERTOS_KERNEL_PATH}' found relative to enclosing project") 61 | break() 62 | endif() 63 | endforeach() 64 | if (FREERTOS_KERNEL_PATH) 65 | break() 66 | endif() 67 | endif() 68 | 69 | # user must have specified 70 | if (FREERTOS_KERNEL_PATH) 71 | if (EXISTS "${FREERTOS_KERNEL_PATH}/${FREERTOS_KERNEL_RP2040_RELATIVE_PATH}") 72 | break() 73 | endif() 74 | endif() 75 | endforeach () 76 | 77 | if (NOT FREERTOS_KERNEL_PATH) 78 | message(FATAL_ERROR "FreeRTOS location was not specified. Please set FREERTOS_KERNEL_PATH.") 79 | endif() 80 | 81 | set(FREERTOS_KERNEL_PATH "${FREERTOS_KERNEL_PATH}" CACHE PATH "Path to the FreeRTOS Kernel") 82 | 83 | get_filename_component(FREERTOS_KERNEL_PATH "${FREERTOS_KERNEL_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}") 84 | if (NOT EXISTS ${FREERTOS_KERNEL_PATH}) 85 | message(FATAL_ERROR "Directory '${FREERTOS_KERNEL_PATH}' not found") 86 | endif() 87 | if (NOT EXISTS ${FREERTOS_KERNEL_PATH}/${FREERTOS_KERNEL_RP2040_RELATIVE_PATH}/CMakeLists.txt) 88 | message(FATAL_ERROR "Directory '${FREERTOS_KERNEL_PATH}' does not contain a '${PICO_PLATFORM}' port here: ${FREERTOS_KERNEL_RP2040_RELATIVE_PATH}") 89 | endif() 90 | set(FREERTOS_KERNEL_PATH ${FREERTOS_KERNEL_PATH} CACHE PATH "Path to the FreeRTOS_KERNEL" FORCE) 91 | 92 | add_subdirectory(${FREERTOS_KERNEL_PATH}/${FREERTOS_KERNEL_RP2040_RELATIVE_PATH} FREERTOS_KERNEL) 93 | -------------------------------------------------------------------------------- /src/probe.pio: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2021-2023 Raspberry Pi (Trading) Ltd. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | * 24 | */ 25 | 26 | // Every TX FIFO entry is either a command, or up to 32 bits of data. 27 | // Command format: 28 | // 29 | // | 13:9 | 8 | 7:0 | 30 | // | Cmd | Dir | Count | 31 | // 32 | // Count is the number of bits to be transferred by this command, minus 1. 33 | // Dir is the output enable for the SWDIO pin. 34 | // Cmd is the address of the write_cmd, read_cmd or get_next_cmd label. 35 | // 36 | // write_cmd expects a FIFO data entry, but read_cmd does not. 37 | // 38 | // read_cmd pushes data to the FIFO, but write_cmd does not. (The lack of RX 39 | // garbage on writes allows the interface code to return early after pushing a 40 | // write command, as there is no need in general to poll for a command's 41 | // completion as long as all commands are executed in order.) 42 | // 43 | // The SWCLK period is 4 PIO SM execution cycles. 44 | 45 | .program probe 46 | .side_set 1 opt 47 | 48 | public write_cmd: 49 | public turnaround_cmd: ; Alias of write, used for probe_oen.pio 50 | pull 51 | write_bitloop: 52 | out pins, 1 [1] side 0x0 ; Data is output by host on negedge 53 | jmp x-- write_bitloop [1] side 0x1 ; ...and captured by target on posedge 54 | ; Fall through to next command 55 | .wrap_target 56 | public get_next_cmd: 57 | pull side 0x0 ; SWCLK is initially low 58 | out x, 8 ; Get bit count 59 | out pindirs, 1 ; Set SWDIO direction 60 | out pc, 5 ; Go to command routine 61 | 62 | read_bitloop: 63 | nop ; Additional delay on taken loop branch 64 | public read_cmd: 65 | in pins, 1 [1] side 0x1 ; Data is captured by host on posedge 66 | jmp x-- read_bitloop side 0x0 67 | push 68 | .wrap ; Wrap to next command 69 | 70 | 71 | ; Implement probe_gpio_init() and probe_sm_init() methods here - set pins, offsets, sidesets etc 72 | % c-sdk { 73 | 74 | static inline void probe_gpio_init() 75 | { 76 | #if defined(PROBE_PIN_RESET) 77 | // Target reset pin: pull up, input to emulate open drain pin 78 | gpio_pull_up(PROBE_PIN_RESET); 79 | // gpio_init will leave the pin cleared and set as input 80 | gpio_init(PROBE_PIN_RESET); 81 | #endif 82 | // Funcsel pins 83 | pio_gpio_init(pio0, PROBE_PIN_SWCLK); 84 | pio_gpio_init(pio0, PROBE_PIN_SWDIO); 85 | // Make sure SWDIO has a pullup on it. Idle state is high 86 | gpio_pull_up(PROBE_PIN_SWDIO); 87 | } 88 | 89 | // DAP interface says all pins have to be High-Z when disabled 90 | static inline void probe_gpio_deinit() 91 | { 92 | #if defined(PROBE_PIN_RESET) 93 | gpio_deinit(PROBE_PIN_RESET); 94 | gpio_disable_pulls(PROBE_PIN_RESET); 95 | #endif 96 | gpio_deinit(PROBE_PIN_SWCLK); 97 | gpio_disable_pulls(PROBE_PIN_SWCLK); 98 | gpio_deinit(PROBE_PIN_SWDIO); 99 | gpio_disable_pulls(PROBE_PIN_SWDIO); 100 | } 101 | 102 | static inline void probe_sm_init(pio_sm_config* sm_config) { 103 | 104 | // Set SWCLK as a sideset pin 105 | sm_config_set_sideset_pins(sm_config, PROBE_PIN_SWCLK); 106 | 107 | // Set SWDIO offset 108 | sm_config_set_out_pins(sm_config, PROBE_PIN_SWDIO, 1); 109 | sm_config_set_set_pins(sm_config, PROBE_PIN_SWDIO, 1); 110 | #ifdef PROBE_IO_SWDI 111 | sm_config_set_in_pins(sm_config, PROBE_PIN_SWDI); 112 | #else 113 | sm_config_set_in_pins(sm_config, PROBE_PIN_SWDIO); 114 | #endif 115 | 116 | 117 | // Set SWD and SWDIO pins as output to start. This will be set in the sm 118 | pio_sm_set_consecutive_pindirs(pio0, PROBE_SM, PROBE_PIN_OFFSET, 2, true); 119 | 120 | // shift output right, autopull off, autopull threshold 121 | sm_config_set_out_shift(sm_config, true, false, 0); 122 | // shift input right as swd data is lsb first, autopush off 123 | sm_config_set_in_shift(sm_config, true, false, 0); 124 | } 125 | 126 | %} 127 | -------------------------------------------------------------------------------- /src/probe.c: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2021 Raspberry Pi (Trading) Ltd. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | * 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | #include 31 | #include 32 | 33 | #include "probe_config.h" 34 | #include "probe.h" 35 | #include "tusb.h" 36 | 37 | #define DIV_ROUND_UP(m, n) (((m) + (n) - 1) / (n)) 38 | 39 | // Only want to set / clear one gpio per event so go up in powers of 2 40 | enum _dbg_pins { 41 | DBG_PIN_WRITE = 1, 42 | DBG_PIN_WRITE_WAIT = 2, 43 | DBG_PIN_READ = 4, 44 | DBG_PIN_PKT = 8, 45 | }; 46 | 47 | CU_REGISTER_DEBUG_PINS(probe_timing) 48 | 49 | // Uncomment to enable debug 50 | //CU_SELECT_DEBUG_PINS(probe_timing) 51 | 52 | #define PROBE_BUF_SIZE 8192 53 | struct _probe { 54 | // PIO offset 55 | uint offset; 56 | uint initted; 57 | }; 58 | 59 | static struct _probe probe; 60 | 61 | void probe_set_swclk_freq(uint freq_khz) { 62 | uint clk_sys_freq_khz = clock_get_hz(clk_sys) / 1000; 63 | probe_info("Set swclk freq %dKHz sysclk %dkHz\n", freq_khz, clk_sys_freq_khz); 64 | // Round up (otherwise fast swclks get faster) 65 | uint32_t divider = (((clk_sys_freq_khz + freq_khz - 1)/ freq_khz) + 3) / 4; 66 | if (divider == 0) 67 | divider = 1; 68 | if (divider > 65535) 69 | divider = 65535; 70 | 71 | pio_sm_set_clkdiv_int_frac(pio0, PROBE_SM, divider, 0); 72 | } 73 | 74 | void probe_assert_reset(bool state) 75 | { 76 | #if defined(PROBE_PIN_RESET) 77 | /* Change the direction to out to drive pin to 0 or to in to emulate open drain */ 78 | gpio_set_dir(PROBE_PIN_RESET, state == 0 ? GPIO_OUT : GPIO_IN); 79 | #endif 80 | } 81 | 82 | int probe_reset_level(void) 83 | { 84 | #if defined(PROBE_PIN_RESET) 85 | return gpio_get(PROBE_PIN_RESET); 86 | #else 87 | return 0; 88 | #endif 89 | } 90 | 91 | typedef enum probe_pio_command { 92 | CMD_WRITE = 0, 93 | CMD_SKIP, 94 | CMD_TURNAROUND, 95 | CMD_READ 96 | } probe_pio_command_t; 97 | 98 | static inline uint32_t fmt_probe_command(uint bit_count, bool out_en, probe_pio_command_t cmd) { 99 | uint cmd_addr = 100 | cmd == CMD_WRITE ? probe.offset + probe_offset_write_cmd : 101 | cmd == CMD_SKIP ? probe.offset + probe_offset_get_next_cmd : 102 | cmd == CMD_TURNAROUND ? probe.offset + probe_offset_turnaround_cmd : 103 | probe.offset + probe_offset_read_cmd; 104 | return ((bit_count - 1) & 0xff) | ((uint)out_en << 8) | (cmd_addr << 9); 105 | } 106 | 107 | void probe_write_bits(uint bit_count, uint32_t data_byte) { 108 | DEBUG_PINS_SET(probe_timing, DBG_PIN_WRITE); 109 | pio_sm_put_blocking(pio0, PROBE_SM, fmt_probe_command(bit_count, true, CMD_WRITE)); 110 | pio_sm_put_blocking(pio0, PROBE_SM, data_byte); 111 | probe_dump("Write %d bits 0x%x\n", bit_count, data_byte); 112 | // Return immediately so we can cue up the next command whilst this one runs 113 | DEBUG_PINS_CLR(probe_timing, DBG_PIN_WRITE); 114 | } 115 | 116 | void probe_hiz_clocks(uint bit_count) { 117 | pio_sm_put_blocking(pio0, PROBE_SM, fmt_probe_command(bit_count, false, CMD_TURNAROUND)); 118 | pio_sm_put_blocking(pio0, PROBE_SM, 0); 119 | } 120 | 121 | uint32_t probe_read_bits(uint bit_count) { 122 | DEBUG_PINS_SET(probe_timing, DBG_PIN_READ); 123 | pio_sm_put_blocking(pio0, PROBE_SM, fmt_probe_command(bit_count, false, CMD_READ)); 124 | uint32_t data = pio_sm_get_blocking(pio0, PROBE_SM); 125 | uint32_t data_shifted = data; 126 | if (bit_count < 32) { 127 | data_shifted = data >> (32 - bit_count); 128 | } 129 | 130 | probe_dump("Read %d bits 0x%x (shifted 0x%x)\n", bit_count, data, data_shifted); 131 | DEBUG_PINS_CLR(probe_timing, DBG_PIN_READ); 132 | return data_shifted; 133 | } 134 | 135 | static void probe_wait_idle() { 136 | pio0->fdebug = 1u << (PIO_FDEBUG_TXSTALL_LSB + PROBE_SM); 137 | while (!(pio0->fdebug & (1u << (PIO_FDEBUG_TXSTALL_LSB + PROBE_SM)))) 138 | ; 139 | } 140 | 141 | void probe_read_mode(void) { 142 | pio_sm_put_blocking(pio0, PROBE_SM, fmt_probe_command(0, false, CMD_SKIP)); 143 | probe_wait_idle(); 144 | } 145 | 146 | void probe_write_mode(void) { 147 | pio_sm_put_blocking(pio0, PROBE_SM, fmt_probe_command(0, true, CMD_SKIP)); 148 | probe_wait_idle(); 149 | } 150 | 151 | void probe_init() { 152 | if (!probe.initted) { 153 | probe_gpio_init(); 154 | uint offset = pio_add_program(pio0, &probe_program); 155 | probe.offset = offset; 156 | 157 | pio_sm_config sm_config = probe_program_get_default_config(offset); 158 | probe_sm_init(&sm_config); 159 | pio_sm_init(pio0, PROBE_SM, offset, &sm_config); 160 | 161 | // Set up divisor 162 | probe_set_swclk_freq(1000); 163 | 164 | // Jump SM to command dispatch routine, and enable it 165 | pio_sm_exec(pio0, PROBE_SM, offset + probe_offset_get_next_cmd); 166 | pio_sm_set_enabled(pio0, PROBE_SM, 1); 167 | probe.initted = 1; 168 | } 169 | } 170 | 171 | void probe_deinit(void) 172 | { 173 | if (probe.initted) { 174 | probe_read_mode(); 175 | pio_sm_set_enabled(pio0, PROBE_SM, 0); 176 | pio_remove_program(pio0, &probe_program, probe.offset); 177 | 178 | probe_assert_reset(1); // de-assert nRESET 179 | probe_gpio_deinit(); 180 | probe.initted = 0; 181 | } 182 | } 183 | -------------------------------------------------------------------------------- /src/FreeRTOSConfig.h: -------------------------------------------------------------------------------- 1 | /* 2 | * FreeRTOS V202107.00 3 | * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | * this software and associated documentation files (the "Software"), to deal in 7 | * the Software without restriction, including without limitation the rights to 8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | * the Software, and to permit persons to whom the Software is furnished to do so, 10 | * subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in all 13 | * copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | * 22 | * http://www.FreeRTOS.org 23 | * http://aws.amazon.com/freertos 24 | * 25 | * 1 tab == 4 spaces! 26 | */ 27 | 28 | #ifndef FREERTOS_CONFIG_H 29 | #define FREERTOS_CONFIG_H 30 | 31 | /*----------------------------------------------------------- 32 | * Application specific definitions. 33 | * 34 | * These definitions should be adjusted for your particular hardware and 35 | * application requirements. 36 | * 37 | * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE 38 | * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. 39 | * 40 | * See http://www.freertos.org/a00110.html 41 | *----------------------------------------------------------*/ 42 | 43 | /* Scheduler Related */ 44 | #define configUSE_PREEMPTION 1 45 | #define configUSE_TICKLESS_IDLE 0 46 | #define configUSE_IDLE_HOOK 0 47 | #define configUSE_TICK_HOOK 1 48 | #define configTICK_RATE_HZ ( ( TickType_t ) 20000 ) 49 | #define configMAX_PRIORITIES 32 50 | #define configMINIMAL_STACK_SIZE ( configSTACK_DEPTH_TYPE ) 256 51 | #define configUSE_16_BIT_TICKS 0 52 | 53 | #define configIDLE_SHOULD_YIELD 1 54 | 55 | /* Synchronization Related */ 56 | #define configUSE_MUTEXES 1 57 | #define configUSE_RECURSIVE_MUTEXES 1 58 | #define configUSE_APPLICATION_TASK_TAG 0 59 | #define configUSE_COUNTING_SEMAPHORES 1 60 | #define configQUEUE_REGISTRY_SIZE 8 61 | #define configUSE_QUEUE_SETS 1 62 | #define configUSE_TIME_SLICING 1 63 | #define configUSE_NEWLIB_REENTRANT 0 64 | #define configENABLE_BACKWARD_COMPATIBILITY 0 65 | #define configNUM_THREAD_LOCAL_STORAGE_POINTERS 5 66 | 67 | /* System */ 68 | #define configSTACK_DEPTH_TYPE uint32_t 69 | #define configMESSAGE_BUFFER_LENGTH_TYPE size_t 70 | 71 | /* Memory allocation related definitions. */ 72 | #define configSUPPORT_STATIC_ALLOCATION 0 73 | #define configSUPPORT_DYNAMIC_ALLOCATION 1 74 | #define configTOTAL_HEAP_SIZE (64*1024) 75 | #define configAPPLICATION_ALLOCATED_HEAP 0 76 | 77 | /* Hook function related definitions. */ 78 | #define configCHECK_FOR_STACK_OVERFLOW 2 79 | #define configUSE_MALLOC_FAILED_HOOK 1 80 | #define configUSE_DAEMON_TASK_STARTUP_HOOK 0 81 | 82 | /* Run time and task stats gathering related definitions. */ 83 | #define configGENERATE_RUN_TIME_STATS 0 84 | #define configUSE_TRACE_FACILITY 1 85 | #define configUSE_STATS_FORMATTING_FUNCTIONS 0 86 | 87 | /* Co-routine related definitions. */ 88 | #define configUSE_CO_ROUTINES 0 89 | #define configMAX_CO_ROUTINE_PRIORITIES 1 90 | 91 | /* Software timer related definitions. */ 92 | #define configUSE_TIMERS 1 93 | #define configTIMER_TASK_PRIORITY ( configMAX_PRIORITIES - 1 ) 94 | #define configTIMER_QUEUE_LENGTH 10 95 | #define configTIMER_TASK_STACK_DEPTH 1024 96 | 97 | /* Interrupt nesting behaviour configuration. */ 98 | /* 99 | #define configKERNEL_INTERRUPT_PRIORITY [dependent of processor] 100 | #define configMAX_SYSCALL_INTERRUPT_PRIORITY [dependent on processor and application] 101 | #define configMAX_API_CALL_INTERRUPT_PRIORITY [dependent on processor and application] 102 | */ 103 | 104 | /* SMP port only */ 105 | #define configNUMBER_OF_CORES 2 106 | #define configTICK_CORE 0 107 | #define configUSE_CORE_AFFINITY 1 108 | #define configRUN_MULTIPLE_PRIORITIES 1 109 | #define configUSE_PASSIVE_IDLE_HOOK 0 110 | 111 | /* RP2040 specific */ 112 | #define configSUPPORT_PICO_SYNC_INTEROP 1 113 | #define configSUPPORT_PICO_TIME_INTEROP 1 114 | 115 | /* RP2350 grows some features */ 116 | #define configENABLE_FPU 1 117 | #define configENABLE_MPU 0 118 | #define configENABLE_TRUSTZONE 0 119 | #define configRUN_FREERTOS_SECURE_ONLY 1 120 | #define configMAX_SYSCALL_INTERRUPT_PRIORITY 16 121 | 122 | #include 123 | /* Define to trap errors during development. */ 124 | #define configASSERT(x) assert(x) 125 | 126 | /* Set the following definitions to 1 to include the API function, or zero 127 | to exclude the API function. */ 128 | #define INCLUDE_vTaskPrioritySet 1 129 | #define INCLUDE_uxTaskPriorityGet 1 130 | #define INCLUDE_vTaskDelete 1 131 | #define INCLUDE_vTaskSuspend 1 132 | #define INCLUDE_vTaskDelayUntil 1 133 | #define INCLUDE_vTaskDelay 1 134 | #define INCLUDE_xTaskGetSchedulerState 1 135 | #define INCLUDE_xTaskGetCurrentTaskHandle 1 136 | #define INCLUDE_uxTaskGetStackHighWaterMark 1 137 | #define INCLUDE_xTaskGetIdleTaskHandle 1 138 | #define INCLUDE_eTaskGetState 1 139 | #define INCLUDE_xTimerPendFunctionCall 1 140 | #define INCLUDE_xTaskAbortDelay 1 141 | #define INCLUDE_xTaskGetHandle 1 142 | #define INCLUDE_xTaskResumeFromISR 1 143 | #define INCLUDE_xQueueGetMutexHolder 1 144 | 145 | /* A header file that defines trace macro can be included here. */ 146 | 147 | #endif /* FREERTOS_CONFIG_H */ 148 | 149 | -------------------------------------------------------------------------------- /src/sw_dp_pio.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013-2022 ARM Limited. All rights reserved. 3 | * Copyright (c) 2022 Raspberry Pi Ltd 4 | * 5 | * SPDX-License-Identifier: Apache-2.0 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the License); you may 8 | * not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an AS IS BASIS, WITHOUT 15 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | /* 21 | * This is a shim between the SW_DP functions and the PIO 22 | * implementation used for Debugprobe. Instead of calling bitbash functions, 23 | * hand off the bit sequences to a SM for asynchronous completion. 24 | */ 25 | 26 | #include 27 | 28 | #include "DAP_config.h" 29 | #include "DAP.h" 30 | #include "probe.h" 31 | 32 | /* Slight hack - we're not bitbashing so we need to set baudrate off the DAP's delay cycles. 33 | * Ideally we don't want calls to udiv everywhere... */ 34 | #define MAKE_KHZ(x) (CPU_CLOCK / (2000 * ((x) + 1))) 35 | volatile uint32_t cached_delay = 0; 36 | 37 | // Generate SWJ Sequence 38 | // count: sequence bit count 39 | // data: pointer to sequence bit data 40 | // return: none 41 | #if ((DAP_SWD != 0) || (DAP_JTAG != 0)) 42 | void SWJ_Sequence (uint32_t count, const uint8_t *data) { 43 | uint32_t bits; 44 | uint32_t n; 45 | 46 | if (DAP_Data.clock_delay != cached_delay) { 47 | probe_set_swclk_freq(MAKE_KHZ(DAP_Data.clock_delay)); 48 | cached_delay = DAP_Data.clock_delay; 49 | } 50 | probe_debug("SWJ sequence count = %d FDB=0x%2x\n", count, data[0]); 51 | n = count; 52 | while (n > 0) { 53 | if (n > 8) 54 | bits = 8; 55 | else 56 | bits = n; 57 | probe_write_bits(bits, *data++); 58 | n -= bits; 59 | } 60 | } 61 | #endif 62 | 63 | // Generate SWD Sequence 64 | // info: sequence information 65 | // swdo: pointer to SWDIO generated data 66 | // swdi: pointer to SWDIO captured data 67 | // return: none 68 | #if (DAP_SWD != 0) 69 | void SWD_Sequence (uint32_t info, const uint8_t *swdo, uint8_t *swdi) { 70 | uint32_t bits; 71 | uint32_t n; 72 | 73 | if (DAP_Data.clock_delay != cached_delay) { 74 | probe_set_swclk_freq(MAKE_KHZ(DAP_Data.clock_delay)); 75 | cached_delay = DAP_Data.clock_delay; 76 | } 77 | probe_debug("SWD sequence\n"); 78 | n = info & SWD_SEQUENCE_CLK; 79 | if (n == 0U) { 80 | n = 64U; 81 | } 82 | bits = n; 83 | if (info & SWD_SEQUENCE_DIN) { 84 | while (n > 0) { 85 | if (n > 8) 86 | bits = 8; 87 | else 88 | bits = n; 89 | *swdi++ = probe_read_bits(bits); 90 | n -= bits; 91 | } 92 | } else { 93 | while (n > 0) { 94 | if (n > 8) 95 | bits = 8; 96 | else 97 | bits = n; 98 | probe_write_bits(bits, *swdo++); 99 | n -= bits; 100 | } 101 | } 102 | } 103 | #endif 104 | 105 | #if (DAP_SWD != 0) 106 | // SWD Transfer I/O 107 | // request: A[3:2] RnW APnDP 108 | // data: DATA[31:0] 109 | // return: ACK[2:0] 110 | uint8_t SWD_Transfer (uint32_t request, uint32_t *data) { 111 | uint8_t prq = 0; 112 | uint8_t ack; 113 | uint8_t bit; 114 | uint32_t val = 0; 115 | uint32_t parity = 0; 116 | uint32_t n; 117 | 118 | if (DAP_Data.clock_delay != cached_delay) { 119 | probe_set_swclk_freq(MAKE_KHZ(DAP_Data.clock_delay)); 120 | cached_delay = DAP_Data.clock_delay; 121 | } 122 | probe_debug("SWD_transfer\n"); 123 | /* Generate the request packet */ 124 | prq |= (1 << 0); /* Start Bit */ 125 | for (n = 1; n < 5; n++) { 126 | bit = (request >> (n - 1)) & 0x1; 127 | prq |= bit << n; 128 | parity += bit; 129 | } 130 | prq |= (parity & 0x1) << 5; /* Parity Bit */ 131 | prq |= (0 << 6); /* Stop Bit */ 132 | prq |= (1 << 7); /* Park bit */ 133 | probe_write_bits(8, prq); 134 | 135 | /* Turnaround (ignore read bits) */ 136 | ack = probe_read_bits(DAP_Data.swd_conf.turnaround + 3); 137 | ack >>= DAP_Data.swd_conf.turnaround; 138 | 139 | if (ack == DAP_TRANSFER_OK) { 140 | /* Data transfer phase */ 141 | if (request & DAP_TRANSFER_RnW) { 142 | /* Read RDATA[0:31] - note probe_read shifts to LSBs */ 143 | val = probe_read_bits(32); 144 | bit = probe_read_bits(1); 145 | parity = __builtin_popcount(val); 146 | if ((parity ^ bit) & 1U) { 147 | /* Parity error */ 148 | ack = DAP_TRANSFER_ERROR; 149 | } 150 | if (data) 151 | *data = val; 152 | probe_debug("Read %02x ack %02x 0x%08x parity %01x\n", 153 | prq, ack, val, bit); 154 | /* Turnaround for line idle */ 155 | probe_hiz_clocks(DAP_Data.swd_conf.turnaround); 156 | } else { 157 | /* Turnaround for write */ 158 | probe_hiz_clocks(DAP_Data.swd_conf.turnaround); 159 | 160 | /* Write WDATA[0:31] */ 161 | val = *data; 162 | probe_write_bits(32, val); 163 | parity = __builtin_popcount(val); 164 | /* Write Parity Bit */ 165 | probe_write_bits(1, parity & 0x1); 166 | probe_debug("write %02x ack %02x 0x%08x parity %01x\n", 167 | prq, ack, val, parity); 168 | } 169 | /* Capture Timestamp */ 170 | if (request & DAP_TRANSFER_TIMESTAMP) { 171 | DAP_Data.timestamp = time_us_32(); 172 | } 173 | 174 | /* Idle cycles - drive 0 for N clocks */ 175 | if (DAP_Data.transfer.idle_cycles) { 176 | for (n = DAP_Data.transfer.idle_cycles; n; ) { 177 | if (n > 256) { 178 | probe_write_bits(256, 0); 179 | n -= 256; 180 | } else { 181 | probe_write_bits(n, 0); 182 | n -= n; 183 | } 184 | } 185 | } 186 | return ((uint8_t)ack); 187 | } 188 | 189 | if ((ack == DAP_TRANSFER_WAIT) || (ack == DAP_TRANSFER_FAULT)) { 190 | if (DAP_Data.swd_conf.data_phase && ((request & DAP_TRANSFER_RnW) != 0U)) { 191 | /* Dummy Read RDATA[0:31] + Parity */ 192 | probe_read_bits(33); 193 | } 194 | probe_hiz_clocks(DAP_Data.swd_conf.turnaround); 195 | if (DAP_Data.swd_conf.data_phase && ((request & DAP_TRANSFER_RnW) == 0U)) { 196 | /* Dummy Write WDATA[0:31] + Parity */ 197 | probe_write_bits(32, 0); 198 | probe_write_bits(1, 0); 199 | } 200 | return ((uint8_t)ack); 201 | } 202 | 203 | /* Protocol error */ 204 | n = DAP_Data.swd_conf.turnaround + 32U + 1U; 205 | /* Back off data phase */ 206 | probe_read_bits(n); 207 | return ((uint8_t)ack); 208 | } 209 | 210 | #endif /* (DAP_SWD != 0) */ 211 | -------------------------------------------------------------------------------- /CMSIS_DAP/CMSIS/DAP/Firmware/Validation/MDK5/Validation.uvoptx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1.0 5 | 6 |
### uVision Project, (C) Keil Software
7 | 8 | 9 | *.c 10 | *.s*; *.src; *.a* 11 | *.obj; *.o 12 | *.lib 13 | *.txt; *.h; *.inc 14 | *.plm 15 | *.cpp 16 | 0 17 | 18 | 19 | 20 | 0 21 | 0 22 | 23 | 24 | 25 | CMSIS_DAP 26 | 0x4 27 | ARM-ADS 28 | 29 | 12000000 30 | 31 | 1 32 | 1 33 | 0 34 | 1 35 | 0 36 | 37 | 38 | 1 39 | 65535 40 | 0 41 | 0 42 | 0 43 | 44 | 45 | 79 46 | 66 47 | 8 48 | .\Listings\ 49 | 50 | 51 | 1 52 | 1 53 | 1 54 | 0 55 | 1 56 | 1 57 | 0 58 | 1 59 | 0 60 | 0 61 | 0 62 | 0 63 | 64 | 65 | 1 66 | 1 67 | 1 68 | 1 69 | 1 70 | 1 71 | 1 72 | 0 73 | 0 74 | 75 | 76 | 1 77 | 0 78 | 1 79 | 80 | 7 81 | 82 | 0 83 | 1 84 | 1 85 | 0 86 | 1 87 | 1 88 | 1 89 | 1 90 | 1 91 | 1 92 | 0 93 | 1 94 | 1 95 | 1 96 | 0 97 | 1 98 | 1 99 | 1 100 | 1 101 | 0 102 | 0 103 | 1 104 | 0 105 | 0 106 | 3 107 | 108 | 109 | 110 | 111 | .\test.ini 112 | 113 | 114 | 115 | 116 | .\test.ini 117 | BIN\CMSIS_AGDI.dll 118 | 119 | 120 | 121 | 0 122 | ARMRTXEVENTFLAGS 123 | -L70 -Z18 -C0 -M0 -T1 124 | 125 | 126 | 0 127 | DLGDARM 128 | (1010=-1,-1,-1,-1,0)(1007=-1,-1,-1,-1,0)(1008=-1,-1,-1,-1,0)(1009=-1,-1,-1,-1,0)(1012=-1,-1,-1,-1,0) 129 | 130 | 131 | 0 132 | ARMDBGFLAGS 133 | -T0 134 | 135 | 136 | 0 137 | CMSIS_AGDI 138 | -X"" -O206 -S8 -C0 -P00 -TO18 -TC10000000 -TP20 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO7 -FD20000000 -FC1000 -FN0 139 | 140 | 141 | 0 142 | UL2CM3 143 | UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000) 144 | 145 | 146 | 147 | 148 | 0 149 | 150 | 151 | 0 152 | 1 153 | 1 154 | 0 155 | 0 156 | 0 157 | 0 158 | 1 159 | 0 160 | 0 161 | 0 162 | 0 163 | 0 164 | 0 165 | 0 166 | 0 167 | 0 168 | 0 169 | 0 170 | 0 171 | 0 172 | 0 173 | 0 174 | 0 175 | 176 | 177 | 178 | 0 179 | 0 180 | 0 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | Source Code 194 | 1 195 | 0 196 | 0 197 | 0 198 | 199 | 1 200 | 1 201 | 1 202 | 0 203 | 0 204 | 0 205 | .\test.c 206 | test.c 207 | 0 208 | 0 209 | 210 | 211 | 212 | 213 | Documentation 214 | 1 215 | 0 216 | 0 217 | 0 218 | 219 | 2 220 | 2 221 | 5 222 | 0 223 | 0 224 | 0 225 | .\readme.txt 226 | readme.txt 227 | 0 228 | 0 229 | 230 | 231 | 232 | 233 | ::CMSIS 234 | 0 235 | 0 236 | 0 237 | 1 238 | 239 | 240 | 241 | ::Device 242 | 1 243 | 0 244 | 0 245 | 1 246 | 247 | 248 |
249 | -------------------------------------------------------------------------------- /src/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2021 Raspberry Pi (Trading) Ltd. 5 | * Copyright (c) 2021 Peter Lawrence 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | * 25 | */ 26 | 27 | #include "FreeRTOS.h" 28 | #include "task.h" 29 | 30 | #include 31 | #include 32 | #include 33 | 34 | #if PICO_SDK_VERSION_MAJOR >= 2 35 | #include "bsp/board_api.h" 36 | #else 37 | #include "bsp/board.h" 38 | #endif 39 | #include "tusb.h" 40 | 41 | #include "probe_config.h" 42 | #include "probe.h" 43 | #include "cdc_uart.h" 44 | #include "autobaud.h" 45 | #include "get_serial.h" 46 | #include "tusb_edpt_handler.h" 47 | #include "DAP.h" 48 | #include "hardware/structs/usb.h" 49 | 50 | // UART0 for debugprobe debug 51 | // UART1 for debugprobe to target device 52 | 53 | static uint8_t TxDataBuffer[CFG_TUD_HID_EP_BUFSIZE]; 54 | static uint8_t RxDataBuffer[CFG_TUD_HID_EP_BUFSIZE]; 55 | 56 | #define THREADED 1 57 | 58 | #define UART_TASK_PRIO (tskIDLE_PRIORITY + 3) 59 | #define TUD_TASK_PRIO (tskIDLE_PRIORITY + 2) 60 | #define DAP_TASK_PRIO (tskIDLE_PRIORITY + 1) 61 | 62 | #define AUTOBAUD_TASK_PRIO (tskIDLE_PRIORITY + 1) 63 | 64 | TaskHandle_t dap_taskhandle, tud_taskhandle, mon_taskhandle; 65 | 66 | static int was_configured; 67 | 68 | void dev_mon(void *ptr) 69 | { 70 | uint32_t sof[3]; 71 | int i = 0; 72 | TickType_t wake; 73 | wake = xTaskGetTickCount(); 74 | do { 75 | /* ~5 SOF events per tick */ 76 | xTaskDelayUntil(&wake, 100); 77 | if (tud_connected() && !tud_suspended()) { 78 | sof[i++] = usb_hw->sof_rd & USB_SOF_RD_BITS; 79 | i = i % 3; 80 | } else { 81 | for (i = 0; i < 3; i++) 82 | sof[i] = 0; 83 | } 84 | if ((sof[0] | sof[1] | sof[2]) != 0) { 85 | if ((sof[0] == sof[1]) && (sof[1] == sof[2])) { 86 | probe_info("Watchdog timeout! Resetting USBD\n"); 87 | /* uh oh, signal disconnect (implicitly resets the controller) */ 88 | tud_deinit(0); 89 | /* Make sure the port got the message */ 90 | xTaskDelayUntil(&wake, 1); 91 | tud_init(0); 92 | } 93 | } 94 | } while (1); 95 | } 96 | 97 | void usb_thread(void *ptr) 98 | { 99 | #ifdef PROBE_USB_CONNECTED_LED 100 | gpio_init(PROBE_USB_CONNECTED_LED); 101 | gpio_set_dir(PROBE_USB_CONNECTED_LED, GPIO_OUT); 102 | #endif 103 | TickType_t wake; 104 | wake = xTaskGetTickCount(); 105 | do { 106 | tud_task(); 107 | #ifdef PROBE_USB_CONNECTED_LED 108 | if (!gpio_get(PROBE_USB_CONNECTED_LED) && tud_ready()) 109 | gpio_put(PROBE_USB_CONNECTED_LED, 1); 110 | else 111 | gpio_put(PROBE_USB_CONNECTED_LED, 0); 112 | #endif 113 | // If suspended or disconnected, delay for 1ms (20 ticks) 114 | if (tud_suspended() || !tud_connected()) 115 | xTaskDelayUntil(&wake, 20); 116 | // Go to sleep for up to a tick if nothing to do 117 | else if (!tud_task_event_ready()) 118 | xTaskDelayUntil(&wake, 1); 119 | } while (1); 120 | } 121 | 122 | // Workaround API change in 0.13 123 | #if (TUSB_VERSION_MAJOR == 0) && (TUSB_VERSION_MINOR <= 12) 124 | #define tud_vendor_flush(x) ((void)0) 125 | #endif 126 | 127 | int main(void) { 128 | // Declare pins in binary information 129 | bi_decl_config(); 130 | 131 | board_init(); 132 | usb_serial_init(); 133 | cdc_uart_init(); 134 | tusb_init(); 135 | stdio_uart_init(); 136 | 137 | DAP_Setup(); 138 | 139 | probe_info("Welcome to debugprobe!\n"); 140 | 141 | if (THREADED) { 142 | xTaskCreate(usb_thread, "TUD", configMINIMAL_STACK_SIZE, NULL, TUD_TASK_PRIO, &tud_taskhandle); 143 | #if PICO_RP2040 144 | xTaskCreate(dev_mon, "WDOG", configMINIMAL_STACK_SIZE, NULL, TUD_TASK_PRIO, &mon_taskhandle); 145 | #endif 146 | vTaskStartScheduler(); 147 | } 148 | 149 | while (!THREADED) { 150 | tud_task(); 151 | cdc_task(); 152 | 153 | #if (PROBE_DEBUG_PROTOCOL == PROTO_DAP_V2) 154 | if (tud_vendor_available()) { 155 | uint32_t resp_len; 156 | tud_vendor_read(RxDataBuffer, sizeof(RxDataBuffer)); 157 | resp_len = DAP_ProcessCommand(RxDataBuffer, TxDataBuffer); 158 | tud_vendor_write(TxDataBuffer, resp_len); 159 | } 160 | #endif 161 | } 162 | 163 | return 0; 164 | } 165 | 166 | uint16_t tud_hid_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen) 167 | { 168 | // TODO not Implemented 169 | (void) itf; 170 | (void) report_id; 171 | (void) report_type; 172 | (void) buffer; 173 | (void) reqlen; 174 | 175 | return 0; 176 | } 177 | 178 | void tud_hid_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t const* RxDataBuffer, uint16_t bufsize) 179 | { 180 | uint32_t response_size = TU_MIN(CFG_TUD_HID_EP_BUFSIZE, bufsize); 181 | 182 | // This doesn't use multiple report and report ID 183 | (void) itf; 184 | (void) report_id; 185 | (void) report_type; 186 | 187 | DAP_ProcessCommand(RxDataBuffer, TxDataBuffer); 188 | 189 | tud_hid_report(0, TxDataBuffer, response_size); 190 | } 191 | 192 | #if (PROBE_DEBUG_PROTOCOL == PROTO_DAP_V2) 193 | extern uint8_t const desc_ms_os_20[]; 194 | 195 | bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) 196 | { 197 | // nothing to with DATA & ACK stage 198 | if (stage != CONTROL_STAGE_SETUP) return true; 199 | 200 | switch (request->bmRequestType_bit.type) 201 | { 202 | case TUSB_REQ_TYPE_VENDOR: 203 | switch (request->bRequest) 204 | { 205 | case 1: 206 | if ( request->wIndex == 7 ) 207 | { 208 | // Get Microsoft OS 2.0 compatible descriptor 209 | uint16_t total_len; 210 | memcpy(&total_len, desc_ms_os_20+8, 2); 211 | 212 | return tud_control_xfer(rhport, request, (void*) desc_ms_os_20, total_len); 213 | }else 214 | { 215 | return false; 216 | } 217 | 218 | default: break; 219 | } 220 | break; 221 | default: break; 222 | } 223 | 224 | // stall unknown request 225 | return false; 226 | } 227 | #endif 228 | 229 | void tud_suspend_cb(bool remote_wakeup_en) 230 | { 231 | probe_info("Suspended\n"); 232 | /* Were we actually configured? If not, threads don't exist */ 233 | if (was_configured) { 234 | vTaskSuspend(uart_taskhandle); 235 | vTaskSuspend(dap_taskhandle); 236 | if (autobaud_running) 237 | autobaud_wait_stop(); 238 | vTaskSuspend(autobaud_taskhandle); 239 | } 240 | /* slow down clk_sys for power saving ? */ 241 | } 242 | 243 | void tud_resume_cb(void) 244 | { 245 | probe_info("Resumed\n"); 246 | if (was_configured) { 247 | vTaskResume(uart_taskhandle); 248 | vTaskResume(dap_taskhandle); 249 | vTaskResume(autobaud_taskhandle); 250 | } 251 | } 252 | 253 | void tud_unmount_cb(void) 254 | { 255 | probe_info("Disconnected\n"); 256 | vTaskSuspend(uart_taskhandle); 257 | vTaskSuspend(dap_taskhandle); 258 | vTaskDelete(uart_taskhandle); 259 | vTaskDelete(dap_taskhandle); 260 | if (autobaud_running) 261 | autobaud_wait_stop(); 262 | vTaskSuspend(autobaud_taskhandle); 263 | vTaskDelete(autobaud_taskhandle); 264 | was_configured = 0; 265 | } 266 | 267 | void tud_mount_cb(void) 268 | { 269 | probe_info("Connected, Configured\n"); 270 | if (!was_configured) { 271 | /* UART needs to preempt USB as if we don't, characters get lost */ 272 | xTaskCreate(cdc_thread, "UART", configMINIMAL_STACK_SIZE, NULL, UART_TASK_PRIO, &uart_taskhandle); 273 | /* Lowest priority thread is debug - need to shuffle buffers before we can toggle swd... */ 274 | xTaskCreate(dap_thread, "DAP", configMINIMAL_STACK_SIZE, NULL, DAP_TASK_PRIO, &dap_taskhandle); 275 | /* Autobaud detection using PIO as a frequency counter */ 276 | xTaskCreate(autobaud_thread, "ABR", configMINIMAL_STACK_SIZE, NULL, AUTOBAUD_TASK_PRIO, &autobaud_taskhandle); 277 | vTaskCoreAffinitySet(autobaud_taskhandle, (1 << 1)); 278 | was_configured = 1; 279 | } 280 | } 281 | 282 | void vApplicationTickHook (void) 283 | { 284 | }; 285 | 286 | void vApplicationStackOverflowHook(TaskHandle_t Task, char *pcTaskName) 287 | { 288 | panic("stack overflow (not the helpful kind) for %s\n", *pcTaskName); 289 | } 290 | 291 | void vApplicationMallocFailedHook(void) 292 | { 293 | panic("Malloc Failed\n"); 294 | }; 295 | -------------------------------------------------------------------------------- /CMSIS_DAP/CMSIS/DAP/Firmware/Template/MDK5/USBD_User_HID_0.c: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------------ 2 | * MDK Middleware - Component ::USB:Device 3 | * Copyright (c) 2004-2017 ARM Germany GmbH. All rights reserved. 4 | *------------------------------------------------------------------------------ 5 | * Name: USBD_User_HID_0.c 6 | * Purpose: USB Device Human Interface Device class (HID) User module 7 | * Rev.: V6.2.3 8 | *----------------------------------------------------------------------------*/ 9 | /** 10 | * \addtogroup usbd_hidFunctions 11 | * 12 | * USBD_User_HID_0.c implements the application specific functionality of the 13 | * HID class and is used to receive and send data reports to the USB Host. 14 | * 15 | * The implementation must match the configuration file USBD_Config_HID_0.h. 16 | * The following values in USBD_Config_HID_0.h affect the user code: 17 | * 18 | * - 'Endpoint polling Interval' specifies the frequency of requests 19 | * initiated by USB Host for \ref USBD_HIDn_GetReport. 20 | * 21 | * - 'Number of Output Reports' configures the values for \em rid of 22 | * \ref USBD_HIDn_SetReport. 23 | * 24 | * - 'Number of Input Reports' configures the values for \em rid of 25 | * \ref USBD_HIDn_GetReport and \ref USBD_HID_GetReportTrigger. 26 | * 27 | * - 'Maximum Input Report Size' specifies the maximum value for: 28 | * - return of \ref USBD_HIDn_GetReport 29 | * - len of \ref USBD_HID_GetReportTrigger. 30 | * 31 | * - 'Maximum Output Report Size' specifies the maximum value for \em len 32 | * in \ref USBD_HIDn_SetReport for rtype=HID_REPORT_OUTPUT 33 | * 34 | * - 'Maximum Feature Report Size' specifies the maximum value for \em len 35 | * in \ref USBD_HIDn_SetReport for rtype=HID_REPORT_FEATURE 36 | * 37 | */ 38 | 39 | 40 | //! [code_USBD_User_HID] 41 | 42 | #include 43 | #include 44 | #include "cmsis_os2.h" 45 | #define osObjectsExternal 46 | #include "osObjects.h" 47 | #include "rl_usb.h" 48 | #include "RTE\USB\USBD_Config_HID_0.h" 49 | #include "DAP_config.h" 50 | #include "DAP.h" 51 | 52 | 53 | #if (USBD_HID0_OUT_REPORT_MAX_SZ != DAP_PACKET_SIZE) 54 | #error "USB HID0 Output Report Size must match DAP Packet Size" 55 | #endif 56 | #if (USBD_HID0_IN_REPORT_MAX_SZ != DAP_PACKET_SIZE) 57 | #error "USB HID Input Report Size must match DAP Packet Size" 58 | #endif 59 | 60 | static volatile uint16_t USB_RequestIndexI; // Request Index In 61 | static volatile uint16_t USB_RequestIndexO; // Request Index Out 62 | static volatile uint16_t USB_RequestCountI; // Request Count In 63 | static volatile uint16_t USB_RequestCountO; // Request Count Out 64 | 65 | static volatile uint16_t USB_ResponseIndexI; // Response Index In 66 | static volatile uint16_t USB_ResponseIndexO; // Response Index Out 67 | static volatile uint16_t USB_ResponseCountI; // Response Count In 68 | static volatile uint16_t USB_ResponseCountO; // Response Count Out 69 | static volatile uint8_t USB_ResponseIdle; // Response Idle Flag 70 | 71 | static uint8_t USB_Request [DAP_PACKET_COUNT][DAP_PACKET_SIZE]; // Request Buffer 72 | static uint8_t USB_Response[DAP_PACKET_COUNT][DAP_PACKET_SIZE]; // Response Buffer 73 | 74 | 75 | // Called during USBD_Initialize to initialize the USB HID class instance. 76 | void USBD_HID0_Initialize (void) { 77 | // Initialize variables 78 | USB_RequestIndexI = 0U; 79 | USB_RequestIndexO = 0U; 80 | USB_RequestCountI = 0U; 81 | USB_RequestCountO = 0U; 82 | USB_ResponseIndexI = 0U; 83 | USB_ResponseIndexO = 0U; 84 | USB_ResponseCountI = 0U; 85 | USB_ResponseCountO = 0U; 86 | USB_ResponseIdle = 1U; 87 | } 88 | 89 | 90 | // Called during USBD_Uninitialize to de-initialize the USB HID class instance. 91 | void USBD_HID0_Uninitialize (void) { 92 | } 93 | 94 | 95 | // \brief Prepare HID Report data to send. 96 | // \param[in] rtype report type: 97 | // - HID_REPORT_INPUT = input report requested 98 | // - HID_REPORT_FEATURE = feature report requested 99 | // \param[in] req request type: 100 | // - USBD_HID_REQ_EP_CTRL = control endpoint request 101 | // - USBD_HID_REQ_PERIOD_UPDATE = idle period expiration request 102 | // - USBD_HID_REQ_EP_INT = previously sent report on interrupt endpoint request 103 | // \param[in] rid report ID (0 if only one report exists). 104 | // \param[out] buf buffer containing report data to send. 105 | // \return number of report data bytes prepared to send or invalid report requested. 106 | // - value >= 0: number of report data bytes prepared to send 107 | // - value = -1: invalid report requested 108 | int32_t USBD_HID0_GetReport (uint8_t rtype, uint8_t req, uint8_t rid, uint8_t *buf) { 109 | (void)rid; 110 | 111 | switch (rtype) { 112 | case HID_REPORT_INPUT: 113 | switch (req) { 114 | case USBD_HID_REQ_EP_CTRL: // Explicit USB Host request via Control OUT Endpoint 115 | case USBD_HID_REQ_PERIOD_UPDATE: // Periodic USB Host request via Interrupt OUT Endpoint 116 | break; 117 | case USBD_HID_REQ_EP_INT: // Called after USBD_HID_GetReportTrigger to signal data obtained. 118 | if (USB_ResponseCountI != USB_ResponseCountO) { 119 | // Load data from response buffer to be sent back 120 | memcpy(buf, USB_Response[USB_ResponseIndexO], DAP_PACKET_SIZE); 121 | USB_ResponseIndexO++; 122 | if (USB_ResponseIndexO == DAP_PACKET_COUNT) { 123 | USB_ResponseIndexO = 0U; 124 | } 125 | USB_ResponseCountO++; 126 | return ((int32_t)DAP_PACKET_SIZE); 127 | } else { 128 | USB_ResponseIdle = 1U; 129 | } 130 | break; 131 | } 132 | break; 133 | case HID_REPORT_FEATURE: 134 | break; 135 | } 136 | return (0); 137 | } 138 | 139 | 140 | // \brief Process received HID Report data. 141 | // \param[in] rtype report type: 142 | // - HID_REPORT_OUTPUT = output report received 143 | // - HID_REPORT_FEATURE = feature report received 144 | // \param[in] req request type: 145 | // - USBD_HID_REQ_EP_CTRL = report received on control endpoint 146 | // - USBD_HID_REQ_EP_INT = report received on interrupt endpoint 147 | // \param[in] rid report ID (0 if only one report exists). 148 | // \param[in] buf buffer that receives report data. 149 | // \param[in] len length of received report data. 150 | // \return true received report data processed. 151 | // \return false received report data not processed or request not supported. 152 | bool USBD_HID0_SetReport (uint8_t rtype, uint8_t req, uint8_t rid, const uint8_t *buf, int32_t len) { 153 | (void)req; 154 | (void)rid; 155 | 156 | switch (rtype) { 157 | case HID_REPORT_OUTPUT: 158 | if (len == 0) { 159 | break; 160 | } 161 | if (buf[0] == ID_DAP_TransferAbort) { 162 | DAP_TransferAbort = 1U; 163 | break; 164 | } 165 | if ((uint16_t)(USB_RequestCountI - USB_RequestCountO) == DAP_PACKET_COUNT) { 166 | osThreadFlagsSet(DAP_ThreadId, 0x80U); 167 | break; // Discard packet when buffer is full 168 | } 169 | // Store received data into request buffer 170 | memcpy(USB_Request[USB_RequestIndexI], buf, (uint32_t)len); 171 | USB_RequestIndexI++; 172 | if (USB_RequestIndexI == DAP_PACKET_COUNT) { 173 | USB_RequestIndexI = 0U; 174 | } 175 | USB_RequestCountI++; 176 | osThreadFlagsSet(DAP_ThreadId, 0x01U); 177 | break; 178 | case HID_REPORT_FEATURE: 179 | break; 180 | } 181 | return true; 182 | } 183 | 184 | 185 | // DAP Thread. 186 | __NO_RETURN void DAP_Thread (void *argument) { 187 | uint32_t flags; 188 | uint32_t n; 189 | (void) argument; 190 | 191 | for (;;) { 192 | osThreadFlagsWait(0x81U, osFlagsWaitAny, osWaitForever); 193 | 194 | // Process pending requests 195 | while (USB_RequestCountI != USB_RequestCountO) { 196 | 197 | // Handle Queue Commands 198 | n = USB_RequestIndexO; 199 | while (USB_Request[n][0] == ID_DAP_QueueCommands) { 200 | USB_Request[n][0] = ID_DAP_ExecuteCommands; 201 | n++; 202 | if (n == DAP_PACKET_COUNT) { 203 | n = 0U; 204 | } 205 | if (n == USB_RequestIndexI) { 206 | flags = osThreadFlagsWait(0x81U, osFlagsWaitAny, osWaitForever); 207 | if (flags & 0x80U) { 208 | break; 209 | } 210 | } 211 | } 212 | 213 | // Execute DAP Command (process request and prepare response) 214 | DAP_ExecuteCommand(USB_Request[USB_RequestIndexO], USB_Response[USB_ResponseIndexI]); 215 | 216 | // Update Request Index and Count 217 | USB_RequestIndexO++; 218 | if (USB_RequestIndexO == DAP_PACKET_COUNT) { 219 | USB_RequestIndexO = 0U; 220 | } 221 | USB_RequestCountO++; 222 | 223 | // Update Response Index and Count 224 | USB_ResponseIndexI++; 225 | if (USB_ResponseIndexI == DAP_PACKET_COUNT) { 226 | USB_ResponseIndexI = 0U; 227 | } 228 | USB_ResponseCountI++; 229 | 230 | if (USB_ResponseIdle) { 231 | if (USB_ResponseCountI != USB_ResponseCountO) { 232 | // Load data from response buffer to be sent back 233 | n = USB_ResponseIndexO++; 234 | if (USB_ResponseIndexO == DAP_PACKET_COUNT) { 235 | USB_ResponseIndexO = 0U; 236 | } 237 | USB_ResponseCountO++; 238 | USB_ResponseIdle = 0U; 239 | USBD_HID_GetReportTrigger(0U, 0U, USB_Response[n], DAP_PACKET_SIZE); 240 | } 241 | } 242 | } 243 | } 244 | } 245 | 246 | //! [code_USBD_User_HID] 247 | -------------------------------------------------------------------------------- /CMSIS_DAP/CMSIS/DAP/Firmware/Validation/MDK5/RTE/Device/ARMCM3/startup_ARMCM3.s: -------------------------------------------------------------------------------- 1 | ;/**************************************************************************//** 2 | ; * @file startup_ARMCM3.s 3 | ; * @brief CMSIS Core Device Startup File for 4 | ; * ARMCM3 Device Series 5 | ; * @version V5.00 6 | ; * @date 02. March 2016 7 | ; ******************************************************************************/ 8 | ;/* 9 | ; * Copyright (c) 2009-2016 ARM Limited. All rights reserved. 10 | ; * 11 | ; * SPDX-License-Identifier: Apache-2.0 12 | ; * 13 | ; * Licensed under the Apache License, Version 2.0 (the License); you may 14 | ; * not use this file except in compliance with the License. 15 | ; * You may obtain a copy of the License at 16 | ; * 17 | ; * www.apache.org/licenses/LICENSE-2.0 18 | ; * 19 | ; * Unless required by applicable law or agreed to in writing, software 20 | ; * distributed under the License is distributed on an AS IS BASIS, WITHOUT 21 | ; * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 22 | ; * See the License for the specific language governing permissions and 23 | ; * limitations under the License. 24 | ; */ 25 | 26 | ;/* 27 | ;//-------- <<< Use Configuration Wizard in Context Menu >>> ------------------ 28 | ;*/ 29 | 30 | 31 | ; Stack Configuration 32 | ; Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> 33 | ; 34 | 35 | Stack_Size EQU 0x00000400 36 | 37 | AREA STACK, NOINIT, READWRITE, ALIGN=3 38 | Stack_Mem SPACE Stack_Size 39 | __initial_sp 40 | 41 | 42 | ; Heap Configuration 43 | ; Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> 44 | ; 45 | 46 | Heap_Size EQU 0x00000C00 47 | 48 | AREA HEAP, NOINIT, READWRITE, ALIGN=3 49 | __heap_base 50 | Heap_Mem SPACE Heap_Size 51 | __heap_limit 52 | 53 | 54 | PRESERVE8 55 | THUMB 56 | 57 | 58 | ; Vector Table Mapped to Address 0 at Reset 59 | 60 | AREA RESET, DATA, READONLY 61 | EXPORT __Vectors 62 | EXPORT __Vectors_End 63 | EXPORT __Vectors_Size 64 | 65 | __Vectors DCD __initial_sp ; Top of Stack 66 | DCD Reset_Handler ; Reset Handler 67 | DCD NMI_Handler ; NMI Handler 68 | DCD HardFault_Handler ; Hard Fault Handler 69 | DCD MemManage_Handler ; MPU Fault Handler 70 | DCD BusFault_Handler ; Bus Fault Handler 71 | DCD UsageFault_Handler ; Usage Fault Handler 72 | DCD 0 ; Reserved 73 | DCD 0 ; Reserved 74 | DCD 0 ; Reserved 75 | DCD 0 ; Reserved 76 | DCD SVC_Handler ; SVCall Handler 77 | DCD DebugMon_Handler ; Debug Monitor Handler 78 | DCD 0 ; Reserved 79 | DCD PendSV_Handler ; PendSV Handler 80 | DCD SysTick_Handler ; SysTick Handler 81 | 82 | ; External Interrupts 83 | DCD WDT_IRQHandler ; 0: Watchdog Timer 84 | DCD RTC_IRQHandler ; 1: Real Time Clock 85 | DCD TIM0_IRQHandler ; 2: Timer0 / Timer1 86 | DCD TIM2_IRQHandler ; 3: Timer2 / Timer3 87 | DCD MCIA_IRQHandler ; 4: MCIa 88 | DCD MCIB_IRQHandler ; 5: MCIb 89 | DCD UART0_IRQHandler ; 6: UART0 - DUT FPGA 90 | DCD UART1_IRQHandler ; 7: UART1 - DUT FPGA 91 | DCD UART2_IRQHandler ; 8: UART2 - DUT FPGA 92 | DCD UART4_IRQHandler ; 9: UART4 - not connected 93 | DCD AACI_IRQHandler ; 10: AACI / AC97 94 | DCD CLCD_IRQHandler ; 11: CLCD Combined Interrupt 95 | DCD ENET_IRQHandler ; 12: Ethernet 96 | DCD USBDC_IRQHandler ; 13: USB Device 97 | DCD USBHC_IRQHandler ; 14: USB Host Controller 98 | DCD CHLCD_IRQHandler ; 15: Character LCD 99 | DCD FLEXRAY_IRQHandler ; 16: Flexray 100 | DCD CAN_IRQHandler ; 17: CAN 101 | DCD LIN_IRQHandler ; 18: LIN 102 | DCD I2C_IRQHandler ; 19: I2C ADC/DAC 103 | DCD 0 ; 20: Reserved 104 | DCD 0 ; 21: Reserved 105 | DCD 0 ; 22: Reserved 106 | DCD 0 ; 23: Reserved 107 | DCD 0 ; 24: Reserved 108 | DCD 0 ; 25: Reserved 109 | DCD 0 ; 26: Reserved 110 | DCD 0 ; 27: Reserved 111 | DCD CPU_CLCD_IRQHandler ; 28: Reserved - CPU FPGA CLCD 112 | DCD 0 ; 29: Reserved - CPU FPGA 113 | DCD UART3_IRQHandler ; 30: UART3 - CPU FPGA 114 | DCD SPI_IRQHandler ; 31: SPI Touchscreen - CPU FPGA 115 | __Vectors_End 116 | 117 | __Vectors_Size EQU __Vectors_End - __Vectors 118 | 119 | AREA |.text|, CODE, READONLY 120 | 121 | 122 | ; Reset Handler 123 | 124 | Reset_Handler PROC 125 | EXPORT Reset_Handler [WEAK] 126 | IMPORT SystemInit 127 | IMPORT __main 128 | LDR R0, =SystemInit 129 | BLX R0 130 | LDR R0, =__main 131 | BX R0 132 | ENDP 133 | 134 | 135 | ; Dummy Exception Handlers (infinite loops which can be modified) 136 | 137 | NMI_Handler PROC 138 | EXPORT NMI_Handler [WEAK] 139 | B . 140 | ENDP 141 | HardFault_Handler\ 142 | PROC 143 | EXPORT HardFault_Handler [WEAK] 144 | B . 145 | ENDP 146 | MemManage_Handler\ 147 | PROC 148 | EXPORT MemManage_Handler [WEAK] 149 | B . 150 | ENDP 151 | BusFault_Handler\ 152 | PROC 153 | EXPORT BusFault_Handler [WEAK] 154 | B . 155 | ENDP 156 | UsageFault_Handler\ 157 | PROC 158 | EXPORT UsageFault_Handler [WEAK] 159 | B . 160 | ENDP 161 | SVC_Handler PROC 162 | EXPORT SVC_Handler [WEAK] 163 | B . 164 | ENDP 165 | DebugMon_Handler\ 166 | PROC 167 | EXPORT DebugMon_Handler [WEAK] 168 | B . 169 | ENDP 170 | PendSV_Handler PROC 171 | EXPORT PendSV_Handler [WEAK] 172 | B . 173 | ENDP 174 | SysTick_Handler PROC 175 | EXPORT SysTick_Handler [WEAK] 176 | B . 177 | ENDP 178 | 179 | Default_Handler PROC 180 | 181 | EXPORT WDT_IRQHandler [WEAK] 182 | EXPORT RTC_IRQHandler [WEAK] 183 | EXPORT TIM0_IRQHandler [WEAK] 184 | EXPORT TIM2_IRQHandler [WEAK] 185 | EXPORT MCIA_IRQHandler [WEAK] 186 | EXPORT MCIB_IRQHandler [WEAK] 187 | EXPORT UART0_IRQHandler [WEAK] 188 | EXPORT UART1_IRQHandler [WEAK] 189 | EXPORT UART2_IRQHandler [WEAK] 190 | EXPORT UART3_IRQHandler [WEAK] 191 | EXPORT UART4_IRQHandler [WEAK] 192 | EXPORT AACI_IRQHandler [WEAK] 193 | EXPORT CLCD_IRQHandler [WEAK] 194 | EXPORT ENET_IRQHandler [WEAK] 195 | EXPORT USBDC_IRQHandler [WEAK] 196 | EXPORT USBHC_IRQHandler [WEAK] 197 | EXPORT CHLCD_IRQHandler [WEAK] 198 | EXPORT FLEXRAY_IRQHandler [WEAK] 199 | EXPORT CAN_IRQHandler [WEAK] 200 | EXPORT LIN_IRQHandler [WEAK] 201 | EXPORT I2C_IRQHandler [WEAK] 202 | EXPORT CPU_CLCD_IRQHandler [WEAK] 203 | EXPORT SPI_IRQHandler [WEAK] 204 | 205 | WDT_IRQHandler 206 | RTC_IRQHandler 207 | TIM0_IRQHandler 208 | TIM2_IRQHandler 209 | MCIA_IRQHandler 210 | MCIB_IRQHandler 211 | UART0_IRQHandler 212 | UART1_IRQHandler 213 | UART2_IRQHandler 214 | UART3_IRQHandler 215 | UART4_IRQHandler 216 | AACI_IRQHandler 217 | CLCD_IRQHandler 218 | ENET_IRQHandler 219 | USBDC_IRQHandler 220 | USBHC_IRQHandler 221 | CHLCD_IRQHandler 222 | FLEXRAY_IRQHandler 223 | CAN_IRQHandler 224 | LIN_IRQHandler 225 | I2C_IRQHandler 226 | CPU_CLCD_IRQHandler 227 | SPI_IRQHandler 228 | B . 229 | 230 | ENDP 231 | 232 | 233 | ALIGN 234 | 235 | 236 | ; User Initial Stack & Heap 237 | 238 | IF :DEF:__MICROLIB 239 | 240 | EXPORT __initial_sp 241 | EXPORT __heap_base 242 | EXPORT __heap_limit 243 | 244 | ELSE 245 | 246 | IMPORT __use_two_region_memory 247 | EXPORT __user_initial_stackheap 248 | 249 | __user_initial_stackheap PROC 250 | LDR R0, = Heap_Mem 251 | LDR R1, =(Stack_Mem + Stack_Size) 252 | LDR R2, = (Heap_Mem + Heap_Size) 253 | LDR R3, = Stack_Mem 254 | BX LR 255 | ENDP 256 | 257 | ALIGN 258 | 259 | ENDIF 260 | 261 | 262 | END 263 | -------------------------------------------------------------------------------- /src/usb_descriptors.c: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2019 Ha Thach (tinyusb.org) 5 | * Copyright (c) 2021 Peter Lawrence 6 | * Copyright (c) 2022 Raspberry Pi Ltd 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | * 26 | */ 27 | 28 | #include "tusb.h" 29 | #include "get_serial.h" 30 | #include "probe_config.h" 31 | 32 | //--------------------------------------------------------------------+ 33 | // Device Descriptors 34 | //--------------------------------------------------------------------+ 35 | tusb_desc_device_t const desc_device = 36 | { 37 | .bLength = sizeof(tusb_desc_device_t), 38 | .bDescriptorType = TUSB_DESC_DEVICE, 39 | #if (PROBE_DEBUG_PROTOCOL == PROTO_DAP_V2) 40 | .bcdUSB = 0x0210, // USB Specification version 2.1 for BOS 41 | #else 42 | .bcdUSB = 0x0110, 43 | #endif 44 | .bDeviceClass = 0x00, // Each interface specifies its own 45 | .bDeviceSubClass = 0x00, // Each interface specifies its own 46 | .bDeviceProtocol = 0x00, 47 | .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, 48 | 49 | .idVendor = 0x2E8A, // Pi 50 | .idProduct = 0x000c, // CMSIS-DAP Debug Probe 51 | .bcdDevice = 0x0223, // Version 02.23 52 | .iManufacturer = 0x01, 53 | .iProduct = 0x02, 54 | .iSerialNumber = 0x03, 55 | .bNumConfigurations = 0x01 56 | }; 57 | 58 | // Invoked when received GET DEVICE DESCRIPTOR 59 | // Application return pointer to descriptor 60 | uint8_t const * tud_descriptor_device_cb(void) 61 | { 62 | return (uint8_t const *) &desc_device; 63 | } 64 | 65 | //--------------------------------------------------------------------+ 66 | // Configuration Descriptor 67 | //--------------------------------------------------------------------+ 68 | 69 | enum 70 | { 71 | ITF_NUM_PROBE, // Old versions of Keil MDK only look at interface 0 72 | ITF_NUM_CDC_COM, 73 | ITF_NUM_CDC_DATA, 74 | ITF_NUM_TOTAL 75 | }; 76 | 77 | #define CDC_NOTIFICATION_EP_NUM 0x81 78 | #define CDC_DATA_OUT_EP_NUM 0x02 79 | #define CDC_DATA_IN_EP_NUM 0x83 80 | #define DAP_OUT_EP_NUM 0x04 81 | #define DAP_IN_EP_NUM 0x85 82 | 83 | #if (PROBE_DEBUG_PROTOCOL == PROTO_DAP_V1) 84 | #define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN + TUD_HID_INOUT_DESC_LEN) 85 | #else 86 | #define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN + TUD_VENDOR_DESC_LEN) 87 | #endif 88 | 89 | static uint8_t const desc_hid_report[] = 90 | { 91 | TUD_HID_REPORT_DESC_GENERIC_INOUT(CFG_TUD_HID_EP_BUFSIZE) 92 | }; 93 | 94 | uint8_t const * tud_hid_descriptor_report_cb(uint8_t itf) 95 | { 96 | (void) itf; 97 | return desc_hid_report; 98 | } 99 | 100 | uint8_t desc_configuration[] = 101 | { 102 | TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0, 100), 103 | // Interface 0 104 | #if (PROBE_DEBUG_PROTOCOL == PROTO_DAP_V1) 105 | // HID (named interface) 106 | TUD_HID_INOUT_DESCRIPTOR(ITF_NUM_PROBE, 4, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report), DAP_OUT_EP_NUM, DAP_IN_EP_NUM, CFG_TUD_HID_EP_BUFSIZE, 1), 107 | #elif (PROBE_DEBUG_PROTOCOL == PROTO_DAP_V2) 108 | // Bulk (named interface) 109 | TUD_VENDOR_DESCRIPTOR(ITF_NUM_PROBE, 5, DAP_OUT_EP_NUM, DAP_IN_EP_NUM, 64), 110 | #elif (PROBE_DEBUG_PROTOCOL == PROTO_OPENOCD_CUSTOM) 111 | // Bulk 112 | TUD_VENDOR_DESCRIPTOR(ITF_NUM_PROBE, 0, DAP_OUT_EP_NUM, DAP_IN_EP_NUM, 64), 113 | #endif 114 | // Interface 1 + 2 115 | TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_COM, 6, CDC_NOTIFICATION_EP_NUM, 64, CDC_DATA_OUT_EP_NUM, CDC_DATA_IN_EP_NUM, 64), 116 | }; 117 | 118 | // Invoked when received GET CONFIGURATION DESCRIPTOR 119 | // Application return pointer to descriptor 120 | // Descriptor contents must exist long enough for transfer to complete 121 | uint8_t const * tud_descriptor_configuration_cb(uint8_t index) 122 | { 123 | (void) index; // for multiple configurations 124 | /* Hack in CAP_BREAK support */ 125 | desc_configuration[CONFIG_TOTAL_LEN - TUD_CDC_DESC_LEN + 8 + 9 + 5 + 5 + 4 - 1] = 0x6; 126 | return desc_configuration; 127 | } 128 | 129 | //--------------------------------------------------------------------+ 130 | // String Descriptors 131 | //--------------------------------------------------------------------+ 132 | 133 | // array of pointer to string descriptors 134 | char const* string_desc_arr [] = 135 | { 136 | (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) 137 | "Raspberry Pi", // 1: Manufacturer 138 | PROBE_PRODUCT_STRING, // 2: Product 139 | usb_serial, // 3: Serial, uses flash unique ID 140 | "CMSIS-DAP v1 Interface", // 4: Interface descriptor for HID transport 141 | "CMSIS-DAP v2 Interface", // 5: Interface descriptor for Bulk transport 142 | "CDC-ACM UART Interface", // 6: Interface descriptor for CDC 143 | }; 144 | 145 | static uint16_t _desc_str[32]; 146 | 147 | // Invoked when received GET STRING DESCRIPTOR request 148 | // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete 149 | uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid) 150 | { 151 | (void) langid; 152 | 153 | uint8_t chr_count; 154 | 155 | if ( index == 0) 156 | { 157 | memcpy(&_desc_str[1], string_desc_arr[0], 2); 158 | chr_count = 1; 159 | }else 160 | { 161 | // Convert ASCII string into UTF-16 162 | 163 | if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) return NULL; 164 | 165 | const char* str = string_desc_arr[index]; 166 | 167 | // Cap at max char 168 | chr_count = strlen(str); 169 | if ( chr_count > 31 ) chr_count = 31; 170 | 171 | for(uint8_t i=0; iwptr + 1) % DAP_PACKET_COUNT == buffer->rptr); 33 | } 34 | 35 | bool buffer_empty(buffer_t *buffer) 36 | { 37 | return (buffer->wptr == buffer->rptr); 38 | } 39 | 40 | void dap_edpt_init(void) { 41 | 42 | } 43 | 44 | bool dap_edpt_deinit(void) 45 | { 46 | memset(DAPRequestBuffer, 0, sizeof(DAPRequestBuffer)); 47 | memset(DAPResponseBuffer, 0, sizeof(DAPResponseBuffer)); 48 | USBRequestBuffer.wptr = USBRequestBuffer.rptr = 0; 49 | USBResponseBuffer.wptr = USBResponseBuffer.rptr = 0; 50 | return true; 51 | } 52 | 53 | void dap_edpt_reset(uint8_t __unused rhport) 54 | { 55 | itf_num = 0; 56 | } 57 | 58 | char * dap_cmd_string[] = { 59 | [ID_DAP_Info ] = "DAP_Info", 60 | [ID_DAP_HostStatus ] = "DAP_HostStatus", 61 | [ID_DAP_Connect ] = "DAP_Connect", 62 | [ID_DAP_Disconnect ] = "DAP_Disconnect", 63 | [ID_DAP_TransferConfigure ] = "DAP_TransferConfigure", 64 | [ID_DAP_Transfer ] = "DAP_Transfer", 65 | [ID_DAP_TransferBlock ] = "DAP_TransferBlock", 66 | [ID_DAP_TransferAbort ] = "DAP_TransferAbort", 67 | [ID_DAP_WriteABORT ] = "DAP_WriteABORT", 68 | [ID_DAP_Delay ] = "DAP_Delay", 69 | [ID_DAP_ResetTarget ] = "DAP_ResetTarget", 70 | [ID_DAP_SWJ_Pins ] = "DAP_SWJ_Pins", 71 | [ID_DAP_SWJ_Clock ] = "DAP_SWJ_Clock", 72 | [ID_DAP_SWJ_Sequence ] = "DAP_SWJ_Sequence", 73 | [ID_DAP_SWD_Configure ] = "DAP_SWD_Configure", 74 | [ID_DAP_SWD_Sequence ] = "DAP_SWD_Sequence", 75 | [ID_DAP_JTAG_Sequence ] = "DAP_JTAG_Sequence", 76 | [ID_DAP_JTAG_Configure ] = "DAP_JTAG_Configure", 77 | [ID_DAP_JTAG_IDCODE ] = "DAP_JTAG_IDCODE", 78 | [ID_DAP_SWO_Transport ] = "DAP_SWO_Transport", 79 | [ID_DAP_SWO_Mode ] = "DAP_SWO_Mode", 80 | [ID_DAP_SWO_Baudrate ] = "DAP_SWO_Baudrate", 81 | [ID_DAP_SWO_Control ] = "DAP_SWO_Control", 82 | [ID_DAP_SWO_Status ] = "DAP_SWO_Status", 83 | [ID_DAP_SWO_ExtendedStatus ] = "DAP_SWO_ExtendedStatus", 84 | [ID_DAP_SWO_Data ] = "DAP_SWO_Data", 85 | [ID_DAP_QueueCommands ] = "DAP_QueueCommands", 86 | [ID_DAP_ExecuteCommands ] = "DAP_ExecuteCommands", 87 | }; 88 | 89 | 90 | uint16_t dap_edpt_open(uint8_t __unused rhport, tusb_desc_interface_t const *itf_desc, uint16_t max_len) 91 | { 92 | 93 | TU_VERIFY(TUSB_CLASS_VENDOR_SPECIFIC == itf_desc->bInterfaceClass && 94 | DAP_INTERFACE_SUBCLASS == itf_desc->bInterfaceSubClass && 95 | DAP_INTERFACE_PROTOCOL == itf_desc->bInterfaceProtocol, 0); 96 | 97 | // Initialise circular buffer indices 98 | USBResponseBuffer.wptr = 0; 99 | USBResponseBuffer.rptr = 0; 100 | USBRequestBuffer.wptr = 0; 101 | USBRequestBuffer.rptr = 0; 102 | 103 | // Initialse full/empty flags 104 | USBResponseBuffer.wasFull = false; 105 | USBResponseBuffer.wasEmpty = true; 106 | USBRequestBuffer.wasFull = false; 107 | USBRequestBuffer.wasEmpty = true; 108 | 109 | uint16_t const drv_len = sizeof(tusb_desc_interface_t) + (itf_desc->bNumEndpoints * sizeof(tusb_desc_endpoint_t)); 110 | TU_VERIFY(max_len >= drv_len, 0); 111 | itf_num = itf_desc->bInterfaceNumber; 112 | 113 | // Initialising the OUT endpoint 114 | 115 | tusb_desc_endpoint_t *edpt_desc = (tusb_desc_endpoint_t *) (itf_desc + 1); 116 | uint8_t ep_addr = edpt_desc->bEndpointAddress; 117 | 118 | _out_ep_addr = ep_addr; 119 | 120 | // The OUT endpoint requires a call to usbd_edpt_xfer to initialise the endpoint, giving tinyUSB a buffer to consume when a transfer occurs at the endpoint 121 | usbd_edpt_open(rhport, edpt_desc); 122 | usbd_edpt_xfer(rhport, ep_addr, WR_SLOT_PTR(USBRequestBuffer), DAP_PACKET_SIZE); 123 | 124 | // Initiliasing the IN endpoint 125 | 126 | edpt_desc++; 127 | ep_addr = edpt_desc->bEndpointAddress; 128 | 129 | _in_ep_addr = ep_addr; 130 | 131 | // The IN endpoint doesn't need a transfer to initialise it, as this will be done by the main loop of dap_thread 132 | usbd_edpt_open(rhport, edpt_desc); 133 | 134 | return drv_len; 135 | 136 | } 137 | 138 | bool dap_edpt_control_xfer_cb(uint8_t __unused rhport, uint8_t stage, tusb_control_request_t const *request) 139 | { 140 | return false; 141 | } 142 | 143 | // Manage USBResponseBuffer (request) write and USBRequestBuffer (response) read indices 144 | bool dap_edpt_xfer_cb(uint8_t __unused rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) 145 | { 146 | const uint8_t ep_dir = tu_edpt_dir(ep_addr); 147 | 148 | if(ep_dir == TUSB_DIR_IN) 149 | { 150 | if(xferred_bytes >= 0u && xferred_bytes <= DAP_PACKET_SIZE) 151 | { 152 | USBResponseBuffer.rptr++; 153 | 154 | // This checks that the buffer was not empty in DAP thread, which means the next buffer was not queued up for the in endpoint callback 155 | // So, queue up the buffer at the new read index, since we expect read to catch up to write at this point. 156 | // It is possible for the read index to be multiple spaces behind the write index (if the USB callbacks are lagging behind dap thread), 157 | // so we account for this by only setting wasEmpty to true if the next callback will empty the buffer 158 | if(!USBResponseBuffer.wasEmpty) 159 | { 160 | usbd_edpt_xfer(rhport, ep_addr, RD_SLOT_PTR(USBResponseBuffer), (uint16_t) _resp_len); 161 | USBResponseBuffer.wasEmpty = (USBResponseBuffer.rptr + 1) == USBResponseBuffer.wptr; 162 | } 163 | 164 | // Wake up DAP thread after processing the callback 165 | vTaskResume(dap_taskhandle); 166 | return true; 167 | } 168 | 169 | return false; 170 | 171 | } else if(ep_dir == TUSB_DIR_OUT) { 172 | 173 | if(xferred_bytes >= 0u && xferred_bytes <= DAP_PACKET_SIZE) 174 | { 175 | // Only queue the next buffer in the out callback if the buffer is not full 176 | // If full, we set the wasFull flag, which will be checked by dap thread 177 | if(!buffer_full(&USBRequestBuffer)) 178 | { 179 | USBRequestBuffer.wptr++; 180 | usbd_edpt_xfer(rhport, ep_addr, WR_SLOT_PTR(USBRequestBuffer), DAP_PACKET_SIZE); 181 | USBRequestBuffer.wasFull = false; 182 | } 183 | else { 184 | USBRequestBuffer.wasFull = true; 185 | } 186 | 187 | // Wake up DAP thread after processing the callback 188 | vTaskResume(dap_taskhandle); 189 | return true; 190 | } 191 | 192 | return false; 193 | } 194 | else return false; 195 | } 196 | 197 | void dap_thread(void *ptr) 198 | { 199 | uint32_t n; 200 | do 201 | { 202 | while(USBRequestBuffer.rptr != USBRequestBuffer.wptr) 203 | { 204 | /* 205 | * Atomic command support - buffer QueueCommands, but don't process them 206 | * until a non-QueueCommands packet is seen. 207 | */ 208 | n = USBRequestBuffer.rptr; 209 | while (USBRequestBuffer.data[n % DAP_PACKET_COUNT][0] == ID_DAP_QueueCommands) { 210 | probe_info("%lu %lu DAP queued cmd %s len %02x\n", 211 | USBRequestBuffer.wptr, USBRequestBuffer.rptr, 212 | dap_cmd_string[USBRequestBuffer.data[n % DAP_PACKET_COUNT][0]], USBRequestBuffer.data[n % DAP_PACKET_COUNT][1]); 213 | USBRequestBuffer.data[n % DAP_PACKET_COUNT][0] = ID_DAP_ExecuteCommands; 214 | n++; 215 | while (n == USBRequestBuffer.wptr) { 216 | /* Need yield in a loop here, as IN callbacks will also wake the thread */ 217 | probe_info("DAP wait\n"); 218 | vTaskSuspend(dap_taskhandle); 219 | } 220 | } 221 | // Read a single packet from the USB buffer into the DAP Request buffer 222 | memcpy(DAPRequestBuffer, RD_SLOT_PTR(USBRequestBuffer), DAP_PACKET_SIZE); 223 | probe_info("%lu %lu DAP cmd %s len %02x\n", 224 | USBRequestBuffer.wptr, USBRequestBuffer.rptr, 225 | dap_cmd_string[DAPRequestBuffer[0]], DAPRequestBuffer[1]); 226 | USBRequestBuffer.rptr++; 227 | 228 | // If the buffer was full in the out callback, we need to queue up another buffer for the endpoint to consume, now that we know there is space in the buffer. 229 | if(USBRequestBuffer.wasFull) 230 | { 231 | vTaskSuspendAll(); // Suspend the scheduler to safely update the write index 232 | USBRequestBuffer.wptr++; 233 | usbd_edpt_xfer(_rhport, _out_ep_addr, WR_SLOT_PTR(USBRequestBuffer), DAP_PACKET_SIZE); 234 | USBRequestBuffer.wasFull = false; 235 | xTaskResumeAll(); 236 | } 237 | 238 | _resp_len = DAP_ExecuteCommand(DAPRequestBuffer, DAPResponseBuffer); 239 | probe_info("%lu %lu DAP resp %s\n", 240 | USBResponseBuffer.wptr, USBResponseBuffer.rptr, 241 | dap_cmd_string[DAPResponseBuffer[0]]); 242 | 243 | 244 | // Suspend the scheduler to avoid stale values/race conditions between threads 245 | vTaskSuspendAll(); 246 | 247 | if(buffer_empty(&USBResponseBuffer)) 248 | { 249 | memcpy(WR_SLOT_PTR(USBResponseBuffer), DAPResponseBuffer, (uint16_t) _resp_len); 250 | USBResponseBuffer.wptr++; 251 | 252 | usbd_edpt_xfer(_rhport, _in_ep_addr, RD_SLOT_PTR(USBResponseBuffer), (uint16_t) _resp_len); 253 | } else { 254 | 255 | memcpy(WR_SLOT_PTR(USBResponseBuffer), DAPResponseBuffer, (uint16_t) _resp_len); 256 | USBResponseBuffer.wptr++; 257 | 258 | // The In callback needs to check this flag to know when to queue up the next buffer. 259 | USBResponseBuffer.wasEmpty = false; 260 | } 261 | xTaskResumeAll(); 262 | } 263 | 264 | // Suspend DAP thread until it is awoken by a USB thread callback 265 | vTaskSuspend(dap_taskhandle); 266 | 267 | } while (1); 268 | 269 | } 270 | 271 | usbd_class_driver_t const _dap_edpt_driver = 272 | { 273 | .init = dap_edpt_init, 274 | .deinit = dap_edpt_deinit, 275 | .reset = dap_edpt_reset, 276 | .open = dap_edpt_open, 277 | .control_xfer_cb = dap_edpt_control_xfer_cb, 278 | .xfer_cb = dap_edpt_xfer_cb, 279 | .sof = NULL, 280 | #if CFG_TUSB_DEBUG >= 2 281 | .name = "DAP ENDPOINT" 282 | #endif 283 | }; 284 | 285 | // Add the custom driver to the tinyUSB stack 286 | usbd_class_driver_t const *usbd_app_driver_get_cb(uint8_t *driver_count) 287 | { 288 | *driver_count = 1; 289 | return &_dap_edpt_driver; 290 | } 291 | 292 | -------------------------------------------------------------------------------- /CMSIS_DAP/CMSIS/Core/Include/cmsis_compiler.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************//** 2 | * @file cmsis_compiler.h 3 | * @brief CMSIS compiler generic header file 4 | * @version V5.1.0 5 | * @date 09. October 2018 6 | ******************************************************************************/ 7 | /* 8 | * Copyright (c) 2009-2018 Arm Limited. All rights reserved. 9 | * 10 | * SPDX-License-Identifier: Apache-2.0 11 | * 12 | * Licensed under the Apache License, Version 2.0 (the License); you may 13 | * not use this file except in compliance with the License. 14 | * You may obtain a copy of the License at 15 | * 16 | * www.apache.org/licenses/LICENSE-2.0 17 | * 18 | * Unless required by applicable law or agreed to in writing, software 19 | * distributed under the License is distributed on an AS IS BASIS, WITHOUT 20 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 21 | * See the License for the specific language governing permissions and 22 | * limitations under the License. 23 | */ 24 | 25 | #ifndef __CMSIS_COMPILER_H 26 | #define __CMSIS_COMPILER_H 27 | 28 | #include 29 | 30 | /* 31 | * Arm Compiler 4/5 32 | */ 33 | #if defined ( __CC_ARM ) 34 | #include "cmsis_armcc.h" 35 | 36 | 37 | /* 38 | * Arm Compiler 6.6 LTM (armclang) 39 | */ 40 | #elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) && (__ARMCC_VERSION < 6100100) 41 | #include "cmsis_armclang_ltm.h" 42 | 43 | /* 44 | * Arm Compiler above 6.10.1 (armclang) 45 | */ 46 | #elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6100100) 47 | #include "cmsis_armclang.h" 48 | 49 | 50 | /* 51 | * GNU Compiler 52 | */ 53 | #elif defined ( __GNUC__ ) 54 | #include "cmsis_gcc.h" 55 | 56 | 57 | /* 58 | * IAR Compiler 59 | */ 60 | #elif defined ( __ICCARM__ ) 61 | #include 62 | 63 | 64 | /* 65 | * TI Arm Compiler 66 | */ 67 | #elif defined ( __TI_ARM__ ) 68 | #include 69 | 70 | #ifndef __ASM 71 | #define __ASM __asm 72 | #endif 73 | #ifndef __INLINE 74 | #define __INLINE inline 75 | #endif 76 | #ifndef __STATIC_INLINE 77 | #define __STATIC_INLINE static inline 78 | #endif 79 | #ifndef __STATIC_FORCEINLINE 80 | #define __STATIC_FORCEINLINE __STATIC_INLINE 81 | #endif 82 | #ifndef __NO_RETURN 83 | #define __NO_RETURN __attribute__((noreturn)) 84 | #endif 85 | #ifndef __USED 86 | #define __USED __attribute__((used)) 87 | #endif 88 | #ifndef __WEAK 89 | #define __WEAK __attribute__((weak)) 90 | #endif 91 | #ifndef __PACKED 92 | #define __PACKED __attribute__((packed)) 93 | #endif 94 | #ifndef __PACKED_STRUCT 95 | #define __PACKED_STRUCT struct __attribute__((packed)) 96 | #endif 97 | #ifndef __PACKED_UNION 98 | #define __PACKED_UNION union __attribute__((packed)) 99 | #endif 100 | #ifndef __UNALIGNED_UINT32 /* deprecated */ 101 | struct __attribute__((packed)) T_UINT32 { uint32_t v; }; 102 | #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) 103 | #endif 104 | #ifndef __UNALIGNED_UINT16_WRITE 105 | __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; 106 | #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void*)(addr))->v) = (val)) 107 | #endif 108 | #ifndef __UNALIGNED_UINT16_READ 109 | __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; 110 | #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) 111 | #endif 112 | #ifndef __UNALIGNED_UINT32_WRITE 113 | __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; 114 | #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) 115 | #endif 116 | #ifndef __UNALIGNED_UINT32_READ 117 | __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; 118 | #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) 119 | #endif 120 | #ifndef __ALIGNED 121 | #define __ALIGNED(x) __attribute__((aligned(x))) 122 | #endif 123 | #ifndef __RESTRICT 124 | #define __RESTRICT __restrict 125 | #endif 126 | #ifndef __COMPILER_BARRIER 127 | #warning No compiler specific solution for __COMPILER_BARRIER. __COMPILER_BARRIER is ignored. 128 | #define __COMPILER_BARRIER() (void)0 129 | #endif 130 | 131 | 132 | /* 133 | * TASKING Compiler 134 | */ 135 | #elif defined ( __TASKING__ ) 136 | /* 137 | * The CMSIS functions have been implemented as intrinsics in the compiler. 138 | * Please use "carm -?i" to get an up to date list of all intrinsics, 139 | * Including the CMSIS ones. 140 | */ 141 | 142 | #ifndef __ASM 143 | #define __ASM __asm 144 | #endif 145 | #ifndef __INLINE 146 | #define __INLINE inline 147 | #endif 148 | #ifndef __STATIC_INLINE 149 | #define __STATIC_INLINE static inline 150 | #endif 151 | #ifndef __STATIC_FORCEINLINE 152 | #define __STATIC_FORCEINLINE __STATIC_INLINE 153 | #endif 154 | #ifndef __NO_RETURN 155 | #define __NO_RETURN __attribute__((noreturn)) 156 | #endif 157 | #ifndef __USED 158 | #define __USED __attribute__((used)) 159 | #endif 160 | #ifndef __WEAK 161 | #define __WEAK __attribute__((weak)) 162 | #endif 163 | #ifndef __PACKED 164 | #define __PACKED __packed__ 165 | #endif 166 | #ifndef __PACKED_STRUCT 167 | #define __PACKED_STRUCT struct __packed__ 168 | #endif 169 | #ifndef __PACKED_UNION 170 | #define __PACKED_UNION union __packed__ 171 | #endif 172 | #ifndef __UNALIGNED_UINT32 /* deprecated */ 173 | struct __packed__ T_UINT32 { uint32_t v; }; 174 | #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) 175 | #endif 176 | #ifndef __UNALIGNED_UINT16_WRITE 177 | __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; 178 | #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val)) 179 | #endif 180 | #ifndef __UNALIGNED_UINT16_READ 181 | __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; 182 | #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) 183 | #endif 184 | #ifndef __UNALIGNED_UINT32_WRITE 185 | __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; 186 | #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) 187 | #endif 188 | #ifndef __UNALIGNED_UINT32_READ 189 | __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; 190 | #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) 191 | #endif 192 | #ifndef __ALIGNED 193 | #define __ALIGNED(x) __align(x) 194 | #endif 195 | #ifndef __RESTRICT 196 | #warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored. 197 | #define __RESTRICT 198 | #endif 199 | #ifndef __COMPILER_BARRIER 200 | #warning No compiler specific solution for __COMPILER_BARRIER. __COMPILER_BARRIER is ignored. 201 | #define __COMPILER_BARRIER() (void)0 202 | #endif 203 | 204 | 205 | /* 206 | * COSMIC Compiler 207 | */ 208 | #elif defined ( __CSMC__ ) 209 | #include 210 | 211 | #ifndef __ASM 212 | #define __ASM _asm 213 | #endif 214 | #ifndef __INLINE 215 | #define __INLINE inline 216 | #endif 217 | #ifndef __STATIC_INLINE 218 | #define __STATIC_INLINE static inline 219 | #endif 220 | #ifndef __STATIC_FORCEINLINE 221 | #define __STATIC_FORCEINLINE __STATIC_INLINE 222 | #endif 223 | #ifndef __NO_RETURN 224 | // NO RETURN is automatically detected hence no warning here 225 | #define __NO_RETURN 226 | #endif 227 | #ifndef __USED 228 | #warning No compiler specific solution for __USED. __USED is ignored. 229 | #define __USED 230 | #endif 231 | #ifndef __WEAK 232 | #define __WEAK __weak 233 | #endif 234 | #ifndef __PACKED 235 | #define __PACKED @packed 236 | #endif 237 | #ifndef __PACKED_STRUCT 238 | #define __PACKED_STRUCT @packed struct 239 | #endif 240 | #ifndef __PACKED_UNION 241 | #define __PACKED_UNION @packed union 242 | #endif 243 | #ifndef __UNALIGNED_UINT32 /* deprecated */ 244 | @packed struct T_UINT32 { uint32_t v; }; 245 | #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) 246 | #endif 247 | #ifndef __UNALIGNED_UINT16_WRITE 248 | __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; 249 | #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val)) 250 | #endif 251 | #ifndef __UNALIGNED_UINT16_READ 252 | __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; 253 | #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) 254 | #endif 255 | #ifndef __UNALIGNED_UINT32_WRITE 256 | __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; 257 | #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) 258 | #endif 259 | #ifndef __UNALIGNED_UINT32_READ 260 | __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; 261 | #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) 262 | #endif 263 | #ifndef __ALIGNED 264 | #warning No compiler specific solution for __ALIGNED. __ALIGNED is ignored. 265 | #define __ALIGNED(x) 266 | #endif 267 | #ifndef __RESTRICT 268 | #warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored. 269 | #define __RESTRICT 270 | #endif 271 | #ifndef __COMPILER_BARRIER 272 | #warning No compiler specific solution for __COMPILER_BARRIER. __COMPILER_BARRIER is ignored. 273 | #define __COMPILER_BARRIER() (void)0 274 | #endif 275 | 276 | 277 | #else 278 | #error Unknown compiler. 279 | #endif 280 | 281 | 282 | #endif /* __CMSIS_COMPILER_H */ 283 | 284 | -------------------------------------------------------------------------------- /src/cdc_uart.c: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2021 Raspberry Pi (Trading) Ltd. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | * 24 | */ 25 | 26 | #include 27 | #include "FreeRTOS.h" 28 | #include "task.h" 29 | #include "tusb.h" 30 | #include "autobaud.h" 31 | 32 | #include "probe_config.h" 33 | 34 | TaskHandle_t uart_taskhandle; 35 | TickType_t last_wake, interval = 100; 36 | volatile TickType_t break_expiry; 37 | volatile bool timed_break; 38 | 39 | /* Max 1 FIFO worth of data */ 40 | static uint8_t tx_buf[32]; 41 | static uint8_t rx_buf[32]; 42 | // Actually s^-1 so 25ms 43 | #define DEBOUNCE_MS 40 44 | static uint debounce_ticks = 5; 45 | 46 | #ifdef PROBE_UART_TX_LED 47 | static volatile uint tx_led_debounce; 48 | #endif 49 | 50 | #ifdef PROBE_UART_RX_LED 51 | static uint rx_led_debounce; 52 | #endif 53 | 54 | static BaudInfo_t baud_info; 55 | 56 | void cdc_uart_init(void) { 57 | gpio_set_function(PROBE_UART_TX, GPIO_FUNC_UART); 58 | gpio_set_function(PROBE_UART_RX, GPIO_FUNC_UART); 59 | gpio_set_pulls(PROBE_UART_TX, 1, 0); 60 | gpio_set_pulls(PROBE_UART_RX, 1, 0); 61 | uart_init(PROBE_UART_INTERFACE, PROBE_UART_BAUDRATE); 62 | 63 | #ifdef PROBE_UART_TX_LED 64 | tx_led_debounce = 0; 65 | gpio_init(PROBE_UART_TX_LED); 66 | gpio_set_dir(PROBE_UART_TX_LED, GPIO_OUT); 67 | #endif 68 | #ifdef PROBE_UART_RX_LED 69 | rx_led_debounce = 0; 70 | gpio_init(PROBE_UART_RX_LED); 71 | gpio_set_dir(PROBE_UART_RX_LED, GPIO_OUT); 72 | #endif 73 | 74 | #ifdef PROBE_UART_HWFC 75 | /* HWFC implies that hardware flow control is implemented and the 76 | * UART operates in "full-duplex" mode (See USB CDC PSTN120 6.3.12). 77 | * Default to pulling in the active direction, so an unconnected CTS 78 | * behaves the same as if CTS were not enabled. */ 79 | gpio_set_pulls(PROBE_UART_CTS, 0, 1); 80 | gpio_set_function(PROBE_UART_RTS, GPIO_FUNC_UART); 81 | gpio_set_function(PROBE_UART_CTS, GPIO_FUNC_UART); 82 | uart_set_hw_flow(PROBE_UART_INTERFACE, true, true); 83 | #else 84 | #ifdef PROBE_UART_RTS 85 | gpio_init(PROBE_UART_RTS); 86 | gpio_set_dir(PROBE_UART_RTS, GPIO_OUT); 87 | gpio_put(PROBE_UART_RTS, 1); 88 | #endif 89 | #endif 90 | 91 | #ifdef PROBE_UART_DTR 92 | gpio_init(PROBE_UART_DTR); 93 | gpio_set_dir(PROBE_UART_DTR, GPIO_OUT); 94 | gpio_put(PROBE_UART_DTR, 1); 95 | #endif 96 | } 97 | 98 | bool cdc_task(void) 99 | { 100 | static int was_connected = 0; 101 | static uint cdc_tx_oe = 0; 102 | uint rx_len = 0; 103 | bool keep_alive = false; 104 | 105 | // Consume uart fifo regardless even if not connected 106 | while(uart_is_readable(PROBE_UART_INTERFACE) && (rx_len < sizeof(rx_buf))) { 107 | rx_buf[rx_len++] = uart_getc(PROBE_UART_INTERFACE); 108 | } 109 | 110 | if (tud_cdc_connected()) { 111 | was_connected = 1; 112 | int written = 0; 113 | /* Implicit overflow if we don't write all the bytes to the host. 114 | * Also throw away bytes if we can't write... */ 115 | if (rx_len) { 116 | #ifdef PROBE_UART_RX_LED 117 | gpio_put(PROBE_UART_RX_LED, 1); 118 | rx_led_debounce = debounce_ticks; 119 | #endif 120 | written = MIN(tud_cdc_write_available(), rx_len); 121 | if (rx_len > written) 122 | cdc_tx_oe++; 123 | 124 | if (written > 0) { 125 | tud_cdc_write(rx_buf, written); 126 | tud_cdc_write_flush(); 127 | } 128 | } else { 129 | #ifdef PROBE_UART_RX_LED 130 | if (rx_led_debounce) 131 | rx_led_debounce--; 132 | else 133 | gpio_put(PROBE_UART_RX_LED, 0); 134 | #endif 135 | } 136 | 137 | /* Reading from a firehose and writing to a FIFO. */ 138 | size_t watermark = MIN(tud_cdc_available(), sizeof(tx_buf)); 139 | if (watermark > 0) { 140 | size_t tx_len; 141 | #ifdef PROBE_UART_TX_LED 142 | gpio_put(PROBE_UART_TX_LED, 1); 143 | tx_led_debounce = debounce_ticks; 144 | #endif 145 | /* Batch up to half a FIFO of data - don't clog up on RX */ 146 | watermark = MIN(watermark, 16); 147 | tx_len = tud_cdc_read(tx_buf, watermark); 148 | uart_write_blocking(PROBE_UART_INTERFACE, tx_buf, tx_len); 149 | } else { 150 | #ifdef PROBE_UART_TX_LED 151 | if (tx_led_debounce) 152 | tx_led_debounce--; 153 | else 154 | gpio_put(PROBE_UART_TX_LED, 0); 155 | #endif 156 | } 157 | /* Pending break handling */ 158 | if (timed_break) { 159 | if (((int)break_expiry - (int)xTaskGetTickCount()) < 0) { 160 | timed_break = false; 161 | uart_set_break(PROBE_UART_INTERFACE, false); 162 | #ifdef PROBE_UART_TX_LED 163 | tx_led_debounce = 0; 164 | #endif 165 | } else { 166 | keep_alive = true; 167 | } 168 | } 169 | } else if (was_connected) { 170 | tud_cdc_write_clear(); 171 | uart_set_break(PROBE_UART_INTERFACE, false); 172 | timed_break = false; 173 | was_connected = 0; 174 | #ifdef PROBE_UART_TX_LED 175 | tx_led_debounce = 0; 176 | #endif 177 | cdc_tx_oe = 0; 178 | } 179 | return keep_alive; 180 | } 181 | 182 | void cdc_uart_set_baudrate(uint32_t baudrate) { 183 | /* Set the tick thread interval to the amount of time it takes to 184 | * fill up half a FIFO. Millis is too coarse for integer divide. 185 | */ 186 | uint32_t micros = (1000 * 1000 * 16 * 10) / MAX(baudrate, 1); 187 | interval = MAX(1, micros / ((1000 * 1000) / configTICK_RATE_HZ)); 188 | debounce_ticks = MAX(1, configTICK_RATE_HZ / (interval * DEBOUNCE_MS)); 189 | probe_info("New baud rate %ld micros %ld interval %lu\n", 190 | baudrate, micros, interval); 191 | uart_deinit(PROBE_UART_INTERFACE); 192 | tud_cdc_write_clear(); 193 | tud_cdc_read_flush(); 194 | 195 | uart_init(PROBE_UART_INTERFACE, baudrate); 196 | } 197 | 198 | void cdc_thread(void *ptr) 199 | { 200 | BaseType_t delayed; 201 | last_wake = xTaskGetTickCount(); 202 | bool keep_alive; 203 | /* Threaded with a polling interval that scales according to linerate */ 204 | while (1) { 205 | keep_alive = cdc_task(); 206 | if (!keep_alive) { 207 | delayed = xTaskDelayUntil(&last_wake, interval); 208 | if (delayed == pdFALSE) 209 | last_wake = xTaskGetTickCount(); 210 | if (autobaud_running) { 211 | // Receive baud information from autobaud thread 212 | if (xQueueReceive(baudQueue, &baud_info, 0) == pdTRUE) { 213 | cdc_uart_set_baudrate(baud_info.baud); 214 | // Assume 8N1 215 | uart_set_format(PROBE_UART_INTERFACE, 8, 1, UART_PARITY_NONE); 216 | } 217 | } 218 | } 219 | } 220 | } 221 | 222 | void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const* line_coding) 223 | { 224 | if (line_coding->bit_rate == MAGIC_BAUD) { 225 | if (!autobaud_running) 226 | autobaud_start(); 227 | return; 228 | } 229 | else if (autobaud_running) { 230 | autobaud_wait_stop(); 231 | } 232 | uart_parity_t parity; 233 | uint data_bits, stop_bits; 234 | 235 | /* Modifying state, so park the thread before changing it. */ 236 | if (tud_cdc_connected()) 237 | vTaskSuspend(uart_taskhandle); 238 | 239 | cdc_uart_set_baudrate(line_coding->bit_rate); 240 | 241 | switch (line_coding->parity) { 242 | case CDC_LINE_CODING_PARITY_ODD: 243 | parity = UART_PARITY_ODD; 244 | break; 245 | case CDC_LINE_CODING_PARITY_EVEN: 246 | parity = UART_PARITY_EVEN; 247 | break; 248 | default: 249 | probe_info("invalid parity setting %u\n", line_coding->parity); 250 | /* fallthrough */ 251 | case CDC_LINE_CODING_PARITY_NONE: 252 | parity = UART_PARITY_NONE; 253 | break; 254 | } 255 | 256 | switch (line_coding->data_bits) { 257 | case 5: 258 | case 6: 259 | case 7: 260 | case 8: 261 | data_bits = line_coding->data_bits; 262 | break; 263 | default: 264 | probe_info("invalid data bits setting: %u\n", line_coding->data_bits); 265 | data_bits = 8; 266 | break; 267 | } 268 | 269 | /* The PL011 only supports 1 or 2 stop bits. 1.5 stop bits is translated to 2, 270 | * which is safer than the alternative. */ 271 | switch (line_coding->stop_bits) { 272 | case CDC_LINE_CONDING_STOP_BITS_1_5: 273 | case CDC_LINE_CONDING_STOP_BITS_2: 274 | stop_bits = 2; 275 | break; 276 | default: 277 | probe_info("invalid stop bits setting: %u\n", line_coding->stop_bits); 278 | /* fallthrough */ 279 | case CDC_LINE_CONDING_STOP_BITS_1: 280 | stop_bits = 1; 281 | break; 282 | } 283 | 284 | uart_set_format(PROBE_UART_INTERFACE, data_bits, stop_bits, parity); 285 | /* Windows likes to arbitrarily set/get line coding after dtr/rts changes, so 286 | * don't resume if we shouldn't */ 287 | if(tud_cdc_connected()) 288 | vTaskResume(uart_taskhandle); 289 | } 290 | 291 | void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) 292 | { 293 | #ifdef PROBE_UART_RTS 294 | gpio_put(PROBE_UART_RTS, !rts); 295 | #endif 296 | #ifdef PROBE_UART_DTR 297 | gpio_put(PROBE_UART_DTR, !dtr); 298 | #endif 299 | 300 | /* CDC drivers use linestate as a bodge to activate/deactivate the interface. 301 | * Resume our UART polling on activate, stop on deactivate */ 302 | if (!dtr) { 303 | vTaskSuspend(uart_taskhandle); 304 | #ifdef PROBE_UART_RX_LED 305 | gpio_put(PROBE_UART_RX_LED, 0); 306 | rx_led_debounce = 0; 307 | #endif 308 | #ifdef PROBE_UART_TX_LED 309 | gpio_put(PROBE_UART_TX_LED, 0); 310 | tx_led_debounce = 0; 311 | #endif 312 | } else 313 | vTaskResume(uart_taskhandle); 314 | } 315 | 316 | void tud_cdc_send_break_cb(uint8_t itf, uint16_t wValue) { 317 | switch(wValue) { 318 | case 0: 319 | uart_set_break(PROBE_UART_INTERFACE, false); 320 | timed_break = false; 321 | #ifdef PROBE_UART_TX_LED 322 | tx_led_debounce = 0; 323 | #endif 324 | break; 325 | case 0xffff: 326 | uart_set_break(PROBE_UART_INTERFACE, true); 327 | timed_break = false; 328 | #ifdef PROBE_UART_TX_LED 329 | gpio_put(PROBE_UART_TX_LED, 1); 330 | tx_led_debounce = 1 << 30; 331 | #endif 332 | break; 333 | default: 334 | uart_set_break(PROBE_UART_INTERFACE, true); 335 | timed_break = true; 336 | #ifdef PROBE_UART_TX_LED 337 | gpio_put(PROBE_UART_TX_LED, 1); 338 | tx_led_debounce = 1 << 30; 339 | #endif 340 | break_expiry = xTaskGetTickCount() + (wValue * (configTICK_RATE_HZ / 1000)); 341 | break; 342 | } 343 | } 344 | -------------------------------------------------------------------------------- /CMSIS_DAP/CMSIS/DAP/Firmware/Validation/MDK5/test.ini: -------------------------------------------------------------------------------- 1 | /******************************************************************************/ 2 | /* test.ini: Initialization file to test the debug functionality */ 3 | /******************************************************************************/ 4 | /* This file is part of the uVision/ARM development tools. */ 5 | /* Copyright (c) 2012-2017 Keil Software. All rights reserved. */ 6 | /* This software may only be used under the terms of a valid, current, */ 7 | /* end user license from KEIL for a compatible version of KEIL software */ 8 | /* development tools. Nothing else gives you the right to use this software. */ 9 | /******************************************************************************/ 10 | 11 | // ensure logging into file is turned off 12 | LOG OFF 13 | 14 | // overall test success flag 15 | define int testSuccess; 16 | testSuccess = 0; 17 | 18 | // flags to show which particular tests succeeded 19 | define char bpExecSuccess; 20 | bpExecSuccess = 0; 21 | define char bpReadSuccess; 22 | bpReadSuccess = 0; 23 | define char bpWriteSuccess; 24 | bpWriteSuccess = 0; 25 | define char memReadSuccess; 26 | memReadSuccess = 0; 27 | define char memWriteSuccess; 28 | memWriteSuccess = 0; 29 | define char regReadSuccess; 30 | regReadSuccess = 0; 31 | define char regWriteSuccess; 32 | regWriteSuccess = 0; 33 | 34 | 35 | // function to read and write registers 36 | FUNC void RegReadWrite(void) { 37 | unsigned long VR0, VR1, VR2, VR3, VR4, VR5, VR6, VR7, VR8, VR9; 38 | unsigned long VR10, VR11, VR12, VR13, VR14, VR15, VxPSR; 39 | unsigned long VR_0, VR_1, VR_2, VR_3, VR_4, VR_5, VR_6, VR_7, VR_8, VR_9; 40 | unsigned long VR_10, VR_11, VR_12, VR_13, VR_14, VR_15, V_xPSR; 41 | unsigned long bogus; 42 | 43 | bogus = 0x0badF00D; 44 | 45 | printf("Register read started\n"); 46 | 47 | // initialize temporary variables with bogus value 48 | VR0 = bogus; 49 | VR1 = bogus; 50 | VR2 = bogus; 51 | VR3 = bogus; 52 | VR4 = bogus; 53 | VR5 = bogus; 54 | VR6 = bogus; 55 | VR7 = bogus; 56 | VR8 = bogus; 57 | VR9 = bogus; 58 | VR10 = bogus; 59 | VR11 = bogus; 60 | VR12 = bogus; 61 | VR13 = bogus; 62 | VR14 = bogus; 63 | VR15 = bogus; 64 | VxPSR = bogus; 65 | 66 | // read and save current register values 67 | VR0 = R0; 68 | VR1 = R1; 69 | VR2 = R2; 70 | VR3 = R3; 71 | VR4 = R4; 72 | VR5 = R5; 73 | VR6 = R6; 74 | VR7 = R7; 75 | VR8 = R8; 76 | VR9 = R9; 77 | VR10 = R10; 78 | VR11 = R11; 79 | VR12 = R12; 80 | VR13 = R13; 81 | VR14 = R14; 82 | VR15 = R15; 83 | VxPSR = xPSR; 84 | 85 | // print read register values 86 | printf("R0 = 0x%x\n", VR0); 87 | printf("R1 = 0x%x\n", VR1); 88 | printf("R2 = 0x%x\n", VR2); 89 | printf("R3 = 0x%x\n", VR3); 90 | printf("R4 = 0x%x\n", VR4); 91 | printf("R5 = 0x%x\n", VR5); 92 | printf("R6 = 0x%x\n", VR6); 93 | printf("R7 = 0x%x\n", VR7); 94 | printf("R8 = 0x%x\n", VR8); 95 | printf("R9 = 0x%x\n", VR9); 96 | printf("R10 = 0x%x\n", VR10); 97 | printf("R11 = 0x%x\n", VR11); 98 | printf("R12 = 0x%x\n", VR12); 99 | printf("R13 = 0x%x\n", VR13); 100 | printf("R14 = 0x%x\n", VR14); 101 | printf("R15 = 0x%x\n", VR15); 102 | printf("xPSR = 0x%x\n", VxPSR); 103 | 104 | // check if all values differ from bogus value 105 | regReadSuccess = 106 | (VR0 != bogus) && 107 | (VR1 != bogus) && 108 | (VR2 != bogus) && 109 | (VR3 != bogus) && 110 | (VR4 != bogus) && 111 | (VR5 != bogus) && 112 | (VR6 != bogus) && 113 | (VR7 != bogus) && 114 | (VR8 != bogus) && 115 | (VR9 != bogus) && 116 | (VR10 != bogus) && 117 | (VR11 != bogus) && 118 | (VR12 != bogus) && 119 | (VR13 != bogus) && 120 | (VR14 != bogus) && 121 | (VR15 != bogus) && 122 | (VxPSR != bogus); 123 | 124 | if (regReadSuccess != 0) { 125 | printf("Register read passed\n"); 126 | } else { 127 | printf("Register read failed\n"); 128 | // there is no reason to test write if read fails 129 | return; 130 | } 131 | 132 | printf("Register write started\n"); 133 | 134 | // fill all registers with bogus value 135 | R0 = bogus; 136 | R1 = bogus; 137 | R2 = bogus; 138 | R3 = bogus; 139 | R4 = bogus; 140 | R5 = bogus; 141 | R6 = bogus; 142 | R7 = bogus; 143 | R8 = bogus; 144 | R9 = bogus; 145 | R10 = bogus; 146 | R11 = bogus; 147 | R12 = bogus; 148 | // register R13-R15 and xPSR on hardware do not accept 0x0badf00d, use 0x0 instead 149 | R13 = 0x0; 150 | R14 = 0x0; 151 | R15 = 0x0; 152 | xPSR = 0x0; 153 | 154 | // read back into another array 155 | VR_0 = R0; 156 | VR_1 = R1; 157 | VR_2 = R2; 158 | VR_3 = R3; 159 | VR_4 = R4; 160 | VR_5 = R5; 161 | VR_6 = R6; 162 | VR_7 = R7; 163 | VR_8 = R8; 164 | VR_9 = R9; 165 | VR_10 = R10; 166 | VR_11 = R11; 167 | VR_12 = R12; 168 | VR_13 = R13; 169 | VR_14 = R14; 170 | VR_15 = R15; 171 | V_xPSR = xPSR; 172 | 173 | // print the values again 174 | printf("R0 = 0x%x\n", VR_0); 175 | printf("R1 = 0x%x\n", VR_1); 176 | printf("R2 = 0x%x\n", VR_2); 177 | printf("R3 = 0x%x\n", VR_3); 178 | printf("R4 = 0x%x\n", VR_4); 179 | printf("R5 = 0x%x\n", VR_5); 180 | printf("R6 = 0x%x\n", VR_6); 181 | printf("R7 = 0x%x\n", VR_7); 182 | printf("R8 = 0x%x\n", VR_8); 183 | printf("R9 = 0x%x\n", VR_9); 184 | printf("R10 = 0x%x\n", VR_10); 185 | printf("R11 = 0x%x\n", VR_11); 186 | printf("R12 = 0x%x\n", VR_12); 187 | printf("R13 = 0x%x\n", VR_13); 188 | printf("R14 = 0x%x\n", VR_14); 189 | printf("R15 = 0x%x\n", VR_15); 190 | printf("xPSR = 0x%x\n", V_xPSR); 191 | 192 | // check if new values are bogus 193 | regWriteSuccess = 194 | (VR_0 == bogus) && 195 | (VR_1 == bogus) && 196 | (VR_2 == bogus) && 197 | (VR_3 == bogus) && 198 | (VR_4 == bogus) && 199 | (VR_5 == bogus) && 200 | (VR_6 == bogus) && 201 | (VR_7 == bogus) && 202 | (VR_8 == bogus) && 203 | (VR_9 == bogus) && 204 | (VR_10 == bogus) && 205 | (VR_11 == bogus) && 206 | (VR_12 == bogus) && 207 | (VR_13 == 0x0) && 208 | (VR_14 == 0x0) && 209 | (VR_15 == 0x0) && 210 | (V_xPSR == 0x0); 211 | 212 | if (regWriteSuccess != 0) { 213 | printf("Register write passed\n"); 214 | } else { 215 | printf("Register write failed\n"); 216 | } 217 | 218 | // write saved values back into registers 219 | // values are required to be written correctly for the rest of the test 220 | R0 = VR0; 221 | R1 = VR1; 222 | R2 = VR2; 223 | R3 = VR3; 224 | R4 = VR4; 225 | R5 = VR5; 226 | R6 = VR6; 227 | R7 = VR7; 228 | R8 = VR8; 229 | R9 = VR9; 230 | R10 = VR10; 231 | R11 = VR11; 232 | R12 = VR12; 233 | R13 = VR13; 234 | R14 = VR14; 235 | R15 = VR15; 236 | xPSR = VxPSR; 237 | } 238 | 239 | 240 | // function to write predefined numbers into test_array1 241 | FUNC void MemWrite(unsigned long address) { 242 | unsigned int i; 243 | unsigned int val; 244 | 245 | printf("Memory write started\n"); 246 | val = 0x1000; 247 | for (i = 0; i < 256; i++) { 248 | _WWORD(address, val); 249 | val++; 250 | address += 4; 251 | } 252 | printf("Memory write completed\n"); 253 | } 254 | 255 | // function to read from test_array2 and check if write and read was successful 256 | FUNC void MemRead(unsigned long address) { 257 | unsigned int i; 258 | unsigned int val, v; 259 | 260 | printf("Memory read started\n"); 261 | val = 0x1000; 262 | memReadSuccess = 1; // assume it is true 263 | for (i = 0; i < 256; i++) { 264 | v = _RWORD(address); 265 | if (v != val) { 266 | memReadSuccess = 0; 267 | } 268 | val++; 269 | address += 4; 270 | } 271 | if (memReadSuccess != 0) { 272 | printf("Memory read passed\n"); 273 | } else { 274 | printf("Memory read failed\n"); 275 | } 276 | } 277 | 278 | 279 | // check execution breakpoint 280 | FUNC void CheckBpExec(unsigned long address) { 281 | // PC should be at address and value of bpTestCounter variable should be 9 282 | 283 | if ((R15 == address) && (`bpTestCounter == 9)) { 284 | bpExecSuccess = 1; 285 | } 286 | printf("Execution breakpoint (%d): %d\n", `bpTestCounter, bpExecSuccess); 287 | } 288 | 289 | // check breakpoint on read 290 | FUNC void CheckBpRead(int test_state) { 291 | // PC should be at address 292 | 293 | if (`test_state == test_state) { 294 | bpReadSuccess = 1; 295 | } 296 | printf("Breakpoint on read: %d\n",bpReadSuccess); 297 | } 298 | 299 | 300 | // check breakpoint on write 301 | FUNC void CheckBpWrite(int test_state) { 302 | // PC should be at address 303 | 304 | if (`test_state == test_state) { 305 | bpWriteSuccess = 1; 306 | } 307 | printf("Breakpoint on write: %d\n", bpWriteSuccess); 308 | } 309 | 310 | 311 | // evaluate test 312 | FUNC void EvalSuccess(void) { 313 | char success; 314 | 315 | success = testSuccess && 316 | bpExecSuccess && bpReadSuccess && bpWriteSuccess && 317 | regReadSuccess && regWriteSuccess && 318 | memReadSuccess && memWriteSuccess; 319 | 320 | exec("LOG >.\\test_results.txt"); 321 | 322 | // print test results to log file 323 | if (success) { 324 | printf("Test passed!\n"); 325 | } else { 326 | printf("Test failed!\n"); 327 | } 328 | 329 | printf("\nIndividual test results:\n"); 330 | 331 | printf("Execution breakpoint: "); 332 | if (bpExecSuccess) { 333 | printf("passed\n"); 334 | } else { 335 | printf("failed\n"); 336 | } 337 | 338 | printf("Breakpoint on read: "); 339 | if (bpReadSuccess) { 340 | printf("passed\n"); 341 | } else { 342 | printf("failed\n"); 343 | } 344 | 345 | printf("Breakpoint on write: "); 346 | if (bpWriteSuccess) { 347 | printf("passed\n"); 348 | } else { 349 | printf("failed\n"); 350 | } 351 | 352 | printf("Register read: "); 353 | if (regReadSuccess) { 354 | printf("passed\n"); 355 | } else { 356 | printf("failed\n"); 357 | } 358 | 359 | printf("Register write: "); 360 | if (regWriteSuccess) { 361 | printf("passed\n"); 362 | } else { 363 | printf("failed\n"); 364 | } 365 | 366 | printf("Memory read: "); 367 | if (memReadSuccess) { 368 | printf("passed\n"); 369 | } else { 370 | printf("failed\n"); 371 | } 372 | 373 | printf("Memory write: "); 374 | if (memWriteSuccess) { 375 | printf("passed\n"); 376 | } else { 377 | printf("failed\n"); 378 | } 379 | 380 | printf("Control flow: "); 381 | if (testSuccess) { 382 | printf("passed\n"); 383 | } else { 384 | printf("failed\n"); 385 | } 386 | 387 | exec("LOG OFF"); 388 | } 389 | 390 | 391 | LOG >.\\test.log // start logging 392 | 393 | RegReadWrite(); // check register read/write 394 | 395 | BK * // remove all existing breakpoints 396 | BS \test.c\43, 9 // set execution breakpoint (hit count=9) 397 | G // run to break point 398 | CheckBpExec(\test.c\43); // check execution breakpoint 399 | 400 | BK * // remove all existing breakpoints 401 | BS READ test_success // set a read access breakpoint 402 | G // run to break point 403 | CheckBpRead(11); // check breakpoint on read 404 | 405 | BK * // remove all existing breakpoints 406 | BS WRITE test_success // set a write access breakpoint 407 | G // run to break point 408 | CheckBpWrite(12); // check breakpoint on write 409 | 410 | BK * // remove all existing breakpoints 411 | G,\test.c\61 // run until line 61 412 | MemWrite(&test_array1[0]); // test memory write 413 | 414 | G,\test.c\69 // run until line 69 415 | memWriteSuccess = `mem_rw_success; // application memory test result 416 | MemRead(&test_array2[0]); // test memory read 417 | 418 | T 3 // step 3 times 419 | 420 | `test_state -= 16; // modify 'test_state' application variable 421 | 422 | G,\test.c\88 // run until line 88 423 | 424 | testSuccess = `test_success; // read 'test_success' application variable 425 | 426 | LOG OFF // stop logging 427 | 428 | EvalSuccess(); // evaluate test results 429 | 430 | EXIT // exit debug mode 431 | -------------------------------------------------------------------------------- /CMSIS_DAP/CMSIS/Core/Include/mpu_armv7.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * @file mpu_armv7.h 3 | * @brief CMSIS MPU API for Armv7-M MPU 4 | * @version V5.1.1 5 | * @date 10. February 2020 6 | ******************************************************************************/ 7 | /* 8 | * Copyright (c) 2017-2020 Arm Limited. All rights reserved. 9 | * 10 | * SPDX-License-Identifier: Apache-2.0 11 | * 12 | * Licensed under the Apache License, Version 2.0 (the License); you may 13 | * not use this file except in compliance with the License. 14 | * You may obtain a copy of the License at 15 | * 16 | * www.apache.org/licenses/LICENSE-2.0 17 | * 18 | * Unless required by applicable law or agreed to in writing, software 19 | * distributed under the License is distributed on an AS IS BASIS, WITHOUT 20 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 21 | * See the License for the specific language governing permissions and 22 | * limitations under the License. 23 | */ 24 | 25 | #if defined ( __ICCARM__ ) 26 | #pragma system_include /* treat file as system include file for MISRA check */ 27 | #elif defined (__clang__) 28 | #pragma clang system_header /* treat file as system include file */ 29 | #endif 30 | 31 | #ifndef ARM_MPU_ARMV7_H 32 | #define ARM_MPU_ARMV7_H 33 | 34 | #define ARM_MPU_REGION_SIZE_32B ((uint8_t)0x04U) ///!< MPU Region Size 32 Bytes 35 | #define ARM_MPU_REGION_SIZE_64B ((uint8_t)0x05U) ///!< MPU Region Size 64 Bytes 36 | #define ARM_MPU_REGION_SIZE_128B ((uint8_t)0x06U) ///!< MPU Region Size 128 Bytes 37 | #define ARM_MPU_REGION_SIZE_256B ((uint8_t)0x07U) ///!< MPU Region Size 256 Bytes 38 | #define ARM_MPU_REGION_SIZE_512B ((uint8_t)0x08U) ///!< MPU Region Size 512 Bytes 39 | #define ARM_MPU_REGION_SIZE_1KB ((uint8_t)0x09U) ///!< MPU Region Size 1 KByte 40 | #define ARM_MPU_REGION_SIZE_2KB ((uint8_t)0x0AU) ///!< MPU Region Size 2 KBytes 41 | #define ARM_MPU_REGION_SIZE_4KB ((uint8_t)0x0BU) ///!< MPU Region Size 4 KBytes 42 | #define ARM_MPU_REGION_SIZE_8KB ((uint8_t)0x0CU) ///!< MPU Region Size 8 KBytes 43 | #define ARM_MPU_REGION_SIZE_16KB ((uint8_t)0x0DU) ///!< MPU Region Size 16 KBytes 44 | #define ARM_MPU_REGION_SIZE_32KB ((uint8_t)0x0EU) ///!< MPU Region Size 32 KBytes 45 | #define ARM_MPU_REGION_SIZE_64KB ((uint8_t)0x0FU) ///!< MPU Region Size 64 KBytes 46 | #define ARM_MPU_REGION_SIZE_128KB ((uint8_t)0x10U) ///!< MPU Region Size 128 KBytes 47 | #define ARM_MPU_REGION_SIZE_256KB ((uint8_t)0x11U) ///!< MPU Region Size 256 KBytes 48 | #define ARM_MPU_REGION_SIZE_512KB ((uint8_t)0x12U) ///!< MPU Region Size 512 KBytes 49 | #define ARM_MPU_REGION_SIZE_1MB ((uint8_t)0x13U) ///!< MPU Region Size 1 MByte 50 | #define ARM_MPU_REGION_SIZE_2MB ((uint8_t)0x14U) ///!< MPU Region Size 2 MBytes 51 | #define ARM_MPU_REGION_SIZE_4MB ((uint8_t)0x15U) ///!< MPU Region Size 4 MBytes 52 | #define ARM_MPU_REGION_SIZE_8MB ((uint8_t)0x16U) ///!< MPU Region Size 8 MBytes 53 | #define ARM_MPU_REGION_SIZE_16MB ((uint8_t)0x17U) ///!< MPU Region Size 16 MBytes 54 | #define ARM_MPU_REGION_SIZE_32MB ((uint8_t)0x18U) ///!< MPU Region Size 32 MBytes 55 | #define ARM_MPU_REGION_SIZE_64MB ((uint8_t)0x19U) ///!< MPU Region Size 64 MBytes 56 | #define ARM_MPU_REGION_SIZE_128MB ((uint8_t)0x1AU) ///!< MPU Region Size 128 MBytes 57 | #define ARM_MPU_REGION_SIZE_256MB ((uint8_t)0x1BU) ///!< MPU Region Size 256 MBytes 58 | #define ARM_MPU_REGION_SIZE_512MB ((uint8_t)0x1CU) ///!< MPU Region Size 512 MBytes 59 | #define ARM_MPU_REGION_SIZE_1GB ((uint8_t)0x1DU) ///!< MPU Region Size 1 GByte 60 | #define ARM_MPU_REGION_SIZE_2GB ((uint8_t)0x1EU) ///!< MPU Region Size 2 GBytes 61 | #define ARM_MPU_REGION_SIZE_4GB ((uint8_t)0x1FU) ///!< MPU Region Size 4 GBytes 62 | 63 | #define ARM_MPU_AP_NONE 0U ///!< MPU Access Permission no access 64 | #define ARM_MPU_AP_PRIV 1U ///!< MPU Access Permission privileged access only 65 | #define ARM_MPU_AP_URO 2U ///!< MPU Access Permission unprivileged access read-only 66 | #define ARM_MPU_AP_FULL 3U ///!< MPU Access Permission full access 67 | #define ARM_MPU_AP_PRO 5U ///!< MPU Access Permission privileged access read-only 68 | #define ARM_MPU_AP_RO 6U ///!< MPU Access Permission read-only access 69 | 70 | /** MPU Region Base Address Register Value 71 | * 72 | * \param Region The region to be configured, number 0 to 15. 73 | * \param BaseAddress The base address for the region. 74 | */ 75 | #define ARM_MPU_RBAR(Region, BaseAddress) \ 76 | (((BaseAddress) & MPU_RBAR_ADDR_Msk) | \ 77 | ((Region) & MPU_RBAR_REGION_Msk) | \ 78 | (MPU_RBAR_VALID_Msk)) 79 | 80 | /** 81 | * MPU Memory Access Attributes 82 | * 83 | * \param TypeExtField Type extension field, allows you to configure memory access type, for example strongly ordered, peripheral. 84 | * \param IsShareable Region is shareable between multiple bus masters. 85 | * \param IsCacheable Region is cacheable, i.e. its value may be kept in cache. 86 | * \param IsBufferable Region is bufferable, i.e. using write-back caching. Cacheable but non-bufferable regions use write-through policy. 87 | */ 88 | #define ARM_MPU_ACCESS_(TypeExtField, IsShareable, IsCacheable, IsBufferable) \ 89 | ((((TypeExtField) << MPU_RASR_TEX_Pos) & MPU_RASR_TEX_Msk) | \ 90 | (((IsShareable) << MPU_RASR_S_Pos) & MPU_RASR_S_Msk) | \ 91 | (((IsCacheable) << MPU_RASR_C_Pos) & MPU_RASR_C_Msk) | \ 92 | (((IsBufferable) << MPU_RASR_B_Pos) & MPU_RASR_B_Msk)) 93 | 94 | /** 95 | * MPU Region Attribute and Size Register Value 96 | * 97 | * \param DisableExec Instruction access disable bit, 1= disable instruction fetches. 98 | * \param AccessPermission Data access permissions, allows you to configure read/write access for User and Privileged mode. 99 | * \param AccessAttributes Memory access attribution, see \ref ARM_MPU_ACCESS_. 100 | * \param SubRegionDisable Sub-region disable field. 101 | * \param Size Region size of the region to be configured, for example 4K, 8K. 102 | */ 103 | #define ARM_MPU_RASR_EX(DisableExec, AccessPermission, AccessAttributes, SubRegionDisable, Size) \ 104 | ((((DisableExec) << MPU_RASR_XN_Pos) & MPU_RASR_XN_Msk) | \ 105 | (((AccessPermission) << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk) | \ 106 | (((AccessAttributes) & (MPU_RASR_TEX_Msk | MPU_RASR_S_Msk | MPU_RASR_C_Msk | MPU_RASR_B_Msk))) | \ 107 | (((SubRegionDisable) << MPU_RASR_SRD_Pos) & MPU_RASR_SRD_Msk) | \ 108 | (((Size) << MPU_RASR_SIZE_Pos) & MPU_RASR_SIZE_Msk) | \ 109 | (((MPU_RASR_ENABLE_Msk)))) 110 | 111 | /** 112 | * MPU Region Attribute and Size Register Value 113 | * 114 | * \param DisableExec Instruction access disable bit, 1= disable instruction fetches. 115 | * \param AccessPermission Data access permissions, allows you to configure read/write access for User and Privileged mode. 116 | * \param TypeExtField Type extension field, allows you to configure memory access type, for example strongly ordered, peripheral. 117 | * \param IsShareable Region is shareable between multiple bus masters. 118 | * \param IsCacheable Region is cacheable, i.e. its value may be kept in cache. 119 | * \param IsBufferable Region is bufferable, i.e. using write-back caching. Cacheable but non-bufferable regions use write-through policy. 120 | * \param SubRegionDisable Sub-region disable field. 121 | * \param Size Region size of the region to be configured, for example 4K, 8K. 122 | */ 123 | #define ARM_MPU_RASR(DisableExec, AccessPermission, TypeExtField, IsShareable, IsCacheable, IsBufferable, SubRegionDisable, Size) \ 124 | ARM_MPU_RASR_EX(DisableExec, AccessPermission, ARM_MPU_ACCESS_(TypeExtField, IsShareable, IsCacheable, IsBufferable), SubRegionDisable, Size) 125 | 126 | /** 127 | * MPU Memory Access Attribute for strongly ordered memory. 128 | * - TEX: 000b 129 | * - Shareable 130 | * - Non-cacheable 131 | * - Non-bufferable 132 | */ 133 | #define ARM_MPU_ACCESS_ORDERED ARM_MPU_ACCESS_(0U, 1U, 0U, 0U) 134 | 135 | /** 136 | * MPU Memory Access Attribute for device memory. 137 | * - TEX: 000b (if shareable) or 010b (if non-shareable) 138 | * - Shareable or non-shareable 139 | * - Non-cacheable 140 | * - Bufferable (if shareable) or non-bufferable (if non-shareable) 141 | * 142 | * \param IsShareable Configures the device memory as shareable or non-shareable. 143 | */ 144 | #define ARM_MPU_ACCESS_DEVICE(IsShareable) ((IsShareable) ? ARM_MPU_ACCESS_(0U, 1U, 0U, 1U) : ARM_MPU_ACCESS_(2U, 0U, 0U, 0U)) 145 | 146 | /** 147 | * MPU Memory Access Attribute for normal memory. 148 | * - TEX: 1BBb (reflecting outer cacheability rules) 149 | * - Shareable or non-shareable 150 | * - Cacheable or non-cacheable (reflecting inner cacheability rules) 151 | * - Bufferable or non-bufferable (reflecting inner cacheability rules) 152 | * 153 | * \param OuterCp Configures the outer cache policy. 154 | * \param InnerCp Configures the inner cache policy. 155 | * \param IsShareable Configures the memory as shareable or non-shareable. 156 | */ 157 | #define ARM_MPU_ACCESS_NORMAL(OuterCp, InnerCp, IsShareable) ARM_MPU_ACCESS_((4U | (OuterCp)), IsShareable, ((InnerCp) >> 1U), ((InnerCp) & 1U)) 158 | 159 | /** 160 | * MPU Memory Access Attribute non-cacheable policy. 161 | */ 162 | #define ARM_MPU_CACHEP_NOCACHE 0U 163 | 164 | /** 165 | * MPU Memory Access Attribute write-back, write and read allocate policy. 166 | */ 167 | #define ARM_MPU_CACHEP_WB_WRA 1U 168 | 169 | /** 170 | * MPU Memory Access Attribute write-through, no write allocate policy. 171 | */ 172 | #define ARM_MPU_CACHEP_WT_NWA 2U 173 | 174 | /** 175 | * MPU Memory Access Attribute write-back, no write allocate policy. 176 | */ 177 | #define ARM_MPU_CACHEP_WB_NWA 3U 178 | 179 | 180 | /** 181 | * Struct for a single MPU Region 182 | */ 183 | typedef struct { 184 | uint32_t RBAR; //!< The region base address register value (RBAR) 185 | uint32_t RASR; //!< The region attribute and size register value (RASR) \ref MPU_RASR 186 | } ARM_MPU_Region_t; 187 | 188 | /** Enable the MPU. 189 | * \param MPU_Control Default access permissions for unconfigured regions. 190 | */ 191 | __STATIC_INLINE void ARM_MPU_Enable(uint32_t MPU_Control) 192 | { 193 | __DMB(); 194 | MPU->CTRL = MPU_Control | MPU_CTRL_ENABLE_Msk; 195 | #ifdef SCB_SHCSR_MEMFAULTENA_Msk 196 | SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk; 197 | #endif 198 | __DSB(); 199 | __ISB(); 200 | } 201 | 202 | /** Disable the MPU. 203 | */ 204 | __STATIC_INLINE void ARM_MPU_Disable(void) 205 | { 206 | __DMB(); 207 | #ifdef SCB_SHCSR_MEMFAULTENA_Msk 208 | SCB->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk; 209 | #endif 210 | MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk; 211 | __DSB(); 212 | __ISB(); 213 | } 214 | 215 | /** Clear and disable the given MPU region. 216 | * \param rnr Region number to be cleared. 217 | */ 218 | __STATIC_INLINE void ARM_MPU_ClrRegion(uint32_t rnr) 219 | { 220 | MPU->RNR = rnr; 221 | MPU->RASR = 0U; 222 | } 223 | 224 | /** Configure an MPU region. 225 | * \param rbar Value for RBAR register. 226 | * \param rsar Value for RSAR register. 227 | */ 228 | __STATIC_INLINE void ARM_MPU_SetRegion(uint32_t rbar, uint32_t rasr) 229 | { 230 | MPU->RBAR = rbar; 231 | MPU->RASR = rasr; 232 | } 233 | 234 | /** Configure the given MPU region. 235 | * \param rnr Region number to be configured. 236 | * \param rbar Value for RBAR register. 237 | * \param rsar Value for RSAR register. 238 | */ 239 | __STATIC_INLINE void ARM_MPU_SetRegionEx(uint32_t rnr, uint32_t rbar, uint32_t rasr) 240 | { 241 | MPU->RNR = rnr; 242 | MPU->RBAR = rbar; 243 | MPU->RASR = rasr; 244 | } 245 | 246 | /** Memcopy with strictly ordered memory access, e.g. for register targets. 247 | * \param dst Destination data is copied to. 248 | * \param src Source data is copied from. 249 | * \param len Amount of data words to be copied. 250 | */ 251 | __STATIC_INLINE void ARM_MPU_OrderedMemcpy(volatile uint32_t* dst, const uint32_t* __RESTRICT src, uint32_t len) 252 | { 253 | uint32_t i; 254 | for (i = 0U; i < len; ++i) 255 | { 256 | dst[i] = src[i]; 257 | } 258 | } 259 | 260 | /** Load the given number of MPU regions from a table. 261 | * \param table Pointer to the MPU configuration table. 262 | * \param cnt Amount of regions to be configured. 263 | */ 264 | __STATIC_INLINE void ARM_MPU_Load(ARM_MPU_Region_t const* table, uint32_t cnt) 265 | { 266 | const uint32_t rowWordSize = sizeof(ARM_MPU_Region_t)/4U; 267 | while (cnt > MPU_TYPE_RALIASES) { 268 | ARM_MPU_OrderedMemcpy(&(MPU->RBAR), &(table->RBAR), MPU_TYPE_RALIASES*rowWordSize); 269 | table += MPU_TYPE_RALIASES; 270 | cnt -= MPU_TYPE_RALIASES; 271 | } 272 | ARM_MPU_OrderedMemcpy(&(MPU->RBAR), &(table->RBAR), cnt*rowWordSize); 273 | } 274 | 275 | #endif 276 | -------------------------------------------------------------------------------- /CMSIS_DAP/CMSIS/Core/Include/mpu_armv8.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * @file mpu_armv8.h 3 | * @brief CMSIS MPU API for Armv8-M and Armv8.1-M MPU 4 | * @version V5.1.2 5 | * @date 10. February 2020 6 | ******************************************************************************/ 7 | /* 8 | * Copyright (c) 2017-2020 Arm Limited. All rights reserved. 9 | * 10 | * SPDX-License-Identifier: Apache-2.0 11 | * 12 | * Licensed under the Apache License, Version 2.0 (the License); you may 13 | * not use this file except in compliance with the License. 14 | * You may obtain a copy of the License at 15 | * 16 | * www.apache.org/licenses/LICENSE-2.0 17 | * 18 | * Unless required by applicable law or agreed to in writing, software 19 | * distributed under the License is distributed on an AS IS BASIS, WITHOUT 20 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 21 | * See the License for the specific language governing permissions and 22 | * limitations under the License. 23 | */ 24 | 25 | #if defined ( __ICCARM__ ) 26 | #pragma system_include /* treat file as system include file for MISRA check */ 27 | #elif defined (__clang__) 28 | #pragma clang system_header /* treat file as system include file */ 29 | #endif 30 | 31 | #ifndef ARM_MPU_ARMV8_H 32 | #define ARM_MPU_ARMV8_H 33 | 34 | /** \brief Attribute for device memory (outer only) */ 35 | #define ARM_MPU_ATTR_DEVICE ( 0U ) 36 | 37 | /** \brief Attribute for non-cacheable, normal memory */ 38 | #define ARM_MPU_ATTR_NON_CACHEABLE ( 4U ) 39 | 40 | /** \brief Attribute for normal memory (outer and inner) 41 | * \param NT Non-Transient: Set to 1 for non-transient data. 42 | * \param WB Write-Back: Set to 1 to use write-back update policy. 43 | * \param RA Read Allocation: Set to 1 to use cache allocation on read miss. 44 | * \param WA Write Allocation: Set to 1 to use cache allocation on write miss. 45 | */ 46 | #define ARM_MPU_ATTR_MEMORY_(NT, WB, RA, WA) \ 47 | ((((NT) & 1U) << 3U) | (((WB) & 1U) << 2U) | (((RA) & 1U) << 1U) | ((WA) & 1U)) 48 | 49 | /** \brief Device memory type non Gathering, non Re-ordering, non Early Write Acknowledgement */ 50 | #define ARM_MPU_ATTR_DEVICE_nGnRnE (0U) 51 | 52 | /** \brief Device memory type non Gathering, non Re-ordering, Early Write Acknowledgement */ 53 | #define ARM_MPU_ATTR_DEVICE_nGnRE (1U) 54 | 55 | /** \brief Device memory type non Gathering, Re-ordering, Early Write Acknowledgement */ 56 | #define ARM_MPU_ATTR_DEVICE_nGRE (2U) 57 | 58 | /** \brief Device memory type Gathering, Re-ordering, Early Write Acknowledgement */ 59 | #define ARM_MPU_ATTR_DEVICE_GRE (3U) 60 | 61 | /** \brief Memory Attribute 62 | * \param O Outer memory attributes 63 | * \param I O == ARM_MPU_ATTR_DEVICE: Device memory attributes, else: Inner memory attributes 64 | */ 65 | #define ARM_MPU_ATTR(O, I) ((((O) & 0xFU) << 4U) | ((((O) & 0xFU) != 0U) ? ((I) & 0xFU) : (((I) & 0x3U) << 2U))) 66 | 67 | /** \brief Normal memory non-shareable */ 68 | #define ARM_MPU_SH_NON (0U) 69 | 70 | /** \brief Normal memory outer shareable */ 71 | #define ARM_MPU_SH_OUTER (2U) 72 | 73 | /** \brief Normal memory inner shareable */ 74 | #define ARM_MPU_SH_INNER (3U) 75 | 76 | /** \brief Memory access permissions 77 | * \param RO Read-Only: Set to 1 for read-only memory. 78 | * \param NP Non-Privileged: Set to 1 for non-privileged memory. 79 | */ 80 | #define ARM_MPU_AP_(RO, NP) ((((RO) & 1U) << 1U) | ((NP) & 1U)) 81 | 82 | /** \brief Region Base Address Register value 83 | * \param BASE The base address bits [31:5] of a memory region. The value is zero extended. Effective address gets 32 byte aligned. 84 | * \param SH Defines the Shareability domain for this memory region. 85 | * \param RO Read-Only: Set to 1 for a read-only memory region. 86 | * \param NP Non-Privileged: Set to 1 for a non-privileged memory region. 87 | * \oaram XN eXecute Never: Set to 1 for a non-executable memory region. 88 | */ 89 | #define ARM_MPU_RBAR(BASE, SH, RO, NP, XN) \ 90 | (((BASE) & MPU_RBAR_BASE_Msk) | \ 91 | (((SH) << MPU_RBAR_SH_Pos) & MPU_RBAR_SH_Msk) | \ 92 | ((ARM_MPU_AP_(RO, NP) << MPU_RBAR_AP_Pos) & MPU_RBAR_AP_Msk) | \ 93 | (((XN) << MPU_RBAR_XN_Pos) & MPU_RBAR_XN_Msk)) 94 | 95 | /** \brief Region Limit Address Register value 96 | * \param LIMIT The limit address bits [31:5] for this memory region. The value is one extended. 97 | * \param IDX The attribute index to be associated with this memory region. 98 | */ 99 | #define ARM_MPU_RLAR(LIMIT, IDX) \ 100 | (((LIMIT) & MPU_RLAR_LIMIT_Msk) | \ 101 | (((IDX) << MPU_RLAR_AttrIndx_Pos) & MPU_RLAR_AttrIndx_Msk) | \ 102 | (MPU_RLAR_EN_Msk)) 103 | 104 | #if defined(MPU_RLAR_PXN_Pos) 105 | 106 | /** \brief Region Limit Address Register with PXN value 107 | * \param LIMIT The limit address bits [31:5] for this memory region. The value is one extended. 108 | * \param PXN Privileged execute never. Defines whether code can be executed from this privileged region. 109 | * \param IDX The attribute index to be associated with this memory region. 110 | */ 111 | #define ARM_MPU_RLAR_PXN(LIMIT, PXN, IDX) \ 112 | (((LIMIT) & MPU_RLAR_LIMIT_Msk) | \ 113 | (((PXN) << MPU_RLAR_PXN_Pos) & MPU_RLAR_PXN_Msk) | \ 114 | (((IDX) << MPU_RLAR_AttrIndx_Pos) & MPU_RLAR_AttrIndx_Msk) | \ 115 | (MPU_RLAR_EN_Msk)) 116 | 117 | #endif 118 | 119 | /** 120 | * Struct for a single MPU Region 121 | */ 122 | typedef struct { 123 | uint32_t RBAR; /*!< Region Base Address Register value */ 124 | uint32_t RLAR; /*!< Region Limit Address Register value */ 125 | } ARM_MPU_Region_t; 126 | 127 | /** Enable the MPU. 128 | * \param MPU_Control Default access permissions for unconfigured regions. 129 | */ 130 | __STATIC_INLINE void ARM_MPU_Enable(uint32_t MPU_Control) 131 | { 132 | __DMB(); 133 | MPU->CTRL = MPU_Control | MPU_CTRL_ENABLE_Msk; 134 | #ifdef SCB_SHCSR_MEMFAULTENA_Msk 135 | SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk; 136 | #endif 137 | __DSB(); 138 | __ISB(); 139 | } 140 | 141 | /** Disable the MPU. 142 | */ 143 | __STATIC_INLINE void ARM_MPU_Disable(void) 144 | { 145 | __DMB(); 146 | #ifdef SCB_SHCSR_MEMFAULTENA_Msk 147 | SCB->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk; 148 | #endif 149 | MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk; 150 | __DSB(); 151 | __ISB(); 152 | } 153 | 154 | #ifdef MPU_NS 155 | /** Enable the Non-secure MPU. 156 | * \param MPU_Control Default access permissions for unconfigured regions. 157 | */ 158 | __STATIC_INLINE void ARM_MPU_Enable_NS(uint32_t MPU_Control) 159 | { 160 | __DMB(); 161 | MPU_NS->CTRL = MPU_Control | MPU_CTRL_ENABLE_Msk; 162 | #ifdef SCB_SHCSR_MEMFAULTENA_Msk 163 | SCB_NS->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk; 164 | #endif 165 | __DSB(); 166 | __ISB(); 167 | } 168 | 169 | /** Disable the Non-secure MPU. 170 | */ 171 | __STATIC_INLINE void ARM_MPU_Disable_NS(void) 172 | { 173 | __DMB(); 174 | #ifdef SCB_SHCSR_MEMFAULTENA_Msk 175 | SCB_NS->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk; 176 | #endif 177 | MPU_NS->CTRL &= ~MPU_CTRL_ENABLE_Msk; 178 | __DSB(); 179 | __ISB(); 180 | } 181 | #endif 182 | 183 | /** Set the memory attribute encoding to the given MPU. 184 | * \param mpu Pointer to the MPU to be configured. 185 | * \param idx The attribute index to be set [0-7] 186 | * \param attr The attribute value to be set. 187 | */ 188 | __STATIC_INLINE void ARM_MPU_SetMemAttrEx(MPU_Type* mpu, uint8_t idx, uint8_t attr) 189 | { 190 | const uint8_t reg = idx / 4U; 191 | const uint32_t pos = ((idx % 4U) * 8U); 192 | const uint32_t mask = 0xFFU << pos; 193 | 194 | if (reg >= (sizeof(mpu->MAIR) / sizeof(mpu->MAIR[0]))) { 195 | return; // invalid index 196 | } 197 | 198 | mpu->MAIR[reg] = ((mpu->MAIR[reg] & ~mask) | ((attr << pos) & mask)); 199 | } 200 | 201 | /** Set the memory attribute encoding. 202 | * \param idx The attribute index to be set [0-7] 203 | * \param attr The attribute value to be set. 204 | */ 205 | __STATIC_INLINE void ARM_MPU_SetMemAttr(uint8_t idx, uint8_t attr) 206 | { 207 | ARM_MPU_SetMemAttrEx(MPU, idx, attr); 208 | } 209 | 210 | #ifdef MPU_NS 211 | /** Set the memory attribute encoding to the Non-secure MPU. 212 | * \param idx The attribute index to be set [0-7] 213 | * \param attr The attribute value to be set. 214 | */ 215 | __STATIC_INLINE void ARM_MPU_SetMemAttr_NS(uint8_t idx, uint8_t attr) 216 | { 217 | ARM_MPU_SetMemAttrEx(MPU_NS, idx, attr); 218 | } 219 | #endif 220 | 221 | /** Clear and disable the given MPU region of the given MPU. 222 | * \param mpu Pointer to MPU to be used. 223 | * \param rnr Region number to be cleared. 224 | */ 225 | __STATIC_INLINE void ARM_MPU_ClrRegionEx(MPU_Type* mpu, uint32_t rnr) 226 | { 227 | mpu->RNR = rnr; 228 | mpu->RLAR = 0U; 229 | } 230 | 231 | /** Clear and disable the given MPU region. 232 | * \param rnr Region number to be cleared. 233 | */ 234 | __STATIC_INLINE void ARM_MPU_ClrRegion(uint32_t rnr) 235 | { 236 | ARM_MPU_ClrRegionEx(MPU, rnr); 237 | } 238 | 239 | #ifdef MPU_NS 240 | /** Clear and disable the given Non-secure MPU region. 241 | * \param rnr Region number to be cleared. 242 | */ 243 | __STATIC_INLINE void ARM_MPU_ClrRegion_NS(uint32_t rnr) 244 | { 245 | ARM_MPU_ClrRegionEx(MPU_NS, rnr); 246 | } 247 | #endif 248 | 249 | /** Configure the given MPU region of the given MPU. 250 | * \param mpu Pointer to MPU to be used. 251 | * \param rnr Region number to be configured. 252 | * \param rbar Value for RBAR register. 253 | * \param rlar Value for RLAR register. 254 | */ 255 | __STATIC_INLINE void ARM_MPU_SetRegionEx(MPU_Type* mpu, uint32_t rnr, uint32_t rbar, uint32_t rlar) 256 | { 257 | mpu->RNR = rnr; 258 | mpu->RBAR = rbar; 259 | mpu->RLAR = rlar; 260 | } 261 | 262 | /** Configure the given MPU region. 263 | * \param rnr Region number to be configured. 264 | * \param rbar Value for RBAR register. 265 | * \param rlar Value for RLAR register. 266 | */ 267 | __STATIC_INLINE void ARM_MPU_SetRegion(uint32_t rnr, uint32_t rbar, uint32_t rlar) 268 | { 269 | ARM_MPU_SetRegionEx(MPU, rnr, rbar, rlar); 270 | } 271 | 272 | #ifdef MPU_NS 273 | /** Configure the given Non-secure MPU region. 274 | * \param rnr Region number to be configured. 275 | * \param rbar Value for RBAR register. 276 | * \param rlar Value for RLAR register. 277 | */ 278 | __STATIC_INLINE void ARM_MPU_SetRegion_NS(uint32_t rnr, uint32_t rbar, uint32_t rlar) 279 | { 280 | ARM_MPU_SetRegionEx(MPU_NS, rnr, rbar, rlar); 281 | } 282 | #endif 283 | 284 | /** Memcopy with strictly ordered memory access, e.g. for register targets. 285 | * \param dst Destination data is copied to. 286 | * \param src Source data is copied from. 287 | * \param len Amount of data words to be copied. 288 | */ 289 | __STATIC_INLINE void ARM_MPU_OrderedMemcpy(volatile uint32_t* dst, const uint32_t* __RESTRICT src, uint32_t len) 290 | { 291 | uint32_t i; 292 | for (i = 0U; i < len; ++i) 293 | { 294 | dst[i] = src[i]; 295 | } 296 | } 297 | 298 | /** Load the given number of MPU regions from a table to the given MPU. 299 | * \param mpu Pointer to the MPU registers to be used. 300 | * \param rnr First region number to be configured. 301 | * \param table Pointer to the MPU configuration table. 302 | * \param cnt Amount of regions to be configured. 303 | */ 304 | __STATIC_INLINE void ARM_MPU_LoadEx(MPU_Type* mpu, uint32_t rnr, ARM_MPU_Region_t const* table, uint32_t cnt) 305 | { 306 | const uint32_t rowWordSize = sizeof(ARM_MPU_Region_t)/4U; 307 | if (cnt == 1U) { 308 | mpu->RNR = rnr; 309 | ARM_MPU_OrderedMemcpy(&(mpu->RBAR), &(table->RBAR), rowWordSize); 310 | } else { 311 | uint32_t rnrBase = rnr & ~(MPU_TYPE_RALIASES-1U); 312 | uint32_t rnrOffset = rnr % MPU_TYPE_RALIASES; 313 | 314 | mpu->RNR = rnrBase; 315 | while ((rnrOffset + cnt) > MPU_TYPE_RALIASES) { 316 | uint32_t c = MPU_TYPE_RALIASES - rnrOffset; 317 | ARM_MPU_OrderedMemcpy(&(mpu->RBAR)+(rnrOffset*2U), &(table->RBAR), c*rowWordSize); 318 | table += c; 319 | cnt -= c; 320 | rnrOffset = 0U; 321 | rnrBase += MPU_TYPE_RALIASES; 322 | mpu->RNR = rnrBase; 323 | } 324 | 325 | ARM_MPU_OrderedMemcpy(&(mpu->RBAR)+(rnrOffset*2U), &(table->RBAR), cnt*rowWordSize); 326 | } 327 | } 328 | 329 | /** Load the given number of MPU regions from a table. 330 | * \param rnr First region number to be configured. 331 | * \param table Pointer to the MPU configuration table. 332 | * \param cnt Amount of regions to be configured. 333 | */ 334 | __STATIC_INLINE void ARM_MPU_Load(uint32_t rnr, ARM_MPU_Region_t const* table, uint32_t cnt) 335 | { 336 | ARM_MPU_LoadEx(MPU, rnr, table, cnt); 337 | } 338 | 339 | #ifdef MPU_NS 340 | /** Load the given number of MPU regions from a table to the Non-secure MPU. 341 | * \param rnr First region number to be configured. 342 | * \param table Pointer to the MPU configuration table. 343 | * \param cnt Amount of regions to be configured. 344 | */ 345 | __STATIC_INLINE void ARM_MPU_Load_NS(uint32_t rnr, ARM_MPU_Region_t const* table, uint32_t cnt) 346 | { 347 | ARM_MPU_LoadEx(MPU_NS, rnr, table, cnt); 348 | } 349 | #endif 350 | 351 | #endif 352 | 353 | -------------------------------------------------------------------------------- /CMSIS_DAP/CMSIS/DAP/Firmware/Include/DAP.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013-2019 ARM Limited. All rights reserved. 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the License); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an AS IS BASIS, WITHOUT 14 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * ---------------------------------------------------------------------- 19 | * 20 | * $Date: 26. November 2019 21 | * $Revision: V2.0.0 22 | * 23 | * Project: CMSIS-DAP Include 24 | * Title: DAP.h Definitions 25 | * 26 | *---------------------------------------------------------------------------*/ 27 | 28 | #ifndef __DAP_H__ 29 | #define __DAP_H__ 30 | 31 | 32 | // DAP Firmware Version 33 | #ifdef DAP_FW_V1 34 | #define DAP_FW_VER "1.2.0" 35 | #else 36 | #define DAP_FW_VER "2.0.0" 37 | #endif 38 | 39 | // DAP Command IDs 40 | #define ID_DAP_Info 0x00U 41 | #define ID_DAP_HostStatus 0x01U 42 | #define ID_DAP_Connect 0x02U 43 | #define ID_DAP_Disconnect 0x03U 44 | #define ID_DAP_TransferConfigure 0x04U 45 | #define ID_DAP_Transfer 0x05U 46 | #define ID_DAP_TransferBlock 0x06U 47 | #define ID_DAP_TransferAbort 0x07U 48 | #define ID_DAP_WriteABORT 0x08U 49 | #define ID_DAP_Delay 0x09U 50 | #define ID_DAP_ResetTarget 0x0AU 51 | #define ID_DAP_SWJ_Pins 0x10U 52 | #define ID_DAP_SWJ_Clock 0x11U 53 | #define ID_DAP_SWJ_Sequence 0x12U 54 | #define ID_DAP_SWD_Configure 0x13U 55 | #define ID_DAP_SWD_Sequence 0x1DU 56 | #define ID_DAP_JTAG_Sequence 0x14U 57 | #define ID_DAP_JTAG_Configure 0x15U 58 | #define ID_DAP_JTAG_IDCODE 0x16U 59 | #define ID_DAP_SWO_Transport 0x17U 60 | #define ID_DAP_SWO_Mode 0x18U 61 | #define ID_DAP_SWO_Baudrate 0x19U 62 | #define ID_DAP_SWO_Control 0x1AU 63 | #define ID_DAP_SWO_Status 0x1BU 64 | #define ID_DAP_SWO_ExtendedStatus 0x1EU 65 | #define ID_DAP_SWO_Data 0x1CU 66 | 67 | #define ID_DAP_QueueCommands 0x7EU 68 | #define ID_DAP_ExecuteCommands 0x7FU 69 | 70 | // DAP Vendor Command IDs 71 | #define ID_DAP_Vendor0 0x80U 72 | #define ID_DAP_Vendor1 0x81U 73 | #define ID_DAP_Vendor2 0x82U 74 | #define ID_DAP_Vendor3 0x83U 75 | #define ID_DAP_Vendor4 0x84U 76 | #define ID_DAP_Vendor5 0x85U 77 | #define ID_DAP_Vendor6 0x86U 78 | #define ID_DAP_Vendor7 0x87U 79 | #define ID_DAP_Vendor8 0x88U 80 | #define ID_DAP_Vendor9 0x89U 81 | #define ID_DAP_Vendor10 0x8AU 82 | #define ID_DAP_Vendor11 0x8BU 83 | #define ID_DAP_Vendor12 0x8CU 84 | #define ID_DAP_Vendor13 0x8DU 85 | #define ID_DAP_Vendor14 0x8EU 86 | #define ID_DAP_Vendor15 0x8FU 87 | #define ID_DAP_Vendor16 0x90U 88 | #define ID_DAP_Vendor17 0x91U 89 | #define ID_DAP_Vendor18 0x92U 90 | #define ID_DAP_Vendor19 0x93U 91 | #define ID_DAP_Vendor20 0x94U 92 | #define ID_DAP_Vendor21 0x95U 93 | #define ID_DAP_Vendor22 0x96U 94 | #define ID_DAP_Vendor23 0x97U 95 | #define ID_DAP_Vendor24 0x98U 96 | #define ID_DAP_Vendor25 0x99U 97 | #define ID_DAP_Vendor26 0x9AU 98 | #define ID_DAP_Vendor27 0x9BU 99 | #define ID_DAP_Vendor28 0x9CU 100 | #define ID_DAP_Vendor29 0x9DU 101 | #define ID_DAP_Vendor30 0x9EU 102 | #define ID_DAP_Vendor31 0x9FU 103 | 104 | #define ID_DAP_Invalid 0xFFU 105 | 106 | // DAP Status Code 107 | #define DAP_OK 0U 108 | #define DAP_ERROR 0xFFU 109 | 110 | // DAP ID 111 | #define DAP_ID_VENDOR 1U 112 | #define DAP_ID_PRODUCT 2U 113 | #define DAP_ID_SER_NUM 3U 114 | #define DAP_ID_FW_VER 4U 115 | #define DAP_ID_DEVICE_VENDOR 5U 116 | #define DAP_ID_DEVICE_NAME 6U 117 | #define DAP_ID_CAPABILITIES 0xF0U 118 | #define DAP_ID_TIMESTAMP_CLOCK 0xF1U 119 | #define DAP_ID_SWO_BUFFER_SIZE 0xFDU 120 | #define DAP_ID_PACKET_COUNT 0xFEU 121 | #define DAP_ID_PACKET_SIZE 0xFFU 122 | 123 | // DAP Host Status 124 | #define DAP_DEBUGGER_CONNECTED 0U 125 | #define DAP_TARGET_RUNNING 1U 126 | 127 | // DAP Port 128 | #define DAP_PORT_AUTODETECT 0U // Autodetect Port 129 | #define DAP_PORT_DISABLED 0U // Port Disabled (I/O pins in High-Z) 130 | #define DAP_PORT_SWD 1U // SWD Port (SWCLK, SWDIO) + nRESET 131 | #define DAP_PORT_JTAG 2U // JTAG Port (TCK, TMS, TDI, TDO, nTRST) + nRESET 132 | 133 | // DAP SWJ Pins 134 | #define DAP_SWJ_SWCLK_TCK 0 // SWCLK/TCK 135 | #define DAP_SWJ_SWDIO_TMS 1 // SWDIO/TMS 136 | #define DAP_SWJ_TDI 2 // TDI 137 | #define DAP_SWJ_TDO 3 // TDO 138 | #define DAP_SWJ_nTRST 5 // nTRST 139 | #define DAP_SWJ_nRESET 7 // nRESET 140 | 141 | // DAP Transfer Request 142 | #define DAP_TRANSFER_APnDP (1U<<0) 143 | #define DAP_TRANSFER_RnW (1U<<1) 144 | #define DAP_TRANSFER_A2 (1U<<2) 145 | #define DAP_TRANSFER_A3 (1U<<3) 146 | #define DAP_TRANSFER_MATCH_VALUE (1U<<4) 147 | #define DAP_TRANSFER_MATCH_MASK (1U<<5) 148 | #define DAP_TRANSFER_TIMESTAMP (1U<<7) 149 | 150 | // DAP Transfer Response 151 | #define DAP_TRANSFER_OK (1U<<0) 152 | #define DAP_TRANSFER_WAIT (1U<<1) 153 | #define DAP_TRANSFER_FAULT (1U<<2) 154 | #define DAP_TRANSFER_ERROR (1U<<3) 155 | #define DAP_TRANSFER_MISMATCH (1U<<4) 156 | 157 | // DAP SWO Trace Mode 158 | #define DAP_SWO_OFF 0U 159 | #define DAP_SWO_UART 1U 160 | #define DAP_SWO_MANCHESTER 2U 161 | 162 | // DAP SWO Trace Status 163 | #define DAP_SWO_CAPTURE_ACTIVE (1U<<0) 164 | #define DAP_SWO_CAPTURE_PAUSED (1U<<1) 165 | #define DAP_SWO_STREAM_ERROR (1U<<6) 166 | #define DAP_SWO_BUFFER_OVERRUN (1U<<7) 167 | 168 | 169 | // Debug Port Register Addresses 170 | #define DP_IDCODE 0x00U // IDCODE Register (SW Read only) 171 | #define DP_ABORT 0x00U // Abort Register (SW Write only) 172 | #define DP_CTRL_STAT 0x04U // Control & Status 173 | #define DP_WCR 0x04U // Wire Control Register (SW Only) 174 | #define DP_SELECT 0x08U // Select Register (JTAG R/W & SW W) 175 | #define DP_RESEND 0x08U // Resend (SW Read Only) 176 | #define DP_RDBUFF 0x0CU // Read Buffer (Read Only) 177 | 178 | // JTAG IR Codes 179 | #define JTAG_ABORT 0x08U 180 | #define JTAG_DPACC 0x0AU 181 | #define JTAG_APACC 0x0BU 182 | #define JTAG_IDCODE 0x0EU 183 | #define JTAG_BYPASS 0x0FU 184 | 185 | // JTAG Sequence Info 186 | #define JTAG_SEQUENCE_TCK 0x3FU // TCK count 187 | #define JTAG_SEQUENCE_TMS 0x40U // TMS value 188 | #define JTAG_SEQUENCE_TDO 0x80U // TDO capture 189 | 190 | // SWD Sequence Info 191 | #define SWD_SEQUENCE_CLK 0x3FU // SWCLK count 192 | #define SWD_SEQUENCE_DIN 0x80U // SWDIO capture 193 | 194 | 195 | #include 196 | #include 197 | #include "cmsis_compiler.h" 198 | 199 | // DAP Data structure 200 | typedef struct { 201 | uint8_t debug_port; // Debug Port 202 | uint8_t fast_clock; // Fast Clock Flag 203 | uint8_t padding[2]; 204 | uint32_t clock_delay; // Clock Delay 205 | uint32_t timestamp; // Last captured Timestamp 206 | struct { // Transfer Configuration 207 | uint8_t idle_cycles; // Idle cycles after transfer 208 | uint8_t padding[3]; 209 | uint16_t retry_count; // Number of retries after WAIT response 210 | uint16_t match_retry; // Number of retries if read value does not match 211 | uint32_t match_mask; // Match Mask 212 | } transfer; 213 | #if (DAP_SWD != 0) 214 | struct { // SWD Configuration 215 | uint8_t turnaround; // Turnaround period 216 | uint8_t data_phase; // Always generate Data Phase 217 | } swd_conf; 218 | #endif 219 | #if (DAP_JTAG != 0) 220 | struct { // JTAG Device Chain 221 | uint8_t count; // Number of devices 222 | uint8_t index; // Device index (device at TDO has index 0) 223 | #if (DAP_JTAG_DEV_CNT != 0) 224 | uint8_t ir_length[DAP_JTAG_DEV_CNT]; // IR Length in bits 225 | uint16_t ir_before[DAP_JTAG_DEV_CNT]; // Bits before IR 226 | uint16_t ir_after [DAP_JTAG_DEV_CNT]; // Bits after IR 227 | #endif 228 | } jtag_dev; 229 | #endif 230 | } DAP_Data_t; 231 | 232 | extern DAP_Data_t DAP_Data; // DAP Data 233 | extern volatile uint8_t DAP_TransferAbort; // Transfer Abort Flag 234 | 235 | 236 | #ifdef __cplusplus 237 | extern "C" 238 | { 239 | #endif 240 | 241 | // Functions 242 | extern void SWJ_Sequence (uint32_t count, const uint8_t *data); 243 | extern void SWD_Sequence (uint32_t info, const uint8_t *swdo, uint8_t *swdi); 244 | extern void JTAG_Sequence (uint32_t info, const uint8_t *tdi, uint8_t *tdo); 245 | extern void JTAG_IR (uint32_t ir); 246 | extern uint32_t JTAG_ReadIDCode (void); 247 | extern void JTAG_WriteAbort (uint32_t data); 248 | extern uint8_t JTAG_Transfer (uint32_t request, uint32_t *data); 249 | extern uint8_t SWD_Transfer (uint32_t request, uint32_t *data); 250 | 251 | extern void Delayms (uint32_t delay); 252 | 253 | extern uint32_t SWO_Transport (const uint8_t *request, uint8_t *response); 254 | extern uint32_t SWO_Mode (const uint8_t *request, uint8_t *response); 255 | extern uint32_t SWO_Baudrate (const uint8_t *request, uint8_t *response); 256 | extern uint32_t SWO_Control (const uint8_t *request, uint8_t *response); 257 | extern uint32_t SWO_Status (uint8_t *response); 258 | extern uint32_t SWO_ExtendedStatus (const uint8_t *request, uint8_t *response); 259 | extern uint32_t SWO_Data (const uint8_t *request, uint8_t *response); 260 | 261 | extern void SWO_QueueTransfer (uint8_t *buf, uint32_t num); 262 | extern void SWO_AbortTransfer (void); 263 | extern void SWO_TransferComplete (void); 264 | 265 | extern uint32_t UART_SWO_Mode (uint32_t enable); 266 | extern uint32_t UART_SWO_Baudrate (uint32_t baudrate); 267 | extern uint32_t UART_SWO_Control (uint32_t active); 268 | extern void UART_SWO_Capture (uint8_t *buf, uint32_t num); 269 | extern uint32_t UART_SWO_GetCount (void); 270 | 271 | extern uint32_t Manchester_SWO_Mode (uint32_t enable); 272 | extern uint32_t Manchester_SWO_Baudrate (uint32_t baudrate); 273 | extern uint32_t Manchester_SWO_Control (uint32_t active); 274 | extern void Manchester_SWO_Capture (uint8_t *buf, uint32_t num); 275 | extern uint32_t Manchester_SWO_GetCount (void); 276 | 277 | extern uint32_t DAP_ProcessVendorCommand (const uint8_t *request, uint8_t *response); 278 | extern uint32_t DAP_ProcessCommand (const uint8_t *request, uint8_t *response); 279 | extern uint32_t DAP_ExecuteCommand (const uint8_t *request, uint8_t *response); 280 | 281 | extern void DAP_Setup (void); 282 | 283 | // Configurable delay for clock generation 284 | #ifndef DELAY_SLOW_CYCLES 285 | #define DELAY_SLOW_CYCLES 3U // Number of cycles for one iteration 286 | #endif 287 | #if defined(__CC_ARM) 288 | __STATIC_FORCEINLINE void PIN_DELAY_SLOW (uint32_t delay) { 289 | uint32_t count = delay; 290 | while (--count); 291 | } 292 | #else 293 | __STATIC_FORCEINLINE void PIN_DELAY_SLOW (uint32_t delay) { 294 | __ASM volatile ( 295 | ".syntax unified\n" 296 | "0:\n\t" 297 | "subs %0,%0,#1\n\t" 298 | "bne 0b\n" 299 | : "+l" (delay) : : "cc" 300 | ); 301 | } 302 | #endif 303 | 304 | // Fixed delay for fast clock generation 305 | #ifndef DELAY_FAST_CYCLES 306 | #define DELAY_FAST_CYCLES 0U // Number of cycles: 0..3 307 | #endif 308 | __STATIC_FORCEINLINE void PIN_DELAY_FAST (void) { 309 | #if (DELAY_FAST_CYCLES >= 1U) 310 | __NOP(); 311 | #endif 312 | #if (DELAY_FAST_CYCLES >= 2U) 313 | __NOP(); 314 | #endif 315 | #if (DELAY_FAST_CYCLES >= 3U) 316 | __NOP(); 317 | #endif 318 | } 319 | 320 | #ifdef __cplusplus 321 | } 322 | #endif 323 | 324 | 325 | #endif /* __DAP_H__ */ 326 | --------------------------------------------------------------------------------