{"id":22879519,"url":"https://github.com/shalabymhd/uwb_firmware","last_synced_at":"2025-05-07T00:47:37.267Z","repository":{"id":196048757,"uuid":"687037411","full_name":"shalabymhd/uwb_firmware","owner":"shalabymhd","description":"The firmware running on a ST microcontroller for interfacing with the DWM1000 UWB modules.","archived":false,"fork":false,"pushed_at":"2023-10-12T16:02:27.000Z","size":11071,"stargazers_count":4,"open_issues_count":0,"forks_count":2,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-05-07T00:47:33.952Z","etag":null,"topics":["localization","ranging","uwb"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/shalabymhd.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-09-04T13:20:22.000Z","updated_at":"2025-02-11T00:45:10.000Z","dependencies_parsed_at":"2023-09-21T05:17:34.237Z","dependency_job_id":"565211db-a540-412b-b7cd-1b1c8b6d18ae","html_url":"https://github.com/shalabymhd/uwb_firmware","commit_stats":null,"previous_names":["shalabyma/uwb_firmware","shalabymhd/uwb_firmware"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shalabymhd%2Fuwb_firmware","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shalabymhd%2Fuwb_firmware/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shalabymhd%2Fuwb_firmware/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shalabymhd%2Fuwb_firmware/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/shalabymhd","download_url":"https://codeload.github.com/shalabymhd/uwb_firmware/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252793576,"owners_count":21805055,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["localization","ranging","uwb"],"created_at":"2024-12-13T16:47:50.269Z","updated_at":"2025-05-07T00:47:37.213Z","avatar_url":"https://github.com/shalabymhd.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# UWB Module Firmware\nA nice tutorial on getting started with STM32 and Eclipse, created by Mohammed Shalaby, can be found [here](./doc/stm32_tutorial.md).\n\nHistorically, and as also covered in that tutorial, development on an STM32 chip consists of first configuring the chip according to your specific PCB in CubeMX, followed by setting up a configuration within the Eclipse IDE to build and debug the project. However, it turns out that Eclipse is simply just generating a `makefile` and running a `make` command to build the project. To upload and debug, the fundamental tool involved is actually `openocd`, and GDB is the debugger.\n\nIn this branch, we will be using all those tools directly. That is, we will build, upload, and debug the code without involving any editor, doing it all through the terminal. Then, we can use any editor we want to view and edit the code, as well as getting it to run the terminal commands for us. We will still be using CubeMX to generate the HAL code, and as it turns out, the makefile as well! \n\nThe benefits of this editor-independent approach consist of a much more fundamental understanding of what is happening, as well as the ability for each developer to use whatever IDE they want on the same code base. \n\nIf you would like to start from the absolute beginning, switch to the `blank` branch, which contains nothing other than the `config_stm32f4.ioc` file as well as this README.\n\nIn order to program and debug directly on the chip, we need to use the ST-LINK interface provided by our Discovery board. There are two ST-LINK versions that require two different sets of commands, both of which are provided in this document. In order to identify which version your board is running, I would recommend trying out both and identifying which version works, then running the commands associated with that version.\n\n## Generating the starter code with CubeMX\nAssuming you are on the `blank` branch, you will have only the following in your directory\n\n```\nuwb_firmware\n├── config_stm32f4.ioc\n├── README.md\n```\n\n1. Open the CubeMX software.\n2. Use __File \u003e Load Project...__ to load the `config_stm32f4.ioc` file.\n3. Under the __Project Manager__ tab, in the __Project__ section, you should see a field called `Toolchain / IDE`.  Here, you can choose __Makefile__!\n4. Leave everything else as-is, and click on __GENERATE CODE__.\n\nThis should populate the current directory with the following files. \n\n```\nuwb_firmware\n├── config_stm32f4.ioc\n├── config_stm32f4.xml\n├── Drivers\n│   ├── CMSIS\n│   │   ├── Device\n│   │   │   └── ST\n│   │   │       └── STM32F4xx\n│   │   │           ├── Include\n│   │   │           │   ├── stm32f405xx.h\n│   │   │           │   ├── stm32f4xx.h\n│   │   │           │   └── system_stm32f4xx.h\n│   │   │           └── Source\n│   │   │               └── Templates\n│   │   └── Include\n│   │       ├── cmsis_armcc.h\n│   │       ├── cmsis_armclang.h\n│   │       ├── cmsis_compiler.h\n│   │       ├── cmsis_gcc.h\n│   │       ├── cmsis_iccarm.h\n│   │       ├── cmsis_version.h\n│   │       ├── core_armv8mbl.h\n│   │       ├── core_armv8mml.h\n│   │       ├── core_cm0.h\n│   │       ├── core_cm0plus.h\n│   │       ├── core_cm1.h\n│   │       ├── core_cm23.h\n│   │       ├── core_cm33.h\n│   │       ├── core_cm3.h\n│   │       ├── core_cm4.h\n│   │       ├── core_cm7.h\n│   │       ├── core_sc000.h\n│   │       ├── core_sc300.h\n│   │       ├── mpu_armv7.h\n│   │       ├── mpu_armv8.h\n│   │       └── tz_context.h\n│   └── STM32F4xx_HAL_Driver\n│       ├── Inc\n│       │   ├── Legacy\n│       │   │   └── stm32_hal_legacy.h\n│       │   ├── stm32f4xx_hal_cortex.h\n│       │   ├── stm32f4xx_hal_def.h\n│       │   ├── stm32f4xx_hal_dma_ex.h\n│       │   ├── stm32f4xx_hal_dma.h\n│       │   ├── stm32f4xx_hal_exti.h\n│       │   ├── stm32f4xx_hal_flash_ex.h\n│       │   ├── stm32f4xx_hal_flash.h\n│       │   ├── stm32f4xx_hal_flash_ramfunc.h\n│       │   ├── stm32f4xx_hal_gpio_ex.h\n│       │   ├── stm32f4xx_hal_gpio.h\n│       │   ├── stm32f4xx_hal.h\n│       │   ├── stm32f4xx_hal_i2c_ex.h\n│       │   ├── stm32f4xx_hal_i2c.h\n│       │   ├── stm32f4xx_hal_pcd_ex.h\n│       │   ├── stm32f4xx_hal_pcd.h\n│       │   ├── stm32f4xx_hal_pwr_ex.h\n│       │   ├── stm32f4xx_hal_pwr.h\n│       │   ├── stm32f4xx_hal_rcc_ex.h\n│       │   ├── stm32f4xx_hal_rcc.h\n│       │   ├── stm32f4xx_hal_spi.h\n│       │   ├── stm32f4xx_hal_tim_ex.h\n│       │   ├── stm32f4xx_hal_tim.h\n│       │   └── stm32f4xx_ll_usb.h\n│       └── Src\n│           ├── stm32f4xx_hal.c\n│           ├── stm32f4xx_hal_cortex.c\n│           ├── stm32f4xx_hal_dma.c\n│           ├── stm32f4xx_hal_dma_ex.c\n│           ├── stm32f4xx_hal_exti.c\n│           ├── stm32f4xx_hal_flash.c\n│           ├── stm32f4xx_hal_flash_ex.c\n│           ├── stm32f4xx_hal_flash_ramfunc.c\n│           ├── stm32f4xx_hal_gpio.c\n│           ├── stm32f4xx_hal_i2c.c\n│           ├── stm32f4xx_hal_i2c_ex.c\n│           ├── stm32f4xx_hal_pcd.c\n│           ├── stm32f4xx_hal_pcd_ex.c\n│           ├── stm32f4xx_hal_pwr.c\n│           ├── stm32f4xx_hal_pwr_ex.c\n│           ├── stm32f4xx_hal_rcc.c\n│           ├── stm32f4xx_hal_rcc_ex.c\n│           ├── stm32f4xx_hal_spi.c\n│           ├── stm32f4xx_hal_tim.c\n│           ├── stm32f4xx_hal_tim_ex.c\n│           └── stm32f4xx_ll_usb.c\n├── Inc\n│   ├── FreeRTOSConfig.h\n│   ├── main.h\n│   ├── stm32f4xx_hal_conf.h\n│   ├── stm32f4xx_it.h\n│   ├── usbd_cdc_if.h\n│   ├── usbd_conf.h\n│   ├── usbd_desc.h\n│   └── usb_device.h\n├── Makefile\n├── Middlewares\n│   ├── ST\n│   │   └── STM32_USB_Device_Library\n│   │       ├── Class\n│   │       │   └── CDC\n│   │       │       ├── Inc\n│   │       │       │   └── usbd_cdc.h\n│   │       │       └── Src\n│   │       │           └── usbd_cdc.c\n│   │       └── Core\n│   │           ├── Inc\n│   │           │   ├── usbd_core.h\n│   │           │   ├── usbd_ctlreq.h\n│   │           │   ├── usbd_def.h\n│   │           │   └── usbd_ioreq.h\n│   │           └── Src\n│   │               ├── usbd_core.c\n│   │               ├── usbd_ctlreq.c\n│   │               └── usbd_ioreq.c\n│   └── Third_Party\n│       └── FreeRTOS\n│           └── Source\n│               ├── CMSIS_RTOS\n│               │   ├── cmsis_os.c\n│               │   └── cmsis_os.h\n│               ├── croutine.c\n│               ├── event_groups.c\n│               ├── include\n│               │   ├── atomic.h\n│               │   ├── croutine.h\n│               │   ├── deprecated_definitions.h\n│               │   ├── event_groups.h\n│               │   ├── FreeRTOS.h\n│               │   ├── list.h\n│               │   ├── message_buffer.h\n│               │   ├── mpu_prototypes.h\n│               │   ├── mpu_wrappers.h\n│               │   ├── portable.h\n│               │   ├── projdefs.h\n│               │   ├── queue.h\n│               │   ├── semphr.h\n│               │   ├── StackMacros.h\n│               │   ├── stack_macros.h\n│               │   ├── stream_buffer.h\n│               │   ├── task.h\n│               │   └── timers.h\n│               ├── list.c\n│               ├── portable\n│               │   ├── GCC\n│               │   │   └── ARM_CM4F\n│               │   │       ├── port.c\n│               │   │       └── portmacro.h\n│               │   └── MemMang\n│               │       └── heap_4.c\n│               ├── queue.c\n│               ├── stream_buffer.c\n│               ├── tasks.c\n│               └── timers.c\n├── README.md\n├── Src\n│   ├── freertos.c\n│   ├── main.c\n│   ├── stm32f4xx_hal_msp.c\n│   ├── stm32f4xx_hal_timebase_tim.c\n│   ├── stm32f4xx_it.c\n│   ├── syscalls.c\n│   ├── system_stm32f4xx.c\n│   ├── usbd_cdc_if.c\n│   ├── usbd_conf.c\n│   ├── usbd_desc.c\n│   └── usb_device.c\n├── startup\n│   └── startup_stm32f405xx.s\n├── startup_stm32f405xx.s\n└── STM32F405RGTx_FLASH.ld\n```\nNotice the presence of a `Makefile`. Feel free to open this file and check it out. \n\n\n## Compiling the code\nIn the project directory,\n\n    make all\n\nand thats it. This will create a `./build` directory, with a bunch of stuff, including a `.elf` file, which is the compiled firmware that we will be uploading to our board. \n\nSteven suggests the following very basic tutorial on using `make`: https://cs.colby.edu/maxwell/courses/tutorials/maketutor/.\n\n## Uploading with OpenOCD\nAlthough OpenOCD can be downloaded explicitly, it is also possible to install it as a regular package\n\n    sudo apt-get install openocd\n\nThis will allow take care of creating a symbolic link to the `openocd` command, allowing us to just use the `openocd` command from any directory. Assuming you have built the code with `make`, that you are still in the `uwb_firmware` directory, and that the discovery board is plugged in with the appropriate jumpers removed, we can upload our firmware in one command. If your debugger is using ST-LINK V1, the command is\n\n\topenocd -f board/stm32f4discovery.cfg -c \"program ./build/config_stm32f4.elf verify reset exit\"\n\nIf the debugger is using ST-LINK V2, then \n\n    openocd -f interface/stlink-v2-1.cfg -f target/stm32f4x.cfg -c \"program ./build/config_stm32f4.elf verify reset exit\"\n\n## Debugging with OpenOCD and GDB\n\nFirst, make sure the board is connected by USB and start OpenOCD in V1\n\n\topenocd -f board/stm32f4discovery.cfg\n\nor in V2\n\n    openocd -f interface/stlink-v2-1.cfg -f target/stm32f4x.cfg\n\nIn a new terminal in the current `uwb_firmware` directory\n\n    arm-none-eabi-gdb ./build/config_stm32f4.elf\n\nand you will enter a GDB command line. The above step assumes that you have installed the `arm-none-eabi-gcc` toolchain as per Mohammed's tutorial. To connect to the openocd server \n\n    (gdb) target remote localhost:3333\n\nThen at this point you can use whatever GDB commands. You can directly load the firmware from here\n\n    (gdb) load\n    \nYou can then use `list` to see where you are in the code, as well as `continue` or `step`. Theres a way to set breakpoints from the GDB terminal, but at this point, we will move to using the VSCode editor for debugging.\n\n## Setting up the same workflow in VS Code\n\nAt a minimum, you just need to open the `uwb_firmware` folder in VS Code and you can start editting the source code with some basic syntax highlighting already. However, it will probably be full of red warnings as a result of Intellisense not finding all the files. We will need to configure intellisense properly.\n\n### Configuring Intellisense\n Create a `./.vscode/` subdirectory. Create a `c_cpp_properties.json` file and insert the following\n\n```json\n{\n\t\"version\": 4,\n\t\"configurations\":\n\t[\n\t\t{\t\n\t\t\t\"name\": \"Linux: Embedded Development\",\n\t\t\t\"intelliSenseMode\": \"gcc-arm\",\n\t\t\t\"cStandard\": \"c99\",\n\t\t\t\"cppStandard\": \"c++17\",\n\t\t\t\"compilerPath\": \"/opt/gcc-arm-none-eabi-9-2020-q2-update/bin/arm-none-eabi-gcc\"\n\t\t\t,\n\t\t\t\"defines\":\n\t\t\t[\n\t\t\t\t\"USE_HAL_DRIVER\", \n\t\t\t\t\"STM32F405xx\"\n\t\t\t],\n\t\t\t\"includePath\":\n\t\t\t[\n\t\t\t\t\"${workspaceFolder}/**\",\n\t\t\t\t\"/opt/gcc-arm-none-eabi-9-2020-q2-update/lib/gcc/arm-none-eabi/9.3.1/include\",\n\t\t\t\t\"Inc\", \n\t\t\t\t\"Drivers/STM32F4xx_HAL_Driver/Inc\", \n\t\t\t\t\"Drivers/STM32F4xx_HAL_Driver/Inc/Legacy\", \n\t\t\t\t\"Middlewares/Third_Party/FreeRTOS/Source/include\", \n\t\t\t\t\"Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS\", \n\t\t\t\t\"Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4F\", \n\t\t\t\t\"Middlewares/ST/STM32_USB_Device_Library/Core/Inc\", \n\t\t\t\t\"Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc\", \n\t\t\t\t\"Drivers/CMSIS/Device/ST/STM32F4xx/Include\", \n\t\t\t\t\"Drivers/CMSIS/Include\"\n\t\t\t]\n\t\t}\n\t]\n}\n```\nNow you should have the full amazing code navigation/editting functionality of VS Code, including syntax highlighting, Go to Definition, Go to References, code peeking and more. \n\n### Building from VS Code\nVS Code provides functionality to run whatever terminal command as a \"task\" from within the editor. In the `./.vscode/` folder, create a `tasks.json` file with the following\n\n```json\n{\n\t\"version\": \"2.0.0\",\n\t\"tasks\":\n\t[\n\t\t{\n\t\t\t\"label\": \"Build Firmware\",\n\t\t\t\"group\":\n\t\t\t{\n\t\t\t\t\"kind\": \"build\",\n\t\t\t\t\"isDefault\": true\n\t\t\t},\n\t\t\t\"type\": \"shell\",\n\t\t\t\"command\": \"make all\",\n\t\t\t\"args\":\n\t\t\t[\n\t\t\t\t\n\t\t\t],\n\t\t\t\"problemMatcher\":\n\t\t\t[\n\t\t\t\t\"$gcc\"\n\t\t\t],\n\t\t\t\"presentation\":\n\t\t\t{\n\t\t\t\t\"focus\": true\n\t\t\t}\n\t\t}\n\t]\n}\n\n```\nThe line `\"isDefault\": true` sets this task is the default build task. This means that all we need to do is press `CTRL + SHIFT + B` to run the same make command as before.\n\nAlternatively, press `CTRL + SHIFT + P` to open the command palette, and select __Run Task__, it will then ask you which one to choose. \n\n### Uploading from VS Code\nJust as before, we just need to create a VS Code task to run the upload command for us. Open `tasks.json` and add the following task just after the build task (seperated by a comma)\n\n```json\n{\n    \"label\": \"Upload Firmware V2\",\n    \"type\": \"shell\",\n    \"command\": \"openocd\",\n    \"args\":\n\t\t[\n\t\t\t\"-f\",\"interface/stlink-v2-1.cfg\",\n\t\t\t\"-f\",\"target/stm32f4x.cfg\",\n\t\t\t\"-c\",\"'program build/config_stm32f4.elf verify reset exit'\"\n\t\t]\n},\n{\n\t\"label\": \"Upload Firmware V1\",\n\t\"type\": \"shell\",\n\t\"command\": \"openocd\",\n\t\"args\":\n\t[\n\t\t\"-f\",\"board/stm32f4discovery.cfg\",\n\t\t\"-c\",\"'program build/config_stm32f4.elf verify reset exit'\"\n\t]\n}\n\n```\nAnd thats it! You can run this from the command palette by pressing `CTRL + SHIFT + P` and typing in __Run Task__, after which the suggestions will prompt you for which task to choose.\n\n## Debugging with VS Code\nFor this step, the easiest thing to do is to install the [Cortex-Debug](https://marketplace.visualstudio.com/items?itemName=marus25.cortex-debug) extension for VS Code. \n\nThen, create a `launch.json` file inside the `.vscode` folder with the following contents.\n\n```json\n{\n    \"version\": \"0.2.0\",\n    \"configurations\":\n    [\n        {\n            \"name\": \"Build and Debug V2\",\n            \"type\": \"cortex-debug\",\n            \"request\": \"launch\",\n            \"servertype\": \"openocd\",\n            \"cwd\": \"${workspaceFolder}\",\n            \"executable\": \"./build/config_stm32f4.elf\",\n            \"device\": \"STM32F405RGT6\",\n            \"svdFile\": \"${workspaceFolder}/.vscode/STM32F405.svd\",\n            \"configFiles\":\n            [\n                \"/usr/share/openocd/scripts/interface/stlink-v2-1.cfg\",\n                \"/usr/share/openocd/scripts/target/stm32f4x.cfg\"\n            ],\n            \"preLaunchTask\": \"Build Firmware\",\n            \"overrideGDBServerStartedRegex\": \"Info\\\\s:\\\\s([^\\\\n\\\\.]*)\\\\.cpu([^\\\\n]*)\"\n        },\n\t\t{\n\t\t\t\"name\": \"Build and Debug V1\",\n\t\t\t\"type\": \"cortex-debug\",\n\t\t\t\"request\": \"launch\",\n\t\t\t\"servertype\": \"openocd\",\n\t\t\t\"cwd\": \"${workspaceFolder}\",\n\t\t\t\"executable\": \"build/config_stm32f4.elf\",\n\t\t\t\"device\": \"STM32F405RGT6\",\n            \"svdFile\": \"${workspaceFolder}/.vscode/STM32F405.svd\",\n\t\t\t\"configFiles\":\n\t\t\t[\n\t\t\t\t\"/usr/share/openocd/scripts/board/stm32f4discovery.cfg\"\n\t\t\t],\n\t\t\t\"preLaunchTask\": \"Build Firmware\",\n\t\t\t\"overrideGDBServerStartedRegex\": \"Info\\\\s:\\\\s([^\\\\n\\\\.]*)\\\\.cpu([^\\\\n]*)\"\n\t\t}\n    ]\n},\n\n```\n\nCreate a `settings.json` file inside the `.vscode` folder with the following contents.\n\n```json\n{\n\t\"cortex-debug.armToolchainPath\": \"\",\n\t\"cortex-debug.openocdPath\": \"/usr/bin/openocd\"\n}\n```\n\n\nYou should now be able to go to the debug tab in VS Code and see a `Build and Debug` option.\n\n\n## Steven's Magic Links\n\nMakefile tutorial: https://cs.colby.edu/maxwell/courses/tutorials/maketutor/\n\nFreeRTOS tutorial: https://freertos.org/fr-content-src/uploads/2018/07/161204_Mastering_the_FreeRTOS_Real_Time_Kernel-A_Hands-On_Tutorial_Guide.pdf \n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshalabymhd%2Fuwb_firmware","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fshalabymhd%2Fuwb_firmware","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshalabymhd%2Fuwb_firmware/lists"}