From eb6150ffadeaf6c632d292c7fd9bd22b34d32705 Mon Sep 17 00:00:00 2001 From: Kevin Thomas Date: Sat, 4 Apr 2026 12:11:58 -0400 Subject: [PATCH] Added cbm 1 2 --- .gitignore | 3 + drivers/0x01_uart_cbm/.gitattributes | 11 + drivers/0x01_uart_cbm/.gitignore | 10 + .../.vscode/c_cpp_properties.json | 25 ++ drivers/0x01_uart_cbm/.vscode/extensions.json | 9 + drivers/0x01_uart_cbm/.vscode/launch.json | 37 ++ drivers/0x01_uart_cbm/.vscode/settings.json | 40 ++ drivers/0x01_uart_cbm/.vscode/tasks.json | 107 +++++ drivers/0x01_uart_cbm/build.bat | 97 +++++ drivers/0x01_uart_cbm/clean.bat | 30 ++ drivers/0x01_uart_cbm/constants.h | 195 ++++++++++ drivers/0x01_uart_cbm/coprocessor.c | 48 +++ drivers/0x01_uart_cbm/coprocessor.h | 45 +++ drivers/0x01_uart_cbm/delay.c | 46 +++ drivers/0x01_uart_cbm/delay.h | 45 +++ drivers/0x01_uart_cbm/image_def.c | 48 +++ drivers/0x01_uart_cbm/linker.ld | 106 +++++ drivers/0x01_uart_cbm/main.c | 78 ++++ drivers/0x01_uart_cbm/reset.c | 45 +++ drivers/0x01_uart_cbm/reset.h | 44 +++ drivers/0x01_uart_cbm/reset_handler.c | 50 +++ drivers/0x01_uart_cbm/reset_handler.h | 45 +++ drivers/0x01_uart_cbm/stack.c | 46 +++ drivers/0x01_uart_cbm/stack.h | 44 +++ drivers/0x01_uart_cbm/uart.c | 165 ++++++++ drivers/0x01_uart_cbm/uart.h | 111 ++++++ drivers/0x01_uart_cbm/uf2conv.py | 365 ++++++++++++++++++ drivers/0x01_uart_cbm/uf2families.json | 22 ++ drivers/0x01_uart_cbm/vector_table.c | 46 +++ drivers/0x01_uart_cbm/xosc.c | 54 +++ drivers/0x01_uart_cbm/xosc.h | 55 +++ drivers/0x02_blink_cbm/.gitattributes | 11 + drivers/0x02_blink_cbm/.gitignore | 10 + .../.vscode/c_cpp_properties.json | 25 ++ .../0x02_blink_cbm/.vscode/extensions.json | 9 + drivers/0x02_blink_cbm/.vscode/launch.json | 37 ++ drivers/0x02_blink_cbm/.vscode/settings.json | 40 ++ drivers/0x02_blink_cbm/.vscode/tasks.json | 107 +++++ drivers/0x02_blink_cbm/blink.c | 52 +++ drivers/0x02_blink_cbm/blink.h | 78 ++++ drivers/0x02_blink_cbm/build.bat | 103 +++++ drivers/0x02_blink_cbm/clean.bat | 30 ++ drivers/0x02_blink_cbm/constants.h | 214 ++++++++++ drivers/0x02_blink_cbm/coprocessor.c | 48 +++ drivers/0x02_blink_cbm/coprocessor.h | 45 +++ drivers/0x02_blink_cbm/delay.c | 46 +++ drivers/0x02_blink_cbm/delay.h | 45 +++ drivers/0x02_blink_cbm/gpio.c | 111 ++++++ drivers/0x02_blink_cbm/gpio.h | 86 +++++ drivers/0x02_blink_cbm/image_def.c | 48 +++ drivers/0x02_blink_cbm/linker.ld | 106 +++++ drivers/0x02_blink_cbm/main.c | 78 ++++ drivers/0x02_blink_cbm/reset.c | 45 +++ drivers/0x02_blink_cbm/reset.h | 44 +++ drivers/0x02_blink_cbm/reset_handler.c | 50 +++ drivers/0x02_blink_cbm/reset_handler.h | 45 +++ drivers/0x02_blink_cbm/stack.c | 46 +++ drivers/0x02_blink_cbm/stack.h | 44 +++ drivers/0x02_blink_cbm/uart.c | 165 ++++++++ drivers/0x02_blink_cbm/uart.h | 111 ++++++ drivers/0x02_blink_cbm/uf2conv.py | 365 ++++++++++++++++++ drivers/0x02_blink_cbm/uf2families.json | 22 ++ drivers/0x02_blink_cbm/vector_table.c | 46 +++ drivers/0x02_blink_cbm/xosc.c | 54 +++ drivers/0x02_blink_cbm/xosc.h | 55 +++ 65 files changed, 4493 insertions(+) create mode 100644 drivers/0x01_uart_cbm/.gitattributes create mode 100644 drivers/0x01_uart_cbm/.gitignore create mode 100644 drivers/0x01_uart_cbm/.vscode/c_cpp_properties.json create mode 100644 drivers/0x01_uart_cbm/.vscode/extensions.json create mode 100644 drivers/0x01_uart_cbm/.vscode/launch.json create mode 100644 drivers/0x01_uart_cbm/.vscode/settings.json create mode 100644 drivers/0x01_uart_cbm/.vscode/tasks.json create mode 100644 drivers/0x01_uart_cbm/build.bat create mode 100644 drivers/0x01_uart_cbm/clean.bat create mode 100644 drivers/0x01_uart_cbm/constants.h create mode 100644 drivers/0x01_uart_cbm/coprocessor.c create mode 100644 drivers/0x01_uart_cbm/coprocessor.h create mode 100644 drivers/0x01_uart_cbm/delay.c create mode 100644 drivers/0x01_uart_cbm/delay.h create mode 100644 drivers/0x01_uart_cbm/image_def.c create mode 100644 drivers/0x01_uart_cbm/linker.ld create mode 100644 drivers/0x01_uart_cbm/main.c create mode 100644 drivers/0x01_uart_cbm/reset.c create mode 100644 drivers/0x01_uart_cbm/reset.h create mode 100644 drivers/0x01_uart_cbm/reset_handler.c create mode 100644 drivers/0x01_uart_cbm/reset_handler.h create mode 100644 drivers/0x01_uart_cbm/stack.c create mode 100644 drivers/0x01_uart_cbm/stack.h create mode 100644 drivers/0x01_uart_cbm/uart.c create mode 100644 drivers/0x01_uart_cbm/uart.h create mode 100644 drivers/0x01_uart_cbm/uf2conv.py create mode 100644 drivers/0x01_uart_cbm/uf2families.json create mode 100644 drivers/0x01_uart_cbm/vector_table.c create mode 100644 drivers/0x01_uart_cbm/xosc.c create mode 100644 drivers/0x01_uart_cbm/xosc.h create mode 100644 drivers/0x02_blink_cbm/.gitattributes create mode 100644 drivers/0x02_blink_cbm/.gitignore create mode 100644 drivers/0x02_blink_cbm/.vscode/c_cpp_properties.json create mode 100644 drivers/0x02_blink_cbm/.vscode/extensions.json create mode 100644 drivers/0x02_blink_cbm/.vscode/launch.json create mode 100644 drivers/0x02_blink_cbm/.vscode/settings.json create mode 100644 drivers/0x02_blink_cbm/.vscode/tasks.json create mode 100644 drivers/0x02_blink_cbm/blink.c create mode 100644 drivers/0x02_blink_cbm/blink.h create mode 100644 drivers/0x02_blink_cbm/build.bat create mode 100644 drivers/0x02_blink_cbm/clean.bat create mode 100644 drivers/0x02_blink_cbm/constants.h create mode 100644 drivers/0x02_blink_cbm/coprocessor.c create mode 100644 drivers/0x02_blink_cbm/coprocessor.h create mode 100644 drivers/0x02_blink_cbm/delay.c create mode 100644 drivers/0x02_blink_cbm/delay.h create mode 100644 drivers/0x02_blink_cbm/gpio.c create mode 100644 drivers/0x02_blink_cbm/gpio.h create mode 100644 drivers/0x02_blink_cbm/image_def.c create mode 100644 drivers/0x02_blink_cbm/linker.ld create mode 100644 drivers/0x02_blink_cbm/main.c create mode 100644 drivers/0x02_blink_cbm/reset.c create mode 100644 drivers/0x02_blink_cbm/reset.h create mode 100644 drivers/0x02_blink_cbm/reset_handler.c create mode 100644 drivers/0x02_blink_cbm/reset_handler.h create mode 100644 drivers/0x02_blink_cbm/stack.c create mode 100644 drivers/0x02_blink_cbm/stack.h create mode 100644 drivers/0x02_blink_cbm/uart.c create mode 100644 drivers/0x02_blink_cbm/uart.h create mode 100644 drivers/0x02_blink_cbm/uf2conv.py create mode 100644 drivers/0x02_blink_cbm/uf2families.json create mode 100644 drivers/0x02_blink_cbm/vector_table.c create mode 100644 drivers/0x02_blink_cbm/xosc.c create mode 100644 drivers/0x02_blink_cbm/xosc.h diff --git a/.gitignore b/.gitignore index cba05ae..a559946 100644 --- a/.gitignore +++ b/.gitignore @@ -52,3 +52,6 @@ modules.order Module.symvers Mkfile.old dkms.conf + +# Build output +build/ diff --git a/drivers/0x01_uart_cbm/.gitattributes b/drivers/0x01_uart_cbm/.gitattributes new file mode 100644 index 0000000..91c1527 --- /dev/null +++ b/drivers/0x01_uart_cbm/.gitattributes @@ -0,0 +1,11 @@ +# C files +*.c linguist-language=C + +# Exclude from language statistics +*.ld linguist-vendored +*.bat linguist-vendored +*.py linguist-vendored +linker.ld linguist-vendored +build.bat linguist-vendored +clean.bat linguist-vendored +uf2conv.py linguist-vendored diff --git a/drivers/0x01_uart_cbm/.gitignore b/drivers/0x01_uart_cbm/.gitignore new file mode 100644 index 0000000..8a68f1b --- /dev/null +++ b/drivers/0x01_uart_cbm/.gitignore @@ -0,0 +1,10 @@ +# Build artifacts +*.o +*.elf +*.bin +*.uf2 +compile_commands.json + +# OS files +.DS_Store +Thumbs.db diff --git a/drivers/0x01_uart_cbm/.vscode/c_cpp_properties.json b/drivers/0x01_uart_cbm/.vscode/c_cpp_properties.json new file mode 100644 index 0000000..094f8d7 --- /dev/null +++ b/drivers/0x01_uart_cbm/.vscode/c_cpp_properties.json @@ -0,0 +1,25 @@ +{ + "configurations": [ + { + "name": "ARM GCC", + "includePath": [ + "${workspaceFolder}/**" + ], + "defines": [ + "__GNUC__", + "__ARM_ARCH_8M_MAIN__", + "__ARMCC_VERSION" + ], + "compilerPath": "${env:USERPROFILE}/.pico-sdk/toolchain/14_2_Rel1/bin/arm-none-eabi-gcc.exe", + "compileCommands": "${workspaceFolder}/compile_commands.json", + "cStandard": "c11", + "cppStandard": "c++17", + "intelliSenseMode": "gcc-arm", + "compilerArgs": [ + "-mcpu=cortex-m33", + "-mthumb" + ] + } + ], + "version": 4 +} diff --git a/drivers/0x01_uart_cbm/.vscode/extensions.json b/drivers/0x01_uart_cbm/.vscode/extensions.json new file mode 100644 index 0000000..fe41ced --- /dev/null +++ b/drivers/0x01_uart_cbm/.vscode/extensions.json @@ -0,0 +1,9 @@ +{ + "recommendations": [ + "marus25.cortex-debug", + "ms-vscode.cpptools", + "ms-vscode.cpptools-extension-pack", + "ms-vscode.vscode-serial-monitor", + "raspberry-pi.raspberry-pi-pico" + ] +} diff --git a/drivers/0x01_uart_cbm/.vscode/launch.json b/drivers/0x01_uart_cbm/.vscode/launch.json new file mode 100644 index 0000000..d42d98f --- /dev/null +++ b/drivers/0x01_uart_cbm/.vscode/launch.json @@ -0,0 +1,37 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Debug RP2350 (OpenOCD)", + "cwd": "${workspaceFolder}", + "executable": "${workspaceFolder}/uart.elf", + "request": "launch", + "type": "cortex-debug", + "servertype": "openocd", + "serverpath": "${env:USERPROFILE}/.pico-sdk/openocd/0.12.0+dev/openocd.exe", + "searchDir": ["${env:USERPROFILE}/.pico-sdk/openocd/0.12.0+dev/scripts"], + "gdbPath": "${env:USERPROFILE}/.pico-sdk/toolchain/14_2_Rel1/bin/arm-none-eabi-gdb.exe", + "device": "RP2350", + "configFiles": [ + "interface/cmsis-dap.cfg", + "target/rp2350.cfg" + ], + "svdFile": "${env:USERPROFILE}/.pico-sdk/sdk/2.2.0/src/rp2350/hardware_regs/RP2350.svd", + "overrideLaunchCommands": [ + "set arch armv8-m.main", + "set output-radix 16", + "monitor reset init", + "load", + "monitor reset halt" + ], + "openOCDPreConfigLaunchCommands": [ + "set USE_CORE { cm0 cm1 }" + ], + "openOCDLaunchCommands": [ + "adapter speed 5000" + ], + "preLaunchTask": "Compile Project", + "showDevDebugOutput": "raw" + } + ] +} diff --git a/drivers/0x01_uart_cbm/.vscode/settings.json b/drivers/0x01_uart_cbm/.vscode/settings.json new file mode 100644 index 0000000..95be83b --- /dev/null +++ b/drivers/0x01_uart_cbm/.vscode/settings.json @@ -0,0 +1,40 @@ +{ + "cmake.showSystemKits": false, + "cmake.options.statusBarVisibility": "hidden", + "cmake.options.advanced": { + "build": { + "statusBarVisibility": "hidden" + }, + "launch": { + "statusBarVisibility": "hidden" + }, + "debug": { + "statusBarVisibility": "hidden" + } + }, + "cmake.configureOnEdit": false, + "cmake.automaticReconfigure": false, + "cmake.configureOnOpen": false, + "cmake.generator": "Ninja", + "cmake.cmakePath": "${userHome}/.pico-sdk/cmake/v3.31.5/bin/cmake", + "C_Cpp.debugShortcut": false, + "terminal.integrated.env.windows": { + "PICO_SDK_PATH": "${env:USERPROFILE}/.pico-sdk/sdk/2.2.0", + "PICO_TOOLCHAIN_PATH": "${env:USERPROFILE}/.pico-sdk/toolchain/14_2_Rel1", + "Path": "${env:USERPROFILE}/.pico-sdk/toolchain/14_2_Rel1/bin;${env:USERPROFILE}/.pico-sdk/picotool/2.2.0-a4/picotool;${env:USERPROFILE}/.pico-sdk/cmake/v3.31.5/bin;${env:USERPROFILE}/.pico-sdk/ninja/v1.12.1;${env:PATH}" + }, + "terminal.integrated.env.osx": { + "PICO_SDK_PATH": "${env:HOME}/.pico-sdk/sdk/2.2.0", + "PICO_TOOLCHAIN_PATH": "${env:HOME}/.pico-sdk/toolchain/14_2_Rel1", + "PATH": "${env:HOME}/.pico-sdk/toolchain/14_2_Rel1/bin:${env:HOME}/.pico-sdk/picotool/2.2.0-a4/picotool:${env:HOME}/.pico-sdk/cmake/v3.31.5/bin:${env:HOME}/.pico-sdk/ninja/v1.12.1:${env:PATH}" + }, + "terminal.integrated.env.linux": { + "PICO_SDK_PATH": "${env:HOME}/.pico-sdk/sdk/2.2.0", + "PICO_TOOLCHAIN_PATH": "${env:HOME}/.pico-sdk/toolchain/14_2_Rel1", + "PATH": "${env:HOME}/.pico-sdk/toolchain/14_2_Rel1/bin:${env:HOME}/.pico-sdk/picotool/2.2.0-a4/picotool:${env:HOME}/.pico-sdk/cmake/v3.31.5/bin:${env:HOME}/.pico-sdk/ninja/v1.12.1:${env:PATH}" + }, + "raspberry-pi-pico.cmakeAutoConfigure": true, + "raspberry-pi-pico.useCmakeTools": false, + "raspberry-pi-pico.cmakePath": "${HOME}/.pico-sdk/cmake/v3.31.5/bin/cmake", + "raspberry-pi-pico.ninjaPath": "${HOME}/.pico-sdk/ninja/v1.12.1/ninja" +} diff --git a/drivers/0x01_uart_cbm/.vscode/tasks.json b/drivers/0x01_uart_cbm/.vscode/tasks.json new file mode 100644 index 0000000..1423142 --- /dev/null +++ b/drivers/0x01_uart_cbm/.vscode/tasks.json @@ -0,0 +1,107 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "Compile Project", + "type": "shell", + "command": ".\\build.bat", + "group": { + "kind": "build", + "isDefault": true + }, + "presentation": { + "reveal": "always", + "panel": "dedicated" + }, + "problemMatcher": "$gcc" + }, + { + "label": "Clean Project", + "type": "shell", + "command": ".\\clean.bat", + "group": "build", + "presentation": { + "reveal": "always", + "panel": "dedicated" + }, + "problemMatcher": [] + }, + { + "label": "Run Project", + "type": "shell", + "command": "${env:USERPROFILE}/.pico-sdk/picotool/2.2.0-a4/picotool/picotool.exe", + "args": [ + "load", + "uart.uf2", + "-fx" + ], + "presentation": { + "reveal": "always", + "panel": "dedicated" + }, + "problemMatcher": [], + "dependsOn": ["Compile Project"] + }, + { + "label": "Flash", + "type": "shell", + "command": "${env:USERPROFILE}/.pico-sdk/openocd/0.12.0+dev/openocd.exe", + "args": [ + "-s", + "${env:USERPROFILE}/.pico-sdk/openocd/0.12.0+dev/scripts", + "-f", + "interface/cmsis-dap.cfg", + "-f", + "target/rp2350.cfg", + "-c", + "adapter speed 5000; program uart.elf verify reset exit" + ], + "problemMatcher": [], + "dependsOn": ["Compile Project"] + }, + { + "label": "Rescue Reset", + "type": "process", + "command": "${userHome}/.pico-sdk/openocd/0.12.0+dev/openocd.exe", + "args": [ + "-s", + "${userHome}/.pico-sdk/openocd/0.12.0+dev/scripts", + "-f", + "interface/cmsis-dap.cfg", + "-f", + "target/${command:raspberry-pi-pico.getChip}-rescue.cfg", + "-c", + "adapter speed 5000; reset halt; exit" + ], + "problemMatcher": [], + "windows": { + "command": "${env:USERPROFILE}/.pico-sdk/openocd/0.12.0+dev/openocd.exe" + } + }, + { + "label": "RISC-V Reset (RP2350)", + "type": "process", + "command": "${userHome}/.pico-sdk/openocd/0.12.0+dev/openocd.exe", + "args": [ + "-s", + "${userHome}/.pico-sdk/openocd/0.12.0+dev/scripts", + "-c", + "set USE_CORE { rv0 rv1 cm0 cm1 }", + "-f", + "interface/cmsis-dap.cfg", + "-f", + "target/rp2350.cfg", + "-c", + "adapter speed 5000; init;", + "-c", + "write_memory 0x40120158 8 { 0x3 }; echo [format \"Info : ARCHSEL 0x%02x\" [read_memory 0x40120158 8 1]];", + "-c", + "reset halt; targets rp2350.rv0; echo [format \"Info : ARCHSEL_STATUS 0x%02x\" [read_memory 0x4012015C 8 1]]; exit" + ], + "problemMatcher": [], + "windows": { + "command": "${env:USERPROFILE}/.pico-sdk/openocd/0.12.0+dev/openocd.exe" + } + } + ] +} diff --git a/drivers/0x01_uart_cbm/build.bat b/drivers/0x01_uart_cbm/build.bat new file mode 100644 index 0000000..caf95aa --- /dev/null +++ b/drivers/0x01_uart_cbm/build.bat @@ -0,0 +1,97 @@ +@echo off +REM ============================================================================== +REM FILE: build.bat +REM +REM DESCRIPTION: +REM Build script for RP2350 bare-metal C UART driver. +REM +REM BRIEF: +REM Automates the process of compiling, linking, and generating UF2 firmware. +REM +REM AUTHOR: Kevin Thomas +REM CREATION DATE: 2025 +REM UPDATE DATE: 2025 +REM ============================================================================== + +echo Building C bare-metal version... + +REM ============================================================================== +REM Compile C Source Files +REM ============================================================================== +arm-none-eabi-gcc -mcpu=cortex-m33 -mthumb -Og -g3 -Wall -Wextra -ffunction-sections -fdata-sections -c vector_table.c -o vector_table.o +if errorlevel 1 goto error + +arm-none-eabi-gcc -mcpu=cortex-m33 -mthumb -Og -g3 -Wall -Wextra -ffunction-sections -fdata-sections -c reset_handler.c -o reset_handler.o +if errorlevel 1 goto error + +arm-none-eabi-gcc -mcpu=cortex-m33 -mthumb -Og -g3 -Wall -Wextra -ffunction-sections -fdata-sections -c stack.c -o stack.o +if errorlevel 1 goto error + +arm-none-eabi-gcc -mcpu=cortex-m33 -mthumb -Og -g3 -Wall -Wextra -ffunction-sections -fdata-sections -c xosc.c -o xosc.o +if errorlevel 1 goto error + +arm-none-eabi-gcc -mcpu=cortex-m33 -mthumb -Og -g3 -Wall -Wextra -ffunction-sections -fdata-sections -c reset.c -o reset.o +if errorlevel 1 goto error + +arm-none-eabi-gcc -mcpu=cortex-m33 -mthumb -Og -g3 -Wall -Wextra -ffunction-sections -fdata-sections -c coprocessor.c -o coprocessor.o +if errorlevel 1 goto error + +arm-none-eabi-gcc -mcpu=cortex-m33 -mthumb -Og -g3 -Wall -Wextra -ffunction-sections -fdata-sections -c uart.c -o uart.o +if errorlevel 1 goto error + +arm-none-eabi-gcc -mcpu=cortex-m33 -mthumb -Og -g3 -Wall -Wextra -ffunction-sections -fdata-sections -c delay.c -o delay.o +if errorlevel 1 goto error + +arm-none-eabi-gcc -mcpu=cortex-m33 -mthumb -Og -g3 -Wall -Wextra -ffunction-sections -fdata-sections -c main.c -o main.o +if errorlevel 1 goto error + +arm-none-eabi-gcc -mcpu=cortex-m33 -mthumb -Og -g3 -Wall -Wextra -ffunction-sections -fdata-sections -c image_def.c -o image_def.o +if errorlevel 1 goto error + +REM ============================================================================== +REM Link Object Files +REM ============================================================================== +arm-none-eabi-gcc -mcpu=cortex-m33 -mthumb -T linker.ld -nostdlib -Wl,--gc-sections vector_table.o reset_handler.o stack.o xosc.o reset.o coprocessor.o uart.o delay.o main.o image_def.o -o uart.elf +if errorlevel 1 goto error + +REM ============================================================================== +REM Create Raw Binary from ELF +REM ============================================================================== +arm-none-eabi-objcopy -O binary uart.elf uart.bin +if errorlevel 1 goto error + +REM ============================================================================== +REM Create UF2 Image for RP2350 +REM -b 0x10000000 : base address +REM -f 0xe48bff59 : RP2350 family ID +REM ============================================================================== +python uf2conv.py -b 0x10000000 -f 0xe48bff59 -o uart.uf2 uart.bin +if errorlevel 1 goto error + +REM ============================================================================== +REM Success Message and Flashing Instructions +REM ============================================================================== +echo. +echo ================================= +echo SUCCESS! Created uart.uf2 +echo ================================= +echo. +echo To flash via UF2: +echo 1. Hold BOOTSEL button +echo 2. Plug in USB +echo 3. Copy uart.uf2 to RP2350 drive +echo. +echo To flash via OpenOCD (debug probe): +echo openocd -f interface/cmsis-dap.cfg -f target/rp2350.cfg -c "adapter speed 5000" -c "program uart.elf verify reset exit" +echo. +goto end + +REM ============================================================================== +REM Error Handling +REM ============================================================================== +:error +echo. +echo BUILD FAILED! +echo. + +:end diff --git a/drivers/0x01_uart_cbm/clean.bat b/drivers/0x01_uart_cbm/clean.bat new file mode 100644 index 0000000..02cdd3b --- /dev/null +++ b/drivers/0x01_uart_cbm/clean.bat @@ -0,0 +1,30 @@ +@echo off +REM ============================================================================== +REM FILE: clean.bat +REM +REM DESCRIPTION: +REM Clean script for RP2350 bare-metal C UART driver. +REM +REM BRIEF: +REM Removes all build artifacts and generated files. +REM +REM AUTHOR: Kevin Thomas +REM CREATION DATE: 2025 +REM UPDATE DATE: 2025 +REM ============================================================================== + +echo Cleaning build artifacts... + +REM Remove object files +if exist *.o del /Q *.o + +REM Remove ELF file +if exist uart.elf del /Q uart.elf + +REM Remove binary file +if exist uart.bin del /Q uart.bin + +REM Remove UF2 file +if exist uart.uf2 del /Q uart.uf2 + +echo Clean complete! diff --git a/drivers/0x01_uart_cbm/constants.h b/drivers/0x01_uart_cbm/constants.h new file mode 100644 index 0000000..704e32b --- /dev/null +++ b/drivers/0x01_uart_cbm/constants.h @@ -0,0 +1,195 @@ +/** + * @file constants.h + * @brief Memory-mapped register structures and peripheral base addresses + * @author Kevin Thomas + * @date 2025 + * + * MIT License + * + * Copyright (c) 2025 Kevin Thomas + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef CONSTANTS_H +#define CONSTANTS_H + +#include + +/** + * Stack addresses. + */ +#define STACK_TOP 0x20082000U +#define STACK_LIMIT 0x2007A000U + +/** + * XOSC (External Crystal Oscillator) Register Structure. + */ +typedef struct { + volatile uint32_t CTRL; /**< 0x00: Control register */ + volatile uint32_t STATUS; /**< 0x04: Status register */ + volatile uint32_t DORMANT; /**< 0x08: Dormant mode */ + volatile uint32_t STARTUP; /**< 0x0C: Startup delay */ + volatile uint32_t RESERVED[3]; /**< 0x10-0x18: Reserved */ + volatile uint32_t COUNT; /**< 0x1C: Frequency count */ +} xosc_hw_t; + +/** + * XOSC base address and pointer. + */ +#define XOSC_BASE 0x40048000U +#define XOSC ((xosc_hw_t *)XOSC_BASE) + +/** + * XOSC status bit definitions. + */ +#define XOSC_STATUS_STABLE_SHIFT 31U + +/** + * CPACR (Coprocessor Access Control Register) in PPB. + */ +#define PPB_BASE 0xE0000000U +#define CPACR ((volatile uint32_t *)(PPB_BASE + 0x0ED88U)) + +/** + * Coprocessor access control bit definitions. + */ +#define CPACR_CP0_SHIFT 0U +#define CPACR_CP1_SHIFT 1U + +/** + * CLOCKS Register Structure. + */ +typedef struct { + volatile uint32_t RESERVED0[18]; /**< 0x00-0x44: Other clock registers */ + volatile uint32_t CLK_PERI_CTRL; /**< 0x48: Peripheral clock control */ +} clocks_hw_t; + +/** + * CLOCKS base address and pointer. + */ +#define CLOCKS_BASE 0x40010000U +#define CLOCKS ((clocks_hw_t *)CLOCKS_BASE) + +/** + * Clock control bit definitions. + */ +#define CLOCKS_CLK_PERI_CTRL_ENABLE_SHIFT 11U +#define CLOCKS_CLK_PERI_CTRL_AUXSRC_SHIFT 5U +#define CLOCKS_CLK_PERI_CTRL_AUXSRC_XOSC 4U + +/** + * RESETS Register Structure. + */ +typedef struct { + volatile uint32_t RESET; /**< 0x00: Reset control */ + volatile uint32_t WDSEL; /**< 0x04: Watchdog select */ + volatile uint32_t RESET_DONE; /**< 0x08: Reset done status */ +} resets_hw_t; + +/** + * RESETS base address and pointer. + */ +#define RESETS_BASE 0x40020000U +#define RESETS ((resets_hw_t *)RESETS_BASE) +#define RESETS_RESET_CLEAR ((volatile uint32_t *)(RESETS_BASE + 0x3000U)) + +/** + * Reset control bit definitions. + */ +#define RESETS_RESET_IO_BANK0_SHIFT 6U +#define RESETS_RESET_UART0_SHIFT 26U + +/** + * IO_BANK0 GPIO Control Register (one per GPIO). + */ +typedef struct { + volatile uint32_t STATUS; /**< 0x00: GPIO status */ + volatile uint32_t CTRL; /**< 0x04: GPIO control */ +} io_bank0_gpio_ctrl_t; + +/** + * IO_BANK0 Register Structure. + */ +typedef struct { + io_bank0_gpio_ctrl_t GPIO[30]; /**< 0x000-0x0E8: GPIO 0-29 */ +} io_bank0_hw_t; + +/** + * IO_BANK0 base address and pointer. + */ +#define IO_BANK0_BASE 0x40028000U +#define IO_BANK0 ((io_bank0_hw_t *)IO_BANK0_BASE) + +/** + * GPIO control bit definitions. + */ +#define IO_BANK0_CTRL_FUNCSEL_MASK 0x1FU +#define IO_BANK0_CTRL_FUNCSEL_UART 0x02U +#define IO_BANK0_CTRL_FUNCSEL_SIO 0x05U + +/** + * PADS_BANK0 Register Structure. + */ +typedef struct { + volatile uint32_t VOLTAGE_SELECT; /**< 0x00: Voltage select */ + volatile uint32_t GPIO[30]; /**< 0x04-0x78: GPIO 0-29 pad control */ +} pads_bank0_hw_t; + +/** + * PADS_BANK0 base address and pointer. + */ +#define PADS_BANK0_BASE 0x40038000U +#define PADS_BANK0 ((pads_bank0_hw_t *)PADS_BANK0_BASE) + +/** + * Pad control bit definitions. + */ +#define PADS_BANK0_OD_SHIFT 7U +#define PADS_BANK0_IE_SHIFT 6U +#define PADS_BANK0_ISO_SHIFT 8U + +/** + * UART0 base address. + */ +#define UART0_BASE 0x40070000U + +/** + * UART register offsets (as word indices from UART0_BASE). + */ +#define UART_DR_OFFSET (0x00U / 4U) +#define UART_FR_OFFSET (0x18U / 4U) +#define UART_IBRD_OFFSET (0x24U / 4U) +#define UART_FBRD_OFFSET (0x28U / 4U) +#define UART_LCR_H_OFFSET (0x2CU / 4U) +#define UART_CR_OFFSET (0x30U / 4U) + +/** + * UART flag register bit definitions. + */ +#define UART_FR_TXFF_MASK 32U +#define UART_FR_RXFE_MASK 16U + +/** + * UART line control and enable values. + */ +#define UART_LCR_H_8N1_FIFO 0x70U +#define UART_CR_ENABLE ((3U << 8) | 1U) + +#endif // CONSTANTS_H diff --git a/drivers/0x01_uart_cbm/coprocessor.c b/drivers/0x01_uart_cbm/coprocessor.c new file mode 100644 index 0000000..f909edf --- /dev/null +++ b/drivers/0x01_uart_cbm/coprocessor.c @@ -0,0 +1,48 @@ +/** + * @file coprocessor.c + * @brief Coprocessor access control enable functions + * @author Kevin Thomas + * @date 2025 + * + * MIT License + * + * Copyright (c) 2025 Kevin Thomas + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "coprocessor.h" +#include "constants.h" + +void Enable_Coprocessor(void) { + uint32_t value; + + // read CPACR value + value = *CPACR; + // set CP1: Ctrl access priv coproc 1 bit + value |= (1U << CPACR_CP1_SHIFT); + // set CP0: Ctrl access priv coproc 0 bit + value |= (1U << CPACR_CP0_SHIFT); + // store value into CPACR + *CPACR = value; + // data sync barrier + __asm__ volatile ("dsb"); + // instruction sync barrier + __asm__ volatile ("isb"); +} diff --git a/drivers/0x01_uart_cbm/coprocessor.h b/drivers/0x01_uart_cbm/coprocessor.h new file mode 100644 index 0000000..5c998a7 --- /dev/null +++ b/drivers/0x01_uart_cbm/coprocessor.h @@ -0,0 +1,45 @@ +/** + * @file coprocessor.h + * @brief Coprocessor access control enable functions + * @author Kevin Thomas + * @date 2025 + * + * MIT License + * + * Copyright (c) 2025 Kevin Thomas + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef COPROCESSOR_H +#define COPROCESSOR_H + +/** + * @brief Enable coprocessor access via CPACR + * + * Grants full access to coprocessors 0 and 1 by setting the + * corresponding bits in the Coprocessor Access Control Register, + * then issues DSB and ISB barriers. + * + * @param None + * @retval None + */ +void Enable_Coprocessor(void); + +#endif // COPROCESSOR_H diff --git a/drivers/0x01_uart_cbm/delay.c b/drivers/0x01_uart_cbm/delay.c new file mode 100644 index 0000000..e4a3672 --- /dev/null +++ b/drivers/0x01_uart_cbm/delay.c @@ -0,0 +1,46 @@ +/** + * @file delay.c + * @brief Millisecond delay functions based on a 14.5 MHz clock + * @author Kevin Thomas + * @date 2025 + * + * MIT License + * + * Copyright (c) 2025 Kevin Thomas + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "delay.h" + +void Delay_MS(uint32_t ms) { + if (ms == 0) { + return; + } + __asm__ volatile ( + "mov r4, #3600\n\t" + "mul r5, %0, r4\n\t" + "1:\n\t" + "subs r5, #1\n\t" + "bne 1b\n\t" + : + : "r" (ms) + : "r4", "r5", "cc" + ); +} diff --git a/drivers/0x01_uart_cbm/delay.h b/drivers/0x01_uart_cbm/delay.h new file mode 100644 index 0000000..88bfcef --- /dev/null +++ b/drivers/0x01_uart_cbm/delay.h @@ -0,0 +1,45 @@ +/** + * @file delay.h + * @brief Millisecond delay functions based on a 14.5 MHz clock + * @author Kevin Thomas + * @date 2025 + * + * MIT License + * + * Copyright (c) 2025 Kevin Thomas + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef DELAY_H +#define DELAY_H + +#include + +/** + * @brief Delay for the specified number of milliseconds + * + * Busy-waits using a calibrated loop count (3600 iterations per ms) + * based on a 14.5 MHz clock. Returns immediately if ms is zero. + * + * @param ms Number of milliseconds to delay + */ +void Delay_MS(uint32_t ms); + +#endif // DELAY_H diff --git a/drivers/0x01_uart_cbm/image_def.c b/drivers/0x01_uart_cbm/image_def.c new file mode 100644 index 0000000..54b96d2 --- /dev/null +++ b/drivers/0x01_uart_cbm/image_def.c @@ -0,0 +1,48 @@ +/** + * @file image_def.c + * @brief RP2350 IMAGE_DEF block for boot ROM image recognition + * @author Kevin Thomas + * @date 2025 + * + * MIT License + * + * Copyright (c) 2025 Kevin Thomas + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include + +/** + * IMAGE_DEF block structure placed in flash. + * Must appear within the first 4 KB for the boot ROM to accept the image. + */ +__attribute__((section(".embedded_block"), used)) +const uint8_t picobin_block[] = { + // PICOBIN_BLOCK_MARKER_START (word: 0xffffded3) + 0xD3, 0xDE, 0xFF, 0xFF, + // PICOBIN_BLOCK_ITEM_1BS_IMAGE_TYPE + 0x42, 0x01, 0x21, 0x10, + // PICOBIN_BLOCK_ITEM_2BS_LAST + 0xFF, 0x01, 0x00, 0x00, + // Relative pointer to next block (loop to self) + 0x00, 0x00, 0x00, 0x00, + // PICOBIN_BLOCK_MARKER_END (word: 0xab123579) + 0x79, 0x35, 0x12, 0xAB +}; diff --git a/drivers/0x01_uart_cbm/linker.ld b/drivers/0x01_uart_cbm/linker.ld new file mode 100644 index 0000000..5859a9e --- /dev/null +++ b/drivers/0x01_uart_cbm/linker.ld @@ -0,0 +1,106 @@ +/** + * @file linker.ld + * @brief Minimal linker script for bare-metal RP2350 development + * @author Kevin Thomas + * @date 2025 + * + * MIT License + * + * Copyright (c) 2025 Kevin Thomas + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +ENTRY(Reset_Handler) + +/** + * Define memory regions. + */ +__XIP_BASE = 0x10000000; +__XIP_SIZE = 32M; + +__SRAM_BASE = 0x20000000; +__SRAM_SIZE = 512K; +__STACK_SIZE = 32K; + +MEMORY +{ + RAM (rwx) : ORIGIN = __SRAM_BASE, LENGTH = __SRAM_SIZE + FLASH (rx) : ORIGIN = __XIP_BASE, LENGTH = __XIP_SIZE +} + +/** + * Program headers. + */ +PHDRS +{ + text PT_LOAD FLAGS(5); +} + +/** + * Section placement. + */ +SECTIONS +{ + . = ORIGIN(FLASH); + + /** + * Vector table MUST be first at 0x10000000. + */ + .vectors : + { + KEEP(*(.vectors)) + } > FLASH :text + + ASSERT((ADDR(.vectors) == ORIGIN(FLASH)), + "Vector table must be at start of flash (0x10000000)") + + /** + * Text and read-only data. + */ + .text : + { + . = ALIGN(4); + *(.text*) + *(.rodata*) + KEEP(*(.init)) + KEEP(*(.fini)) + KEEP(*(.ARM.attributes)) + } > FLASH :text + + /** + * IMAGE_DEF block at end of code. + */ + .embedded_block : + { + KEEP(*(.embedded_block)) + } > FLASH :text + + /** + * Non-secure stack symbols. + */ + __StackTop = ORIGIN(RAM) + LENGTH(RAM); + __StackLimit = __StackTop - __STACK_SIZE; + __stack = __StackTop; + _stack_top = __StackTop; + + .stack (NOLOAD) : { . = ALIGN(8); } > RAM + + PROVIDE(__Vectors = ADDR(.vectors)); +} diff --git a/drivers/0x01_uart_cbm/main.c b/drivers/0x01_uart_cbm/main.c new file mode 100644 index 0000000..1515c3f --- /dev/null +++ b/drivers/0x01_uart_cbm/main.c @@ -0,0 +1,78 @@ +/** + * @file main.c + * @brief UART demonstration: echo received characters back in uppercase + * @author Kevin Thomas + * @date 2025 + * + * MIT License + * + * Copyright (c) 2025 Kevin Thomas + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * ----------------------------------------------------------------------------- + * + * Demonstrates bare-metal UART0 using the uart driver (uart.h / uart.c). + * Characters typed into a terminal via a USB-to-UART adapter are echoed + * back in uppercase, illustrating full-duplex raw UART operation at the + * register level without the Pico SDK. + * + * Wiring: + * GPIO0 (TX) -> USB-to-UART adapter RX + * GPIO1 (RX) -> USB-to-UART adapter TX + * GND -> USB-to-UART adapter GND + */ + +#include "uart.h" + +/** + * @brief Echo received characters back as uppercase + * + * @details Polls UART0 for incoming data. When a character is + * available, reads it, converts to uppercase, and echoes + * it back. Never returns. + * + * @param None + * @retval None + */ +static void _echo_uppercase(void) { + while (1) { + if (uart_driver_is_readable()) { + char c = uart_driver_getchar(); + char upper = uart_driver_to_upper(c); + uart_driver_putchar(upper); + } + } +} + +/** + * @brief Application entry point for the UART uppercase echo demo + * + * Prints two banner messages over UART0, then enters the echo loop. + * UART0 hardware initialization is performed by Reset_Handler before + * main() is called. + * + * @return int Does not return + */ +int main(void) { + uart_driver_puts("UART driver ready (115200 8N1)\r\n"); + uart_driver_puts("Type characters to echo them back in UPPERCASE:\r\n"); + _echo_uppercase(); + return 0; +} diff --git a/drivers/0x01_uart_cbm/reset.c b/drivers/0x01_uart_cbm/reset.c new file mode 100644 index 0000000..f9370f5 --- /dev/null +++ b/drivers/0x01_uart_cbm/reset.c @@ -0,0 +1,45 @@ +/** + * @file reset.c + * @brief Reset controller functions for subsystem initialization + * @author Kevin Thomas + * @date 2025 + * + * MIT License + * + * Copyright (c) 2025 Kevin Thomas + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "reset.h" +#include "constants.h" + +void Init_Subsystem(void) { + uint32_t value; + + // read RESETS->RESET value + value = RESETS->RESET; + // clear IO_BANK0 bit + value &= ~(1U << RESETS_RESET_IO_BANK0_SHIFT); + // store value into RESETS->RESET address + RESETS->RESET = value; + // wait until done + while ((RESETS->RESET_DONE & (1U << RESETS_RESET_IO_BANK0_SHIFT)) == 0) { + } +} diff --git a/drivers/0x01_uart_cbm/reset.h b/drivers/0x01_uart_cbm/reset.h new file mode 100644 index 0000000..4c51a23 --- /dev/null +++ b/drivers/0x01_uart_cbm/reset.h @@ -0,0 +1,44 @@ +/** + * @file reset.h + * @brief Reset controller functions for subsystem initialization + * @author Kevin Thomas + * @date 2025 + * + * MIT License + * + * Copyright (c) 2025 Kevin Thomas + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef RESET_H +#define RESET_H + +/** + * @brief Initialize the IO_BANK0 subsystem by clearing its reset bit + * + * Clears the IO_BANK0 reset bit in the Reset controller and waits + * until the RESET_DONE register confirms the block is out of reset. + * + * @param None + * @retval None + */ +void Init_Subsystem(void); + +#endif // RESET_H diff --git a/drivers/0x01_uart_cbm/reset_handler.c b/drivers/0x01_uart_cbm/reset_handler.c new file mode 100644 index 0000000..31de70a --- /dev/null +++ b/drivers/0x01_uart_cbm/reset_handler.c @@ -0,0 +1,50 @@ +/** + * @file reset_handler.c + * @brief Reset handler entry point after power-on or system reset + * @author Kevin Thomas + * @date 2025 + * + * MIT License + * + * Copyright (c) 2025 Kevin Thomas + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "reset_handler.h" +#include "stack.h" +#include "xosc.h" +#include "reset.h" +#include "uart.h" +#include "coprocessor.h" + +extern int main(void); + +void __attribute__((naked, noreturn)) Reset_Handler(void) { + __asm__ volatile ( + "bl Init_Stack\n\t" + "bl Init_XOSC\n\t" + "bl Enable_XOSC_Peri_Clock\n\t" + "bl Init_Subsystem\n\t" + "bl UART_Release_Reset\n\t" + "bl UART_Init\n\t" + "bl Enable_Coprocessor\n\t" + "b main\n\t" + ); +} diff --git a/drivers/0x01_uart_cbm/reset_handler.h b/drivers/0x01_uart_cbm/reset_handler.h new file mode 100644 index 0000000..af862df --- /dev/null +++ b/drivers/0x01_uart_cbm/reset_handler.h @@ -0,0 +1,45 @@ +/** + * @file reset_handler.h + * @brief Reset handler entry point after power-on or system reset + * @author Kevin Thomas + * @date 2025 + * + * MIT License + * + * Copyright (c) 2025 Kevin Thomas + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef RESET_HANDLER_H +#define RESET_HANDLER_H + +/** + * @brief Reset handler for the RP2350 + * + * Entry point after reset. Performs stack initialization, XOSC setup, + * subsystem reset release, UART initialization, coprocessor enable, + * and branches to main(). + * + * @param None + * @retval None + */ +void Reset_Handler(void) __attribute__((noreturn)); + +#endif // RESET_HANDLER_H diff --git a/drivers/0x01_uart_cbm/stack.c b/drivers/0x01_uart_cbm/stack.c new file mode 100644 index 0000000..9c09135 --- /dev/null +++ b/drivers/0x01_uart_cbm/stack.c @@ -0,0 +1,46 @@ +/** + * @file stack.c + * @brief Stack pointer initialization for MSP/PSP and their limits + * @author Kevin Thomas + * @date 2025 + * + * MIT License + * + * Copyright (c) 2025 Kevin Thomas + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "stack.h" +#include "constants.h" + +void Init_Stack(void) { + __asm__ volatile ( + "ldr r0, =%0\n\t" + "msr PSP, r0\n\t" + "ldr r0, =%1\n\t" + "msr MSPLIM, r0\n\t" + "msr PSPLIM, r0\n\t" + "ldr r0, =%0\n\t" + "msr MSP, r0\n\t" + : + : "i" (STACK_TOP), "i" (STACK_LIMIT) + : "r0" + ); +} diff --git a/drivers/0x01_uart_cbm/stack.h b/drivers/0x01_uart_cbm/stack.h new file mode 100644 index 0000000..50b31df --- /dev/null +++ b/drivers/0x01_uart_cbm/stack.h @@ -0,0 +1,44 @@ +/** + * @file stack.h + * @brief Stack pointer initialization for MSP/PSP and their limits + * @author Kevin Thomas + * @date 2025 + * + * MIT License + * + * Copyright (c) 2025 Kevin Thomas + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef STACK_H +#define STACK_H + +/** + * @brief Initialize stack pointers + * + * Sets Main and Process Stack Pointers (MSP/PSP) and their limits + * using the STACK_TOP and STACK_LIMIT values from constants.h. + * + * @param None + * @retval None + */ +void Init_Stack(void); + +#endif // STACK_H diff --git a/drivers/0x01_uart_cbm/uart.c b/drivers/0x01_uart_cbm/uart.c new file mode 100644 index 0000000..a1de708 --- /dev/null +++ b/drivers/0x01_uart_cbm/uart.c @@ -0,0 +1,165 @@ +/** + * @file uart.c + * @brief Implementation of the bare-metal UART0 driver + * @author Kevin Thomas + * @date 2025 + * + * MIT License + * + * Copyright (c) 2025 Kevin Thomas + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "uart.h" +#include "constants.h" + +#define UART_BASE ((volatile uint32_t *)UART0_BASE) + +/** + * @brief Clear the UART0 reset bit in the reset controller + * + * @details Reads RESETS->RESET, clears bit 26 (UART0), and writes + * the value back. + * + * @param None + * @retval None + */ +static void _uart_clear_reset_bit(void) { + uint32_t value; + + // read RESETS->RESET value + value = RESETS->RESET; + // clear UART0 reset bit (bit 26) + value &= ~(1U << RESETS_RESET_UART0_SHIFT); + // write value back to RESETS->RESET + RESETS->RESET = value; +} + +/** + * @brief Wait until the UART0 block is out of reset + * + * @details Polls RESETS->RESET_DONE until bit 26 (UART0) is set. + * + * @param None + * @retval None + */ +static void _uart_wait_reset_done(void) { + // loop until UART0 is out of reset + while ((RESETS->RESET_DONE & (1U << RESETS_RESET_UART0_SHIFT)) == 0) { + } +} + +/** + * @brief Configure GPIO pins 0 (TX) and 1 (RX) for UART function + * + * @details Sets IO_BANK0 FUNCSEL to UART (0x02) for both pins and + * programs the corresponding pad controls. + * + * @param None + * @retval None + */ +static void _uart_configure_pins(void) { + // FUNCSEL = 2 -> select UART function + IO_BANK0->GPIO[0].CTRL = IO_BANK0_CTRL_FUNCSEL_UART; + IO_BANK0->GPIO[1].CTRL = IO_BANK0_CTRL_FUNCSEL_UART; + // pad config value for TX (pull/func recommended) + PADS_BANK0->GPIO[0] = 0x04; + // pad config value for RX (input enable) + PADS_BANK0->GPIO[1] = 0x40; +} + +/** + * @brief Set UART0 baud rate divisors for 115200 baud at 14.5 MHz + * + * @details Programs UARTIBRD = 6 and UARTFBRD = 33 for the integer + * and fractional baud rate divisors respectively. + * + * @param None + * @retval None + */ +static void _uart_set_baud(void) { + // disable UART while configuring + UART_BASE[UART_CR_OFFSET] = 0; + // set integer baud divisor + UART_BASE[UART_IBRD_OFFSET] = 6; + // set fractional baud divisor + UART_BASE[UART_FBRD_OFFSET] = 33; +} + +/** + * @brief Configure line control and enable UART0 + * + * @details Sets 8-bit word length with FIFOs enabled, then enables + * UART0 with both TX and RX. + * + * @param None + * @retval None + */ +static void _uart_enable(void) { + // configure line control: FIFO enable + 8-bit + UART_BASE[UART_LCR_H_OFFSET] = UART_LCR_H_8N1_FIFO; + // enable UART with TX and RX enabled + UART_BASE[UART_CR_OFFSET] = UART_CR_ENABLE; +} + +void UART_Release_Reset(void) { + _uart_clear_reset_bit(); + _uart_wait_reset_done(); +} + +void UART_Init(void) { + _uart_configure_pins(); + _uart_set_baud(); + _uart_enable(); +} + +bool uart_driver_is_readable(void) { + // test bit 4, RX FIFO empty (RXFE) + return (UART_BASE[UART_FR_OFFSET] & UART_FR_RXFE_MASK) == 0; +} + +char uart_driver_getchar(void) { + // wait for RX FIFO to be not empty + while (UART_BASE[UART_FR_OFFSET] & UART_FR_RXFE_MASK) { + } + // read data from UARTDR + return (char)(UART_BASE[UART_DR_OFFSET] & 0xFF); +} + +void uart_driver_putchar(char c) { + // wait for TX FIFO to be not full + while (UART_BASE[UART_FR_OFFSET] & UART_FR_TXFF_MASK) { + } + // write data to UARTDR + UART_BASE[UART_DR_OFFSET] = (uint32_t)c; +} + +void uart_driver_puts(const char *str) { + while (*str) { + uart_driver_putchar(*str++); + } +} + +char uart_driver_to_upper(char c) { + if (c >= 'a' && c <= 'z') { + return (char)(c - 32); + } + return c; +} diff --git a/drivers/0x01_uart_cbm/uart.h b/drivers/0x01_uart_cbm/uart.h new file mode 100644 index 0000000..282570a --- /dev/null +++ b/drivers/0x01_uart_cbm/uart.h @@ -0,0 +1,111 @@ +/** + * @file uart.h + * @brief Header for bare-metal UART0 driver (raw TX/RX, GPIO 0/1) + * @author Kevin Thomas + * @date 2025 + * + * MIT License + * + * Copyright (c) 2025 Kevin Thomas + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef UART_H +#define UART_H + +#include +#include + +/** + * @brief Release UART0 from reset and wait until it is ready + * + * Clears the UART0 reset bit in the Reset controller and polls + * RESET_DONE until the UART0 block is out of reset. + * + * @param None + * @retval None + */ +void UART_Release_Reset(void); + +/** + * @brief Initialize UART0 (pins, baud divisors, line control, enable) + * + * Configures IO_BANK0 pins 0 (TX) and 1 (RX) to the UART function, + * programs pad controls, sets baud rate divisors (IBRD=6, FBRD=33 + * for 115200 baud at 14.5 MHz), configures 8N1 with FIFOs, and + * enables UART0 with TX and RX. + * + * @param None + * @retval None + */ +void UART_Init(void); + +/** + * @brief Check whether a received character is waiting in the UART FIFO + * + * Returns immediately without blocking. Use this to poll for incoming + * data before calling uart_driver_getchar(). + * + * @return bool true if at least one byte is available, false otherwise + */ +bool uart_driver_is_readable(void); + +/** + * @brief Read one character from UART0 (blocking) + * + * Blocks until a byte arrives in the receive FIFO, then returns it. + * Prefer pairing with uart_driver_is_readable() to avoid indefinite blocking. + * + * @return char The received character + */ +char uart_driver_getchar(void); + +/** + * @brief Transmit one character over UART0 (blocking) + * + * Waits until the transmit FIFO has space, then writes the character + * to UARTDR. + * + * @param c Character to transmit + */ +void uart_driver_putchar(char c); + +/** + * @brief Transmit a null-terminated string over UART0 + * + * Calls uart_driver_putchar() for every character in the string up to + * and not including the null terminator. + * + * @param str Pointer to the null-terminated ASCII string to send + */ +void uart_driver_puts(const char *str); + +/** + * @brief Convert a lowercase ASCII character to uppercase + * + * Returns the uppercase equivalent if the character is in 'a'-'z'; + * all other characters are passed through unchanged. + * + * @param c Input character + * @return char Uppercase equivalent, or the original character + */ +char uart_driver_to_upper(char c); + +#endif // UART_H diff --git a/drivers/0x01_uart_cbm/uf2conv.py b/drivers/0x01_uart_cbm/uf2conv.py new file mode 100644 index 0000000..d6dd7a8 --- /dev/null +++ b/drivers/0x01_uart_cbm/uf2conv.py @@ -0,0 +1,365 @@ +#!/usr/bin/env python3 +import sys +import struct +import subprocess +import re +import os +import os.path +import argparse +import json +from time import sleep + + +UF2_MAGIC_START0 = 0x0A324655 # "UF2\n" +UF2_MAGIC_START1 = 0x9E5D5157 # Randomly selected +UF2_MAGIC_END = 0x0AB16F30 # Ditto + +INFO_FILE = "/INFO_UF2.TXT" + +appstartaddr = 0x2000 +familyid = 0x0 + + +def is_uf2(buf): + w = struct.unpack(" 476: + assert False, "Invalid UF2 data size at " + ptr + newaddr = hd[3] + if (hd[2] & 0x2000) and (currfamilyid == None): + currfamilyid = hd[7] + if curraddr == None or ((hd[2] & 0x2000) and hd[7] != currfamilyid): + currfamilyid = hd[7] + curraddr = newaddr + if familyid == 0x0 or familyid == hd[7]: + appstartaddr = newaddr + padding = newaddr - curraddr + if padding < 0: + assert False, "Block out of order at " + ptr + if padding > 10*1024*1024: + assert False, "More than 10M of padding needed at " + ptr + if padding % 4 != 0: + assert False, "Non-word padding size at " + ptr + while padding > 0: + padding -= 4 + outp.append(b"\x00\x00\x00\x00") + if familyid == 0x0 or ((hd[2] & 0x2000) and familyid == hd[7]): + outp.append(block[32 : 32 + datalen]) + curraddr = newaddr + datalen + if hd[2] & 0x2000: + if hd[7] in families_found.keys(): + if families_found[hd[7]] > newaddr: + families_found[hd[7]] = newaddr + else: + families_found[hd[7]] = newaddr + if prev_flag == None: + prev_flag = hd[2] + if prev_flag != hd[2]: + all_flags_same = False + if blockno == (numblocks - 1): + print("--- UF2 File Header Info ---") + families = load_families() + for family_hex in families_found.keys(): + family_short_name = "" + for name, value in families.items(): + if value == family_hex: + family_short_name = name + print("Family ID is {:s}, hex value is 0x{:08x}".format(family_short_name,family_hex)) + print("Target Address is 0x{:08x}".format(families_found[family_hex])) + if all_flags_same: + print("All block flag values consistent, 0x{:04x}".format(hd[2])) + else: + print("Flags were not all the same") + print("----------------------------") + if len(families_found) > 1 and familyid == 0x0: + outp = [] + appstartaddr = 0x0 + return b"".join(outp) + +def convert_to_carray(file_content): + outp = "const unsigned long bindata_len = %d;\n" % len(file_content) + outp += "const unsigned char bindata[] __attribute__((aligned(16))) = {" + for i in range(len(file_content)): + if i % 16 == 0: + outp += "\n" + outp += "0x%02x, " % file_content[i] + outp += "\n};\n" + return bytes(outp, "utf-8") + +def convert_to_uf2(file_content): + global familyid + datapadding = b"" + while len(datapadding) < 512 - 256 - 32 - 4: + datapadding += b"\x00\x00\x00\x00" + numblocks = (len(file_content) + 255) // 256 + outp = [] + for blockno in range(numblocks): + ptr = 256 * blockno + chunk = file_content[ptr:ptr + 256] + flags = 0x0 + if familyid: + flags |= 0x2000 + hd = struct.pack(b" + +extern uint32_t _stack_top; +extern void Reset_Handler(void); + +typedef void (*vector_func_t)(void); + +/** + * Vector table placed in .vectors section. + * The Thumb bit (bit 0 = 1) is automatically set by the linker + * for function pointers in Thumb mode. + */ +__attribute__((section(".vectors"), used)) +const void *_vectors[2] = { + &_stack_top, + Reset_Handler +}; diff --git a/drivers/0x01_uart_cbm/xosc.c b/drivers/0x01_uart_cbm/xosc.c new file mode 100644 index 0000000..f8f3228 --- /dev/null +++ b/drivers/0x01_uart_cbm/xosc.c @@ -0,0 +1,54 @@ +/** + * @file xosc.c + * @brief External crystal oscillator (XOSC) initialization and clock enable + * @author Kevin Thomas + * @date 2025 + * + * MIT License + * + * Copyright (c) 2025 Kevin Thomas + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "xosc.h" +#include "constants.h" + +void Init_XOSC(void) { + // set delay 50,000 cycles + XOSC->STARTUP = 0x00C4U; + // set 1_15MHz, freq range, actual 14.5MHz + XOSC->CTRL = 0x00FABAA0U; + // wait until stable bit is set + while ((XOSC->STATUS & (1U << XOSC_STATUS_STABLE_SHIFT)) == 0) { + } +} + +void Enable_XOSC_Peri_Clock(void) { + uint32_t value; + + // read CLK_PERI_CTRL value + value = CLOCKS->CLK_PERI_CTRL; + // set ENABLE bit + value |= (1U << CLOCKS_CLK_PERI_CTRL_ENABLE_SHIFT); + // set AUXSRC: XOSC_CLKSRC + value |= (CLOCKS_CLK_PERI_CTRL_AUXSRC_XOSC << CLOCKS_CLK_PERI_CTRL_AUXSRC_SHIFT); + // store value into CLK_PERI_CTRL + CLOCKS->CLK_PERI_CTRL = value; +} diff --git a/drivers/0x01_uart_cbm/xosc.h b/drivers/0x01_uart_cbm/xosc.h new file mode 100644 index 0000000..ca2b9e7 --- /dev/null +++ b/drivers/0x01_uart_cbm/xosc.h @@ -0,0 +1,55 @@ +/** + * @file xosc.h + * @brief External crystal oscillator (XOSC) initialization and clock enable + * @author Kevin Thomas + * @date 2025 + * + * MIT License + * + * Copyright (c) 2025 Kevin Thomas + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef XOSC_H +#define XOSC_H + +/** + * @brief Initialize the external crystal oscillator and wait until stable + * + * Configures the XOSC startup delay and frequency range, then polls + * the status register until the STABLE bit is set. + * + * @param None + * @retval None + */ +void Init_XOSC(void); + +/** + * @brief Enable the XOSC peripheral clock + * + * Sets the peripheral clock to use XOSC as its auxiliary source and + * enables it via CLK_PERI_CTRL. + * + * @param None + * @retval None + */ +void Enable_XOSC_Peri_Clock(void); + +#endif // XOSC_H diff --git a/drivers/0x02_blink_cbm/.gitattributes b/drivers/0x02_blink_cbm/.gitattributes new file mode 100644 index 0000000..91c1527 --- /dev/null +++ b/drivers/0x02_blink_cbm/.gitattributes @@ -0,0 +1,11 @@ +# C files +*.c linguist-language=C + +# Exclude from language statistics +*.ld linguist-vendored +*.bat linguist-vendored +*.py linguist-vendored +linker.ld linguist-vendored +build.bat linguist-vendored +clean.bat linguist-vendored +uf2conv.py linguist-vendored diff --git a/drivers/0x02_blink_cbm/.gitignore b/drivers/0x02_blink_cbm/.gitignore new file mode 100644 index 0000000..8a68f1b --- /dev/null +++ b/drivers/0x02_blink_cbm/.gitignore @@ -0,0 +1,10 @@ +# Build artifacts +*.o +*.elf +*.bin +*.uf2 +compile_commands.json + +# OS files +.DS_Store +Thumbs.db diff --git a/drivers/0x02_blink_cbm/.vscode/c_cpp_properties.json b/drivers/0x02_blink_cbm/.vscode/c_cpp_properties.json new file mode 100644 index 0000000..094f8d7 --- /dev/null +++ b/drivers/0x02_blink_cbm/.vscode/c_cpp_properties.json @@ -0,0 +1,25 @@ +{ + "configurations": [ + { + "name": "ARM GCC", + "includePath": [ + "${workspaceFolder}/**" + ], + "defines": [ + "__GNUC__", + "__ARM_ARCH_8M_MAIN__", + "__ARMCC_VERSION" + ], + "compilerPath": "${env:USERPROFILE}/.pico-sdk/toolchain/14_2_Rel1/bin/arm-none-eabi-gcc.exe", + "compileCommands": "${workspaceFolder}/compile_commands.json", + "cStandard": "c11", + "cppStandard": "c++17", + "intelliSenseMode": "gcc-arm", + "compilerArgs": [ + "-mcpu=cortex-m33", + "-mthumb" + ] + } + ], + "version": 4 +} diff --git a/drivers/0x02_blink_cbm/.vscode/extensions.json b/drivers/0x02_blink_cbm/.vscode/extensions.json new file mode 100644 index 0000000..fe41ced --- /dev/null +++ b/drivers/0x02_blink_cbm/.vscode/extensions.json @@ -0,0 +1,9 @@ +{ + "recommendations": [ + "marus25.cortex-debug", + "ms-vscode.cpptools", + "ms-vscode.cpptools-extension-pack", + "ms-vscode.vscode-serial-monitor", + "raspberry-pi.raspberry-pi-pico" + ] +} diff --git a/drivers/0x02_blink_cbm/.vscode/launch.json b/drivers/0x02_blink_cbm/.vscode/launch.json new file mode 100644 index 0000000..e483958 --- /dev/null +++ b/drivers/0x02_blink_cbm/.vscode/launch.json @@ -0,0 +1,37 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Debug RP2350 (OpenOCD)", + "cwd": "${workspaceFolder}", + "executable": "${workspaceFolder}/blink.elf", + "request": "launch", + "type": "cortex-debug", + "servertype": "openocd", + "serverpath": "${env:USERPROFILE}/.pico-sdk/openocd/0.12.0+dev/openocd.exe", + "searchDir": ["${env:USERPROFILE}/.pico-sdk/openocd/0.12.0+dev/scripts"], + "gdbPath": "${env:USERPROFILE}/.pico-sdk/toolchain/14_2_Rel1/bin/arm-none-eabi-gdb.exe", + "device": "RP2350", + "configFiles": [ + "interface/cmsis-dap.cfg", + "target/rp2350.cfg" + ], + "svdFile": "${env:USERPROFILE}/.pico-sdk/sdk/2.2.0/src/rp2350/hardware_regs/RP2350.svd", + "overrideLaunchCommands": [ + "set arch armv8-m.main", + "set output-radix 16", + "monitor reset init", + "load", + "monitor reset halt" + ], + "openOCDPreConfigLaunchCommands": [ + "set USE_CORE { cm0 cm1 }" + ], + "openOCDLaunchCommands": [ + "adapter speed 5000" + ], + "preLaunchTask": "Compile Project", + "showDevDebugOutput": "raw" + } + ] +} diff --git a/drivers/0x02_blink_cbm/.vscode/settings.json b/drivers/0x02_blink_cbm/.vscode/settings.json new file mode 100644 index 0000000..95be83b --- /dev/null +++ b/drivers/0x02_blink_cbm/.vscode/settings.json @@ -0,0 +1,40 @@ +{ + "cmake.showSystemKits": false, + "cmake.options.statusBarVisibility": "hidden", + "cmake.options.advanced": { + "build": { + "statusBarVisibility": "hidden" + }, + "launch": { + "statusBarVisibility": "hidden" + }, + "debug": { + "statusBarVisibility": "hidden" + } + }, + "cmake.configureOnEdit": false, + "cmake.automaticReconfigure": false, + "cmake.configureOnOpen": false, + "cmake.generator": "Ninja", + "cmake.cmakePath": "${userHome}/.pico-sdk/cmake/v3.31.5/bin/cmake", + "C_Cpp.debugShortcut": false, + "terminal.integrated.env.windows": { + "PICO_SDK_PATH": "${env:USERPROFILE}/.pico-sdk/sdk/2.2.0", + "PICO_TOOLCHAIN_PATH": "${env:USERPROFILE}/.pico-sdk/toolchain/14_2_Rel1", + "Path": "${env:USERPROFILE}/.pico-sdk/toolchain/14_2_Rel1/bin;${env:USERPROFILE}/.pico-sdk/picotool/2.2.0-a4/picotool;${env:USERPROFILE}/.pico-sdk/cmake/v3.31.5/bin;${env:USERPROFILE}/.pico-sdk/ninja/v1.12.1;${env:PATH}" + }, + "terminal.integrated.env.osx": { + "PICO_SDK_PATH": "${env:HOME}/.pico-sdk/sdk/2.2.0", + "PICO_TOOLCHAIN_PATH": "${env:HOME}/.pico-sdk/toolchain/14_2_Rel1", + "PATH": "${env:HOME}/.pico-sdk/toolchain/14_2_Rel1/bin:${env:HOME}/.pico-sdk/picotool/2.2.0-a4/picotool:${env:HOME}/.pico-sdk/cmake/v3.31.5/bin:${env:HOME}/.pico-sdk/ninja/v1.12.1:${env:PATH}" + }, + "terminal.integrated.env.linux": { + "PICO_SDK_PATH": "${env:HOME}/.pico-sdk/sdk/2.2.0", + "PICO_TOOLCHAIN_PATH": "${env:HOME}/.pico-sdk/toolchain/14_2_Rel1", + "PATH": "${env:HOME}/.pico-sdk/toolchain/14_2_Rel1/bin:${env:HOME}/.pico-sdk/picotool/2.2.0-a4/picotool:${env:HOME}/.pico-sdk/cmake/v3.31.5/bin:${env:HOME}/.pico-sdk/ninja/v1.12.1:${env:PATH}" + }, + "raspberry-pi-pico.cmakeAutoConfigure": true, + "raspberry-pi-pico.useCmakeTools": false, + "raspberry-pi-pico.cmakePath": "${HOME}/.pico-sdk/cmake/v3.31.5/bin/cmake", + "raspberry-pi-pico.ninjaPath": "${HOME}/.pico-sdk/ninja/v1.12.1/ninja" +} diff --git a/drivers/0x02_blink_cbm/.vscode/tasks.json b/drivers/0x02_blink_cbm/.vscode/tasks.json new file mode 100644 index 0000000..50178c0 --- /dev/null +++ b/drivers/0x02_blink_cbm/.vscode/tasks.json @@ -0,0 +1,107 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "Compile Project", + "type": "shell", + "command": ".\\build.bat", + "group": { + "kind": "build", + "isDefault": true + }, + "presentation": { + "reveal": "always", + "panel": "dedicated" + }, + "problemMatcher": "$gcc" + }, + { + "label": "Clean Project", + "type": "shell", + "command": ".\\clean.bat", + "group": "build", + "presentation": { + "reveal": "always", + "panel": "dedicated" + }, + "problemMatcher": [] + }, + { + "label": "Run Project", + "type": "shell", + "command": "${env:USERPROFILE}/.pico-sdk/picotool/2.2.0-a4/picotool/picotool.exe", + "args": [ + "load", + "blink.uf2", + "-fx" + ], + "presentation": { + "reveal": "always", + "panel": "dedicated" + }, + "problemMatcher": [], + "dependsOn": ["Compile Project"] + }, + { + "label": "Flash", + "type": "shell", + "command": "${env:USERPROFILE}/.pico-sdk/openocd/0.12.0+dev/openocd.exe", + "args": [ + "-s", + "${env:USERPROFILE}/.pico-sdk/openocd/0.12.0+dev/scripts", + "-f", + "interface/cmsis-dap.cfg", + "-f", + "target/rp2350.cfg", + "-c", + "adapter speed 5000; program blink.elf verify reset exit" + ], + "problemMatcher": [], + "dependsOn": ["Compile Project"] + }, + { + "label": "Rescue Reset", + "type": "process", + "command": "${userHome}/.pico-sdk/openocd/0.12.0+dev/openocd.exe", + "args": [ + "-s", + "${userHome}/.pico-sdk/openocd/0.12.0+dev/scripts", + "-f", + "interface/cmsis-dap.cfg", + "-f", + "target/${command:raspberry-pi-pico.getChip}-rescue.cfg", + "-c", + "adapter speed 5000; reset halt; exit" + ], + "problemMatcher": [], + "windows": { + "command": "${env:USERPROFILE}/.pico-sdk/openocd/0.12.0+dev/openocd.exe" + } + }, + { + "label": "RISC-V Reset (RP2350)", + "type": "process", + "command": "${userHome}/.pico-sdk/openocd/0.12.0+dev/openocd.exe", + "args": [ + "-s", + "${userHome}/.pico-sdk/openocd/0.12.0+dev/scripts", + "-c", + "set USE_CORE { rv0 rv1 cm0 cm1 }", + "-f", + "interface/cmsis-dap.cfg", + "-f", + "target/rp2350.cfg", + "-c", + "adapter speed 5000; init;", + "-c", + "write_memory 0x40120158 8 { 0x3 }; echo [format \"Info : ARCHSEL 0x%02x\" [read_memory 0x40120158 8 1]];", + "-c", + "reset halt; targets rp2350.rv0; echo [format \"Info : ARCHSEL_STATUS 0x%02x\" [read_memory 0x4012015C 8 1]]; exit" + ], + "problemMatcher": [], + "windows": { + "command": "${env:USERPROFILE}/.pico-sdk/openocd/0.12.0+dev/openocd.exe" + } + } + ] +} diff --git a/drivers/0x02_blink_cbm/blink.c b/drivers/0x02_blink_cbm/blink.c new file mode 100644 index 0000000..c20f285 --- /dev/null +++ b/drivers/0x02_blink_cbm/blink.c @@ -0,0 +1,52 @@ +/** + * @file blink.c + * @brief Implementation of the GPIO output / LED blink driver + * @author Kevin Thomas + * @date 2025 + * + * MIT License + * + * Copyright (c) 2025 Kevin Thomas + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "blink.h" +#include "gpio.h" + +void blink_init(uint32_t pin) { + GPIO_Config(pin); + GPIO_Clear(pin); +} + +void blink_on(uint32_t pin) { + GPIO_Set(pin); +} + +void blink_off(uint32_t pin) { + GPIO_Clear(pin); +} + +void blink_toggle(uint32_t pin) { + GPIO_Toggle(pin); +} + +bool blink_get_state(uint32_t pin) { + return GPIO_Get(pin); +} diff --git a/drivers/0x02_blink_cbm/blink.h b/drivers/0x02_blink_cbm/blink.h new file mode 100644 index 0000000..f7da4e9 --- /dev/null +++ b/drivers/0x02_blink_cbm/blink.h @@ -0,0 +1,78 @@ +/** + * @file blink.h + * @brief Header for GPIO output / LED blink driver + * @author Kevin Thomas + * @date 2025 + * + * MIT License + * + * Copyright (c) 2025 Kevin Thomas + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef BLINK_H +#define BLINK_H + +#include +#include + +/** + * @brief Initialize a GPIO pin as a push-pull digital output + * + * Configures the pad control, sets IO_BANK0 FUNCSEL to SIO, and + * enables the output driver. The initial drive level is low (LED off). + * + * @param pin GPIO pin number to configure as a digital output + */ +void blink_init(uint32_t pin); + +/** + * @brief Drive the output pin high (LED on) + * + * @param pin GPIO pin number previously initialized with blink_init() + */ +void blink_on(uint32_t pin); + +/** + * @brief Drive the output pin low (LED off) + * + * @param pin GPIO pin number previously initialized with blink_init() + */ +void blink_off(uint32_t pin); + +/** + * @brief Toggle the current state of the output pin + * + * Reads the current GPIO output level and inverts it. If the LED was on + * it is turned off, and vice versa. + * + * @param pin GPIO pin number previously initialized with blink_init() + */ +void blink_toggle(uint32_t pin); + +/** + * @brief Query the current drive state of the output pin + * + * @param pin GPIO pin number previously initialized with blink_init() + * @return bool true if the pin is driven high, false if driven low + */ +bool blink_get_state(uint32_t pin); + +#endif // BLINK_H diff --git a/drivers/0x02_blink_cbm/build.bat b/drivers/0x02_blink_cbm/build.bat new file mode 100644 index 0000000..f09f808 --- /dev/null +++ b/drivers/0x02_blink_cbm/build.bat @@ -0,0 +1,103 @@ +@echo off +REM ============================================================================== +REM FILE: build.bat +REM +REM DESCRIPTION: +REM Build script for RP2350 bare-metal C Blink driver. +REM +REM BRIEF: +REM Automates the process of compiling, linking, and generating UF2 firmware. +REM +REM AUTHOR: Kevin Thomas +REM CREATION DATE: 2025 +REM UPDATE DATE: 2025 +REM ============================================================================== + +echo Building C bare-metal version... + +REM ============================================================================== +REM Compile C Source Files +REM ============================================================================== +arm-none-eabi-gcc -mcpu=cortex-m33 -mthumb -Og -g3 -Wall -Wextra -ffunction-sections -fdata-sections -c vector_table.c -o vector_table.o +if errorlevel 1 goto error + +arm-none-eabi-gcc -mcpu=cortex-m33 -mthumb -Og -g3 -Wall -Wextra -ffunction-sections -fdata-sections -c reset_handler.c -o reset_handler.o +if errorlevel 1 goto error + +arm-none-eabi-gcc -mcpu=cortex-m33 -mthumb -Og -g3 -Wall -Wextra -ffunction-sections -fdata-sections -c stack.c -o stack.o +if errorlevel 1 goto error + +arm-none-eabi-gcc -mcpu=cortex-m33 -mthumb -Og -g3 -Wall -Wextra -ffunction-sections -fdata-sections -c xosc.c -o xosc.o +if errorlevel 1 goto error + +arm-none-eabi-gcc -mcpu=cortex-m33 -mthumb -Og -g3 -Wall -Wextra -ffunction-sections -fdata-sections -c reset.c -o reset.o +if errorlevel 1 goto error + +arm-none-eabi-gcc -mcpu=cortex-m33 -mthumb -Og -g3 -Wall -Wextra -ffunction-sections -fdata-sections -c coprocessor.c -o coprocessor.o +if errorlevel 1 goto error + +arm-none-eabi-gcc -mcpu=cortex-m33 -mthumb -Og -g3 -Wall -Wextra -ffunction-sections -fdata-sections -c uart.c -o uart.o +if errorlevel 1 goto error + +arm-none-eabi-gcc -mcpu=cortex-m33 -mthumb -Og -g3 -Wall -Wextra -ffunction-sections -fdata-sections -c gpio.c -o gpio.o +if errorlevel 1 goto error + +arm-none-eabi-gcc -mcpu=cortex-m33 -mthumb -Og -g3 -Wall -Wextra -ffunction-sections -fdata-sections -c blink.c -o blink.o +if errorlevel 1 goto error + +arm-none-eabi-gcc -mcpu=cortex-m33 -mthumb -Og -g3 -Wall -Wextra -ffunction-sections -fdata-sections -c delay.c -o delay.o +if errorlevel 1 goto error + +arm-none-eabi-gcc -mcpu=cortex-m33 -mthumb -Og -g3 -Wall -Wextra -ffunction-sections -fdata-sections -c main.c -o main.o +if errorlevel 1 goto error + +arm-none-eabi-gcc -mcpu=cortex-m33 -mthumb -Og -g3 -Wall -Wextra -ffunction-sections -fdata-sections -c image_def.c -o image_def.o +if errorlevel 1 goto error + +REM ============================================================================== +REM Link Object Files +REM ============================================================================== +arm-none-eabi-gcc -mcpu=cortex-m33 -mthumb -T linker.ld -nostdlib -Wl,--gc-sections vector_table.o reset_handler.o stack.o xosc.o reset.o coprocessor.o uart.o gpio.o blink.o delay.o main.o image_def.o -o blink.elf +if errorlevel 1 goto error + +REM ============================================================================== +REM Create Raw Binary from ELF +REM ============================================================================== +arm-none-eabi-objcopy -O binary blink.elf blink.bin +if errorlevel 1 goto error + +REM ============================================================================== +REM Create UF2 Image for RP2350 +REM -b 0x10000000 : base address +REM -f 0xe48bff59 : RP2350 family ID +REM ============================================================================== +python uf2conv.py -b 0x10000000 -f 0xe48bff59 -o blink.uf2 blink.bin +if errorlevel 1 goto error + +REM ============================================================================== +REM Success Message and Flashing Instructions +REM ============================================================================== +echo. +echo ================================= +echo SUCCESS! Created blink.uf2 +echo ================================= +echo. +echo To flash via UF2: +echo 1. Hold BOOTSEL button +echo 2. Plug in USB +echo 3. Copy blink.uf2 to RP2350 drive +echo. +echo To flash via OpenOCD (debug probe): +echo openocd -f interface/cmsis-dap.cfg -f target/rp2350.cfg -c "adapter speed 5000" -c "program blink.elf verify reset exit" +echo. +goto end + +REM ============================================================================== +REM Error Handling +REM ============================================================================== +:error +echo. +echo BUILD FAILED! +echo. + +:end diff --git a/drivers/0x02_blink_cbm/clean.bat b/drivers/0x02_blink_cbm/clean.bat new file mode 100644 index 0000000..f25812f --- /dev/null +++ b/drivers/0x02_blink_cbm/clean.bat @@ -0,0 +1,30 @@ +@echo off +REM ============================================================================== +REM FILE: clean.bat +REM +REM DESCRIPTION: +REM Clean script for RP2350 bare-metal C Blink driver. +REM +REM BRIEF: +REM Removes all build artifacts and generated files. +REM +REM AUTHOR: Kevin Thomas +REM CREATION DATE: 2025 +REM UPDATE DATE: 2025 +REM ============================================================================== + +echo Cleaning build artifacts... + +REM Remove object files +if exist *.o del /Q *.o + +REM Remove ELF file +if exist blink.elf del /Q blink.elf + +REM Remove binary file +if exist blink.bin del /Q blink.bin + +REM Remove UF2 file +if exist blink.uf2 del /Q blink.uf2 + +echo Clean complete! diff --git a/drivers/0x02_blink_cbm/constants.h b/drivers/0x02_blink_cbm/constants.h new file mode 100644 index 0000000..1b81716 --- /dev/null +++ b/drivers/0x02_blink_cbm/constants.h @@ -0,0 +1,214 @@ +/** + * @file constants.h + * @brief Memory-mapped register structures and peripheral base addresses + * @author Kevin Thomas + * @date 2025 + * + * MIT License + * + * Copyright (c) 2025 Kevin Thomas + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef CONSTANTS_H +#define CONSTANTS_H + +#include + +/** + * Stack addresses. + */ +#define STACK_TOP 0x20082000U +#define STACK_LIMIT 0x2007A000U + +/** + * XOSC (External Crystal Oscillator) Register Structure. + */ +typedef struct { + volatile uint32_t CTRL; /**< 0x00: Control register */ + volatile uint32_t STATUS; /**< 0x04: Status register */ + volatile uint32_t DORMANT; /**< 0x08: Dormant mode */ + volatile uint32_t STARTUP; /**< 0x0C: Startup delay */ + volatile uint32_t RESERVED[3]; /**< 0x10-0x18: Reserved */ + volatile uint32_t COUNT; /**< 0x1C: Frequency count */ +} xosc_hw_t; + +/** + * XOSC base address and pointer. + */ +#define XOSC_BASE 0x40048000U +#define XOSC ((xosc_hw_t *)XOSC_BASE) + +/** + * XOSC status bit definitions. + */ +#define XOSC_STATUS_STABLE_SHIFT 31U + +/** + * CPACR (Coprocessor Access Control Register) in PPB. + */ +#define PPB_BASE 0xE0000000U +#define CPACR ((volatile uint32_t *)(PPB_BASE + 0x0ED88U)) + +/** + * Coprocessor access control bit definitions. + */ +#define CPACR_CP0_SHIFT 0U +#define CPACR_CP1_SHIFT 1U + +/** + * CLOCKS Register Structure. + */ +typedef struct { + volatile uint32_t RESERVED0[18]; /**< 0x00-0x44: Other clock registers */ + volatile uint32_t CLK_PERI_CTRL; /**< 0x48: Peripheral clock control */ +} clocks_hw_t; + +/** + * CLOCKS base address and pointer. + */ +#define CLOCKS_BASE 0x40010000U +#define CLOCKS ((clocks_hw_t *)CLOCKS_BASE) + +/** + * Clock control bit definitions. + */ +#define CLOCKS_CLK_PERI_CTRL_ENABLE_SHIFT 11U +#define CLOCKS_CLK_PERI_CTRL_AUXSRC_SHIFT 5U +#define CLOCKS_CLK_PERI_CTRL_AUXSRC_XOSC 4U + +/** + * RESETS Register Structure. + */ +typedef struct { + volatile uint32_t RESET; /**< 0x00: Reset control */ + volatile uint32_t WDSEL; /**< 0x04: Watchdog select */ + volatile uint32_t RESET_DONE; /**< 0x08: Reset done status */ +} resets_hw_t; + +/** + * RESETS base address and pointer. + */ +#define RESETS_BASE 0x40020000U +#define RESETS ((resets_hw_t *)RESETS_BASE) +#define RESETS_RESET_CLEAR ((volatile uint32_t *)(RESETS_BASE + 0x3000U)) + +/** + * Reset control bit definitions. + */ +#define RESETS_RESET_IO_BANK0_SHIFT 6U +#define RESETS_RESET_UART0_SHIFT 26U + +/** + * IO_BANK0 GPIO Control Register (one per GPIO). + */ +typedef struct { + volatile uint32_t STATUS; /**< 0x00: GPIO status */ + volatile uint32_t CTRL; /**< 0x04: GPIO control */ +} io_bank0_gpio_ctrl_t; + +/** + * IO_BANK0 Register Structure. + */ +typedef struct { + io_bank0_gpio_ctrl_t GPIO[30]; /**< 0x000-0x0E8: GPIO 0-29 */ +} io_bank0_hw_t; + +/** + * IO_BANK0 base address and pointer. + */ +#define IO_BANK0_BASE 0x40028000U +#define IO_BANK0 ((io_bank0_hw_t *)IO_BANK0_BASE) + +/** + * GPIO control bit definitions. + */ +#define IO_BANK0_CTRL_FUNCSEL_MASK 0x1FU +#define IO_BANK0_CTRL_FUNCSEL_UART 0x02U +#define IO_BANK0_CTRL_FUNCSEL_SIO 0x05U + +/** + * PADS_BANK0 Register Structure. + */ +typedef struct { + volatile uint32_t VOLTAGE_SELECT; /**< 0x00: Voltage select */ + volatile uint32_t GPIO[30]; /**< 0x04-0x78: GPIO 0-29 pad control */ +} pads_bank0_hw_t; + +/** + * PADS_BANK0 base address and pointer. + */ +#define PADS_BANK0_BASE 0x40038000U +#define PADS_BANK0 ((pads_bank0_hw_t *)PADS_BANK0_BASE) + +/** + * Pad control bit definitions. + */ +#define PADS_BANK0_OD_SHIFT 7U +#define PADS_BANK0_IE_SHIFT 6U +#define PADS_BANK0_ISO_SHIFT 8U + +/** + * UART0 base address. + */ +#define UART0_BASE 0x40070000U + +/** + * UART register offsets (as word indices from UART0_BASE). + */ +#define UART_DR_OFFSET (0x00U / 4U) +#define UART_FR_OFFSET (0x18U / 4U) +#define UART_IBRD_OFFSET (0x24U / 4U) +#define UART_FBRD_OFFSET (0x28U / 4U) +#define UART_LCR_H_OFFSET (0x2CU / 4U) +#define UART_CR_OFFSET (0x30U / 4U) + +/** + * UART flag register bit definitions. + */ +#define UART_FR_TXFF_MASK 32U +#define UART_FR_RXFE_MASK 16U + +/** + * UART line control and enable values. + */ +#define UART_LCR_H_8N1_FIFO 0x70U +#define UART_CR_ENABLE ((3U << 8) | 1U) + +/** + * GPIO pin definitions. + */ +#define LED_PIN 25U + +/** + * SIO (Single-cycle IO) base address. + */ +#define SIO_BASE 0xD0000000U + +/** + * SIO GPIO output register offsets (as word indices). + */ +#define SIO_GPIO_OUT_SET_OFFSET (0x018U / 4U) +#define SIO_GPIO_OUT_CLR_OFFSET (0x020U / 4U) +#define SIO_GPIO_OUT_XOR_OFFSET (0x028U / 4U) +#define SIO_GPIO_OE_SET_OFFSET (0x038U / 4U) +#define SIO_GPIO_IN_OFFSET (0x008U / 4U) + +#endif // CONSTANTS_H diff --git a/drivers/0x02_blink_cbm/coprocessor.c b/drivers/0x02_blink_cbm/coprocessor.c new file mode 100644 index 0000000..f909edf --- /dev/null +++ b/drivers/0x02_blink_cbm/coprocessor.c @@ -0,0 +1,48 @@ +/** + * @file coprocessor.c + * @brief Coprocessor access control enable functions + * @author Kevin Thomas + * @date 2025 + * + * MIT License + * + * Copyright (c) 2025 Kevin Thomas + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "coprocessor.h" +#include "constants.h" + +void Enable_Coprocessor(void) { + uint32_t value; + + // read CPACR value + value = *CPACR; + // set CP1: Ctrl access priv coproc 1 bit + value |= (1U << CPACR_CP1_SHIFT); + // set CP0: Ctrl access priv coproc 0 bit + value |= (1U << CPACR_CP0_SHIFT); + // store value into CPACR + *CPACR = value; + // data sync barrier + __asm__ volatile ("dsb"); + // instruction sync barrier + __asm__ volatile ("isb"); +} diff --git a/drivers/0x02_blink_cbm/coprocessor.h b/drivers/0x02_blink_cbm/coprocessor.h new file mode 100644 index 0000000..5c998a7 --- /dev/null +++ b/drivers/0x02_blink_cbm/coprocessor.h @@ -0,0 +1,45 @@ +/** + * @file coprocessor.h + * @brief Coprocessor access control enable functions + * @author Kevin Thomas + * @date 2025 + * + * MIT License + * + * Copyright (c) 2025 Kevin Thomas + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef COPROCESSOR_H +#define COPROCESSOR_H + +/** + * @brief Enable coprocessor access via CPACR + * + * Grants full access to coprocessors 0 and 1 by setting the + * corresponding bits in the Coprocessor Access Control Register, + * then issues DSB and ISB barriers. + * + * @param None + * @retval None + */ +void Enable_Coprocessor(void); + +#endif // COPROCESSOR_H diff --git a/drivers/0x02_blink_cbm/delay.c b/drivers/0x02_blink_cbm/delay.c new file mode 100644 index 0000000..e4a3672 --- /dev/null +++ b/drivers/0x02_blink_cbm/delay.c @@ -0,0 +1,46 @@ +/** + * @file delay.c + * @brief Millisecond delay functions based on a 14.5 MHz clock + * @author Kevin Thomas + * @date 2025 + * + * MIT License + * + * Copyright (c) 2025 Kevin Thomas + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "delay.h" + +void Delay_MS(uint32_t ms) { + if (ms == 0) { + return; + } + __asm__ volatile ( + "mov r4, #3600\n\t" + "mul r5, %0, r4\n\t" + "1:\n\t" + "subs r5, #1\n\t" + "bne 1b\n\t" + : + : "r" (ms) + : "r4", "r5", "cc" + ); +} diff --git a/drivers/0x02_blink_cbm/delay.h b/drivers/0x02_blink_cbm/delay.h new file mode 100644 index 0000000..88bfcef --- /dev/null +++ b/drivers/0x02_blink_cbm/delay.h @@ -0,0 +1,45 @@ +/** + * @file delay.h + * @brief Millisecond delay functions based on a 14.5 MHz clock + * @author Kevin Thomas + * @date 2025 + * + * MIT License + * + * Copyright (c) 2025 Kevin Thomas + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef DELAY_H +#define DELAY_H + +#include + +/** + * @brief Delay for the specified number of milliseconds + * + * Busy-waits using a calibrated loop count (3600 iterations per ms) + * based on a 14.5 MHz clock. Returns immediately if ms is zero. + * + * @param ms Number of milliseconds to delay + */ +void Delay_MS(uint32_t ms); + +#endif // DELAY_H diff --git a/drivers/0x02_blink_cbm/gpio.c b/drivers/0x02_blink_cbm/gpio.c new file mode 100644 index 0000000..018fdd8 --- /dev/null +++ b/drivers/0x02_blink_cbm/gpio.c @@ -0,0 +1,111 @@ +/** + * @file gpio.c + * @brief GPIO configuration, set, clear, toggle, and read functions + * @author Kevin Thomas + * @date 2025 + * + * MIT License + * + * Copyright (c) 2025 Kevin Thomas + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "gpio.h" +#include "constants.h" + +#define SIO ((volatile uint32_t *)SIO_BASE) + +/** + * @brief Configure pad control for a GPIO pin + * + * @details Clears OD (output disable), sets IE (input enable), and + * clears ISO (isolation) in PADS_BANK0. + * + * @param gpio_num GPIO pin number (0-29) + */ +static void _gpio_config_pad(uint32_t gpio_num) { + uint32_t value; + + // read PAD value + value = PADS_BANK0->GPIO[gpio_num]; + // clear OD bit (output disable) + value &= ~(1U << PADS_BANK0_OD_SHIFT); + // set IE bit (input enable) + value |= (1U << PADS_BANK0_IE_SHIFT); + // clear ISO bit (isolate) + value &= ~(1U << PADS_BANK0_ISO_SHIFT); + // store value into PAD + PADS_BANK0->GPIO[gpio_num] = value; +} + +/** + * @brief Set IO_BANK0 FUNCSEL to SIO for a GPIO pin + * + * @details Reads the control register, clears FUNCSEL bits, sets + * FUNCSEL to SIO (0x05), and writes back. + * + * @param gpio_num GPIO pin number (0-29) + */ +static void _gpio_config_funcsel(uint32_t gpio_num) { + uint32_t value; + + // read CTRL value + value = IO_BANK0->GPIO[gpio_num].CTRL; + // clear FUNCSEL bits + value &= ~IO_BANK0_CTRL_FUNCSEL_MASK; + // set FUNCSEL to SIO (0x05) + value |= IO_BANK0_CTRL_FUNCSEL_SIO; + // store value into CTRL + IO_BANK0->GPIO[gpio_num].CTRL = value; +} + +/** + * @brief Enable the output driver for a GPIO pin via SIO + * + * @details Sets the corresponding bit in the SIO output-enable set + * register. + * + * @param gpio_num GPIO pin number (0-29) + */ +static void _gpio_enable_output(uint32_t gpio_num) { + SIO[SIO_GPIO_OE_SET_OFFSET] = (1U << gpio_num); +} + +void GPIO_Config(uint32_t gpio_num) { + _gpio_config_pad(gpio_num); + _gpio_config_funcsel(gpio_num); + _gpio_enable_output(gpio_num); +} + +void GPIO_Set(uint32_t gpio_num) { + SIO[SIO_GPIO_OUT_SET_OFFSET] = (1U << gpio_num); +} + +void GPIO_Clear(uint32_t gpio_num) { + SIO[SIO_GPIO_OUT_CLR_OFFSET] = (1U << gpio_num); +} + +void GPIO_Toggle(uint32_t gpio_num) { + SIO[SIO_GPIO_OUT_XOR_OFFSET] = (1U << gpio_num); +} + +bool GPIO_Get(uint32_t gpio_num) { + return (SIO[SIO_GPIO_IN_OFFSET] & (1U << gpio_num)) != 0; +} diff --git a/drivers/0x02_blink_cbm/gpio.h b/drivers/0x02_blink_cbm/gpio.h new file mode 100644 index 0000000..1f13951 --- /dev/null +++ b/drivers/0x02_blink_cbm/gpio.h @@ -0,0 +1,86 @@ +/** + * @file gpio.h + * @brief GPIO configuration, set, clear, toggle, and read functions + * @author Kevin Thomas + * @date 2025 + * + * MIT License + * + * Copyright (c) 2025 Kevin Thomas + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef GPIO_H +#define GPIO_H + +#include +#include + +/** + * @brief Configure a GPIO pin as SIO output + * + * Configures the pad control (clear OD, set IE, clear ISO), sets + * IO_BANK0 FUNCSEL to SIO (0x05), and enables the output driver + * via the SIO output-enable set register. + * + * @param gpio_num GPIO pin number (0-29) + */ +void GPIO_Config(uint32_t gpio_num); + +/** + * @brief Drive a GPIO output high + * + * Sets the specified bit in the SIO GPIO output set register. + * + * @param gpio_num GPIO pin number (0-29) + */ +void GPIO_Set(uint32_t gpio_num); + +/** + * @brief Drive a GPIO output low + * + * Sets the specified bit in the SIO GPIO output clear register. + * + * @param gpio_num GPIO pin number (0-29) + */ +void GPIO_Clear(uint32_t gpio_num); + +/** + * @brief Toggle a GPIO output + * + * Sets the specified bit in the SIO GPIO output XOR register, + * which inverts the current output level. + * + * @param gpio_num GPIO pin number (0-29) + */ +void GPIO_Toggle(uint32_t gpio_num); + +/** + * @brief Read the current input level of a GPIO pin + * + * Reads the SIO GPIO input register and returns the state of the + * specified pin. + * + * @param gpio_num GPIO pin number (0-29) + * @return bool true if pin is high, false if low + */ +bool GPIO_Get(uint32_t gpio_num); + +#endif // GPIO_H diff --git a/drivers/0x02_blink_cbm/image_def.c b/drivers/0x02_blink_cbm/image_def.c new file mode 100644 index 0000000..54b96d2 --- /dev/null +++ b/drivers/0x02_blink_cbm/image_def.c @@ -0,0 +1,48 @@ +/** + * @file image_def.c + * @brief RP2350 IMAGE_DEF block for boot ROM image recognition + * @author Kevin Thomas + * @date 2025 + * + * MIT License + * + * Copyright (c) 2025 Kevin Thomas + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include + +/** + * IMAGE_DEF block structure placed in flash. + * Must appear within the first 4 KB for the boot ROM to accept the image. + */ +__attribute__((section(".embedded_block"), used)) +const uint8_t picobin_block[] = { + // PICOBIN_BLOCK_MARKER_START (word: 0xffffded3) + 0xD3, 0xDE, 0xFF, 0xFF, + // PICOBIN_BLOCK_ITEM_1BS_IMAGE_TYPE + 0x42, 0x01, 0x21, 0x10, + // PICOBIN_BLOCK_ITEM_2BS_LAST + 0xFF, 0x01, 0x00, 0x00, + // Relative pointer to next block (loop to self) + 0x00, 0x00, 0x00, 0x00, + // PICOBIN_BLOCK_MARKER_END (word: 0xab123579) + 0x79, 0x35, 0x12, 0xAB +}; diff --git a/drivers/0x02_blink_cbm/linker.ld b/drivers/0x02_blink_cbm/linker.ld new file mode 100644 index 0000000..5859a9e --- /dev/null +++ b/drivers/0x02_blink_cbm/linker.ld @@ -0,0 +1,106 @@ +/** + * @file linker.ld + * @brief Minimal linker script for bare-metal RP2350 development + * @author Kevin Thomas + * @date 2025 + * + * MIT License + * + * Copyright (c) 2025 Kevin Thomas + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +ENTRY(Reset_Handler) + +/** + * Define memory regions. + */ +__XIP_BASE = 0x10000000; +__XIP_SIZE = 32M; + +__SRAM_BASE = 0x20000000; +__SRAM_SIZE = 512K; +__STACK_SIZE = 32K; + +MEMORY +{ + RAM (rwx) : ORIGIN = __SRAM_BASE, LENGTH = __SRAM_SIZE + FLASH (rx) : ORIGIN = __XIP_BASE, LENGTH = __XIP_SIZE +} + +/** + * Program headers. + */ +PHDRS +{ + text PT_LOAD FLAGS(5); +} + +/** + * Section placement. + */ +SECTIONS +{ + . = ORIGIN(FLASH); + + /** + * Vector table MUST be first at 0x10000000. + */ + .vectors : + { + KEEP(*(.vectors)) + } > FLASH :text + + ASSERT((ADDR(.vectors) == ORIGIN(FLASH)), + "Vector table must be at start of flash (0x10000000)") + + /** + * Text and read-only data. + */ + .text : + { + . = ALIGN(4); + *(.text*) + *(.rodata*) + KEEP(*(.init)) + KEEP(*(.fini)) + KEEP(*(.ARM.attributes)) + } > FLASH :text + + /** + * IMAGE_DEF block at end of code. + */ + .embedded_block : + { + KEEP(*(.embedded_block)) + } > FLASH :text + + /** + * Non-secure stack symbols. + */ + __StackTop = ORIGIN(RAM) + LENGTH(RAM); + __StackLimit = __StackTop - __STACK_SIZE; + __stack = __StackTop; + _stack_top = __StackTop; + + .stack (NOLOAD) : { . = ALIGN(8); } > RAM + + PROVIDE(__Vectors = ADDR(.vectors)); +} diff --git a/drivers/0x02_blink_cbm/main.c b/drivers/0x02_blink_cbm/main.c new file mode 100644 index 0000000..271feff --- /dev/null +++ b/drivers/0x02_blink_cbm/main.c @@ -0,0 +1,78 @@ +/** + * @file main.c + * @brief Blink demonstration: toggle onboard LED every 500 ms + * @author Kevin Thomas + * @date 2025 + * + * MIT License + * + * Copyright (c) 2025 Kevin Thomas + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * ----------------------------------------------------------------------------- + * + * Demonstrates GPIO output control using the blink driver (blink.h / blink.c). + * The onboard LED on GPIO 25 is toggled every BLINK_DELAY_MS milliseconds and + * the current state is reported over UART. + * + * Wiring: + * GPIO25 -> Onboard LED (no external wiring needed) + */ + +#include "blink.h" +#include "uart.h" +#include "delay.h" +#include "constants.h" + +#define BLINK_DELAY_MS 500 + +/** + * @brief Print the current LED state over UART + * + * @details Queries the blink driver for the pin state and prints + * "LED: ON\r\n" or "LED: OFF\r\n" over UART0. + * + * @param pin GPIO pin number to query + */ +static void _print_led_state(uint32_t pin) { + if (blink_get_state(pin)) { + uart_driver_puts("LED: ON\r\n"); + } else { + uart_driver_puts("LED: OFF\r\n"); + } +} + +/** + * @brief Application entry point for the LED blink demo + * + * Initializes the onboard LED and enters an infinite loop that + * toggles the LED state every BLINK_DELAY_MS milliseconds. + * + * @return int Does not return + */ +int main(void) { + blink_init(LED_PIN); + uart_driver_puts("Blink driver initialized on GPIO 25\r\n"); + while (1) { + blink_toggle(LED_PIN); + _print_led_state(LED_PIN); + Delay_MS(BLINK_DELAY_MS); + } +} diff --git a/drivers/0x02_blink_cbm/reset.c b/drivers/0x02_blink_cbm/reset.c new file mode 100644 index 0000000..f9370f5 --- /dev/null +++ b/drivers/0x02_blink_cbm/reset.c @@ -0,0 +1,45 @@ +/** + * @file reset.c + * @brief Reset controller functions for subsystem initialization + * @author Kevin Thomas + * @date 2025 + * + * MIT License + * + * Copyright (c) 2025 Kevin Thomas + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "reset.h" +#include "constants.h" + +void Init_Subsystem(void) { + uint32_t value; + + // read RESETS->RESET value + value = RESETS->RESET; + // clear IO_BANK0 bit + value &= ~(1U << RESETS_RESET_IO_BANK0_SHIFT); + // store value into RESETS->RESET address + RESETS->RESET = value; + // wait until done + while ((RESETS->RESET_DONE & (1U << RESETS_RESET_IO_BANK0_SHIFT)) == 0) { + } +} diff --git a/drivers/0x02_blink_cbm/reset.h b/drivers/0x02_blink_cbm/reset.h new file mode 100644 index 0000000..4c51a23 --- /dev/null +++ b/drivers/0x02_blink_cbm/reset.h @@ -0,0 +1,44 @@ +/** + * @file reset.h + * @brief Reset controller functions for subsystem initialization + * @author Kevin Thomas + * @date 2025 + * + * MIT License + * + * Copyright (c) 2025 Kevin Thomas + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef RESET_H +#define RESET_H + +/** + * @brief Initialize the IO_BANK0 subsystem by clearing its reset bit + * + * Clears the IO_BANK0 reset bit in the Reset controller and waits + * until the RESET_DONE register confirms the block is out of reset. + * + * @param None + * @retval None + */ +void Init_Subsystem(void); + +#endif // RESET_H diff --git a/drivers/0x02_blink_cbm/reset_handler.c b/drivers/0x02_blink_cbm/reset_handler.c new file mode 100644 index 0000000..31de70a --- /dev/null +++ b/drivers/0x02_blink_cbm/reset_handler.c @@ -0,0 +1,50 @@ +/** + * @file reset_handler.c + * @brief Reset handler entry point after power-on or system reset + * @author Kevin Thomas + * @date 2025 + * + * MIT License + * + * Copyright (c) 2025 Kevin Thomas + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "reset_handler.h" +#include "stack.h" +#include "xosc.h" +#include "reset.h" +#include "uart.h" +#include "coprocessor.h" + +extern int main(void); + +void __attribute__((naked, noreturn)) Reset_Handler(void) { + __asm__ volatile ( + "bl Init_Stack\n\t" + "bl Init_XOSC\n\t" + "bl Enable_XOSC_Peri_Clock\n\t" + "bl Init_Subsystem\n\t" + "bl UART_Release_Reset\n\t" + "bl UART_Init\n\t" + "bl Enable_Coprocessor\n\t" + "b main\n\t" + ); +} diff --git a/drivers/0x02_blink_cbm/reset_handler.h b/drivers/0x02_blink_cbm/reset_handler.h new file mode 100644 index 0000000..af862df --- /dev/null +++ b/drivers/0x02_blink_cbm/reset_handler.h @@ -0,0 +1,45 @@ +/** + * @file reset_handler.h + * @brief Reset handler entry point after power-on or system reset + * @author Kevin Thomas + * @date 2025 + * + * MIT License + * + * Copyright (c) 2025 Kevin Thomas + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef RESET_HANDLER_H +#define RESET_HANDLER_H + +/** + * @brief Reset handler for the RP2350 + * + * Entry point after reset. Performs stack initialization, XOSC setup, + * subsystem reset release, UART initialization, coprocessor enable, + * and branches to main(). + * + * @param None + * @retval None + */ +void Reset_Handler(void) __attribute__((noreturn)); + +#endif // RESET_HANDLER_H diff --git a/drivers/0x02_blink_cbm/stack.c b/drivers/0x02_blink_cbm/stack.c new file mode 100644 index 0000000..9c09135 --- /dev/null +++ b/drivers/0x02_blink_cbm/stack.c @@ -0,0 +1,46 @@ +/** + * @file stack.c + * @brief Stack pointer initialization for MSP/PSP and their limits + * @author Kevin Thomas + * @date 2025 + * + * MIT License + * + * Copyright (c) 2025 Kevin Thomas + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "stack.h" +#include "constants.h" + +void Init_Stack(void) { + __asm__ volatile ( + "ldr r0, =%0\n\t" + "msr PSP, r0\n\t" + "ldr r0, =%1\n\t" + "msr MSPLIM, r0\n\t" + "msr PSPLIM, r0\n\t" + "ldr r0, =%0\n\t" + "msr MSP, r0\n\t" + : + : "i" (STACK_TOP), "i" (STACK_LIMIT) + : "r0" + ); +} diff --git a/drivers/0x02_blink_cbm/stack.h b/drivers/0x02_blink_cbm/stack.h new file mode 100644 index 0000000..50b31df --- /dev/null +++ b/drivers/0x02_blink_cbm/stack.h @@ -0,0 +1,44 @@ +/** + * @file stack.h + * @brief Stack pointer initialization for MSP/PSP and their limits + * @author Kevin Thomas + * @date 2025 + * + * MIT License + * + * Copyright (c) 2025 Kevin Thomas + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef STACK_H +#define STACK_H + +/** + * @brief Initialize stack pointers + * + * Sets Main and Process Stack Pointers (MSP/PSP) and their limits + * using the STACK_TOP and STACK_LIMIT values from constants.h. + * + * @param None + * @retval None + */ +void Init_Stack(void); + +#endif // STACK_H diff --git a/drivers/0x02_blink_cbm/uart.c b/drivers/0x02_blink_cbm/uart.c new file mode 100644 index 0000000..a1de708 --- /dev/null +++ b/drivers/0x02_blink_cbm/uart.c @@ -0,0 +1,165 @@ +/** + * @file uart.c + * @brief Implementation of the bare-metal UART0 driver + * @author Kevin Thomas + * @date 2025 + * + * MIT License + * + * Copyright (c) 2025 Kevin Thomas + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "uart.h" +#include "constants.h" + +#define UART_BASE ((volatile uint32_t *)UART0_BASE) + +/** + * @brief Clear the UART0 reset bit in the reset controller + * + * @details Reads RESETS->RESET, clears bit 26 (UART0), and writes + * the value back. + * + * @param None + * @retval None + */ +static void _uart_clear_reset_bit(void) { + uint32_t value; + + // read RESETS->RESET value + value = RESETS->RESET; + // clear UART0 reset bit (bit 26) + value &= ~(1U << RESETS_RESET_UART0_SHIFT); + // write value back to RESETS->RESET + RESETS->RESET = value; +} + +/** + * @brief Wait until the UART0 block is out of reset + * + * @details Polls RESETS->RESET_DONE until bit 26 (UART0) is set. + * + * @param None + * @retval None + */ +static void _uart_wait_reset_done(void) { + // loop until UART0 is out of reset + while ((RESETS->RESET_DONE & (1U << RESETS_RESET_UART0_SHIFT)) == 0) { + } +} + +/** + * @brief Configure GPIO pins 0 (TX) and 1 (RX) for UART function + * + * @details Sets IO_BANK0 FUNCSEL to UART (0x02) for both pins and + * programs the corresponding pad controls. + * + * @param None + * @retval None + */ +static void _uart_configure_pins(void) { + // FUNCSEL = 2 -> select UART function + IO_BANK0->GPIO[0].CTRL = IO_BANK0_CTRL_FUNCSEL_UART; + IO_BANK0->GPIO[1].CTRL = IO_BANK0_CTRL_FUNCSEL_UART; + // pad config value for TX (pull/func recommended) + PADS_BANK0->GPIO[0] = 0x04; + // pad config value for RX (input enable) + PADS_BANK0->GPIO[1] = 0x40; +} + +/** + * @brief Set UART0 baud rate divisors for 115200 baud at 14.5 MHz + * + * @details Programs UARTIBRD = 6 and UARTFBRD = 33 for the integer + * and fractional baud rate divisors respectively. + * + * @param None + * @retval None + */ +static void _uart_set_baud(void) { + // disable UART while configuring + UART_BASE[UART_CR_OFFSET] = 0; + // set integer baud divisor + UART_BASE[UART_IBRD_OFFSET] = 6; + // set fractional baud divisor + UART_BASE[UART_FBRD_OFFSET] = 33; +} + +/** + * @brief Configure line control and enable UART0 + * + * @details Sets 8-bit word length with FIFOs enabled, then enables + * UART0 with both TX and RX. + * + * @param None + * @retval None + */ +static void _uart_enable(void) { + // configure line control: FIFO enable + 8-bit + UART_BASE[UART_LCR_H_OFFSET] = UART_LCR_H_8N1_FIFO; + // enable UART with TX and RX enabled + UART_BASE[UART_CR_OFFSET] = UART_CR_ENABLE; +} + +void UART_Release_Reset(void) { + _uart_clear_reset_bit(); + _uart_wait_reset_done(); +} + +void UART_Init(void) { + _uart_configure_pins(); + _uart_set_baud(); + _uart_enable(); +} + +bool uart_driver_is_readable(void) { + // test bit 4, RX FIFO empty (RXFE) + return (UART_BASE[UART_FR_OFFSET] & UART_FR_RXFE_MASK) == 0; +} + +char uart_driver_getchar(void) { + // wait for RX FIFO to be not empty + while (UART_BASE[UART_FR_OFFSET] & UART_FR_RXFE_MASK) { + } + // read data from UARTDR + return (char)(UART_BASE[UART_DR_OFFSET] & 0xFF); +} + +void uart_driver_putchar(char c) { + // wait for TX FIFO to be not full + while (UART_BASE[UART_FR_OFFSET] & UART_FR_TXFF_MASK) { + } + // write data to UARTDR + UART_BASE[UART_DR_OFFSET] = (uint32_t)c; +} + +void uart_driver_puts(const char *str) { + while (*str) { + uart_driver_putchar(*str++); + } +} + +char uart_driver_to_upper(char c) { + if (c >= 'a' && c <= 'z') { + return (char)(c - 32); + } + return c; +} diff --git a/drivers/0x02_blink_cbm/uart.h b/drivers/0x02_blink_cbm/uart.h new file mode 100644 index 0000000..282570a --- /dev/null +++ b/drivers/0x02_blink_cbm/uart.h @@ -0,0 +1,111 @@ +/** + * @file uart.h + * @brief Header for bare-metal UART0 driver (raw TX/RX, GPIO 0/1) + * @author Kevin Thomas + * @date 2025 + * + * MIT License + * + * Copyright (c) 2025 Kevin Thomas + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef UART_H +#define UART_H + +#include +#include + +/** + * @brief Release UART0 from reset and wait until it is ready + * + * Clears the UART0 reset bit in the Reset controller and polls + * RESET_DONE until the UART0 block is out of reset. + * + * @param None + * @retval None + */ +void UART_Release_Reset(void); + +/** + * @brief Initialize UART0 (pins, baud divisors, line control, enable) + * + * Configures IO_BANK0 pins 0 (TX) and 1 (RX) to the UART function, + * programs pad controls, sets baud rate divisors (IBRD=6, FBRD=33 + * for 115200 baud at 14.5 MHz), configures 8N1 with FIFOs, and + * enables UART0 with TX and RX. + * + * @param None + * @retval None + */ +void UART_Init(void); + +/** + * @brief Check whether a received character is waiting in the UART FIFO + * + * Returns immediately without blocking. Use this to poll for incoming + * data before calling uart_driver_getchar(). + * + * @return bool true if at least one byte is available, false otherwise + */ +bool uart_driver_is_readable(void); + +/** + * @brief Read one character from UART0 (blocking) + * + * Blocks until a byte arrives in the receive FIFO, then returns it. + * Prefer pairing with uart_driver_is_readable() to avoid indefinite blocking. + * + * @return char The received character + */ +char uart_driver_getchar(void); + +/** + * @brief Transmit one character over UART0 (blocking) + * + * Waits until the transmit FIFO has space, then writes the character + * to UARTDR. + * + * @param c Character to transmit + */ +void uart_driver_putchar(char c); + +/** + * @brief Transmit a null-terminated string over UART0 + * + * Calls uart_driver_putchar() for every character in the string up to + * and not including the null terminator. + * + * @param str Pointer to the null-terminated ASCII string to send + */ +void uart_driver_puts(const char *str); + +/** + * @brief Convert a lowercase ASCII character to uppercase + * + * Returns the uppercase equivalent if the character is in 'a'-'z'; + * all other characters are passed through unchanged. + * + * @param c Input character + * @return char Uppercase equivalent, or the original character + */ +char uart_driver_to_upper(char c); + +#endif // UART_H diff --git a/drivers/0x02_blink_cbm/uf2conv.py b/drivers/0x02_blink_cbm/uf2conv.py new file mode 100644 index 0000000..d6dd7a8 --- /dev/null +++ b/drivers/0x02_blink_cbm/uf2conv.py @@ -0,0 +1,365 @@ +#!/usr/bin/env python3 +import sys +import struct +import subprocess +import re +import os +import os.path +import argparse +import json +from time import sleep + + +UF2_MAGIC_START0 = 0x0A324655 # "UF2\n" +UF2_MAGIC_START1 = 0x9E5D5157 # Randomly selected +UF2_MAGIC_END = 0x0AB16F30 # Ditto + +INFO_FILE = "/INFO_UF2.TXT" + +appstartaddr = 0x2000 +familyid = 0x0 + + +def is_uf2(buf): + w = struct.unpack(" 476: + assert False, "Invalid UF2 data size at " + ptr + newaddr = hd[3] + if (hd[2] & 0x2000) and (currfamilyid == None): + currfamilyid = hd[7] + if curraddr == None or ((hd[2] & 0x2000) and hd[7] != currfamilyid): + currfamilyid = hd[7] + curraddr = newaddr + if familyid == 0x0 or familyid == hd[7]: + appstartaddr = newaddr + padding = newaddr - curraddr + if padding < 0: + assert False, "Block out of order at " + ptr + if padding > 10*1024*1024: + assert False, "More than 10M of padding needed at " + ptr + if padding % 4 != 0: + assert False, "Non-word padding size at " + ptr + while padding > 0: + padding -= 4 + outp.append(b"\x00\x00\x00\x00") + if familyid == 0x0 or ((hd[2] & 0x2000) and familyid == hd[7]): + outp.append(block[32 : 32 + datalen]) + curraddr = newaddr + datalen + if hd[2] & 0x2000: + if hd[7] in families_found.keys(): + if families_found[hd[7]] > newaddr: + families_found[hd[7]] = newaddr + else: + families_found[hd[7]] = newaddr + if prev_flag == None: + prev_flag = hd[2] + if prev_flag != hd[2]: + all_flags_same = False + if blockno == (numblocks - 1): + print("--- UF2 File Header Info ---") + families = load_families() + for family_hex in families_found.keys(): + family_short_name = "" + for name, value in families.items(): + if value == family_hex: + family_short_name = name + print("Family ID is {:s}, hex value is 0x{:08x}".format(family_short_name,family_hex)) + print("Target Address is 0x{:08x}".format(families_found[family_hex])) + if all_flags_same: + print("All block flag values consistent, 0x{:04x}".format(hd[2])) + else: + print("Flags were not all the same") + print("----------------------------") + if len(families_found) > 1 and familyid == 0x0: + outp = [] + appstartaddr = 0x0 + return b"".join(outp) + +def convert_to_carray(file_content): + outp = "const unsigned long bindata_len = %d;\n" % len(file_content) + outp += "const unsigned char bindata[] __attribute__((aligned(16))) = {" + for i in range(len(file_content)): + if i % 16 == 0: + outp += "\n" + outp += "0x%02x, " % file_content[i] + outp += "\n};\n" + return bytes(outp, "utf-8") + +def convert_to_uf2(file_content): + global familyid + datapadding = b"" + while len(datapadding) < 512 - 256 - 32 - 4: + datapadding += b"\x00\x00\x00\x00" + numblocks = (len(file_content) + 255) // 256 + outp = [] + for blockno in range(numblocks): + ptr = 256 * blockno + chunk = file_content[ptr:ptr + 256] + flags = 0x0 + if familyid: + flags |= 0x2000 + hd = struct.pack(b" + +extern uint32_t _stack_top; +extern void Reset_Handler(void); + +typedef void (*vector_func_t)(void); + +/** + * Vector table placed in .vectors section. + * The Thumb bit (bit 0 = 1) is automatically set by the linker + * for function pointers in Thumb mode. + */ +__attribute__((section(".vectors"), used)) +const void *_vectors[2] = { + &_stack_top, + Reset_Handler +}; diff --git a/drivers/0x02_blink_cbm/xosc.c b/drivers/0x02_blink_cbm/xosc.c new file mode 100644 index 0000000..f8f3228 --- /dev/null +++ b/drivers/0x02_blink_cbm/xosc.c @@ -0,0 +1,54 @@ +/** + * @file xosc.c + * @brief External crystal oscillator (XOSC) initialization and clock enable + * @author Kevin Thomas + * @date 2025 + * + * MIT License + * + * Copyright (c) 2025 Kevin Thomas + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "xosc.h" +#include "constants.h" + +void Init_XOSC(void) { + // set delay 50,000 cycles + XOSC->STARTUP = 0x00C4U; + // set 1_15MHz, freq range, actual 14.5MHz + XOSC->CTRL = 0x00FABAA0U; + // wait until stable bit is set + while ((XOSC->STATUS & (1U << XOSC_STATUS_STABLE_SHIFT)) == 0) { + } +} + +void Enable_XOSC_Peri_Clock(void) { + uint32_t value; + + // read CLK_PERI_CTRL value + value = CLOCKS->CLK_PERI_CTRL; + // set ENABLE bit + value |= (1U << CLOCKS_CLK_PERI_CTRL_ENABLE_SHIFT); + // set AUXSRC: XOSC_CLKSRC + value |= (CLOCKS_CLK_PERI_CTRL_AUXSRC_XOSC << CLOCKS_CLK_PERI_CTRL_AUXSRC_SHIFT); + // store value into CLK_PERI_CTRL + CLOCKS->CLK_PERI_CTRL = value; +} diff --git a/drivers/0x02_blink_cbm/xosc.h b/drivers/0x02_blink_cbm/xosc.h new file mode 100644 index 0000000..ca2b9e7 --- /dev/null +++ b/drivers/0x02_blink_cbm/xosc.h @@ -0,0 +1,55 @@ +/** + * @file xosc.h + * @brief External crystal oscillator (XOSC) initialization and clock enable + * @author Kevin Thomas + * @date 2025 + * + * MIT License + * + * Copyright (c) 2025 Kevin Thomas + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef XOSC_H +#define XOSC_H + +/** + * @brief Initialize the external crystal oscillator and wait until stable + * + * Configures the XOSC startup delay and frequency range, then polls + * the status register until the STABLE bit is set. + * + * @param None + * @retval None + */ +void Init_XOSC(void); + +/** + * @brief Enable the XOSC peripheral clock + * + * Sets the peripheral clock to use XOSC as its auxiliary source and + * enables it via CLK_PERI_CTRL. + * + * @param None + * @retval None + */ +void Enable_XOSC_Peri_Clock(void); + +#endif // XOSC_H