-
Notifications
You must be signed in to change notification settings - Fork 1
feat: Add device generation tools and validation workflow for TinyGo v0.39.0 #25
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
12ed747
f7b37d5
bc3dbf6
630a374
b99a302
09cff7c
8075fb2
32b7c21
d90faf2
6173f2c
804b62b
6f9e1e3
eacd100
8338305
ac4a8ef
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| name: "Setup LLGO" | ||
| description: "Checkout and build LLGO from specific commit hash" | ||
| inputs: | ||
| commit-hash: | ||
| description: "Commit hash to checkout" | ||
| required: true | ||
| platform: | ||
| description: "Platform to download for" | ||
| required: false | ||
| default: "linux-amd64" | ||
| runs: | ||
| using: "composite" | ||
| steps: | ||
| - name: Setup LLGo Dependencies | ||
| uses: goplus/llgo/.github/actions/setup-deps@b25ae1b4e7c06a302d1d09eb9e9b0ad1e3a43abd | ||
| - name: Checkout LLGo Repository | ||
| uses: actions/checkout@v4 | ||
| with: | ||
| repository: goplus/llgo | ||
| ref: ${{ inputs.commit-hash }} | ||
| path: llgo-source | ||
| - name: Setup LLGO | ||
| shell: bash | ||
| run: | | ||
| echo "Setting up LLGO from commit hash ${{ inputs.commit-hash }}..." | ||
| cd llgo-source | ||
| # Install LLGO from source | ||
| bash ./install.sh | ||
| # Set LLGO_ROOT to the source directory | ||
| echo "LLGO_ROOT=$PWD" >> $GITHUB_ENV | ||
| # Verify LLGO is available | ||
| llgo version || echo "Failed to get LLGO version" | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,335 @@ | ||
| #!/bin/bash | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Documentation: Missing Script Header Add documentation explaining the script's purpose, usage, and modes: #!/bin/bash
#
# device-gen.sh - Generate device files from upstream hardware description files
#
# Usage: ./device-gen.sh [generate|verify]
#
# Modes:
# generate - Clean target directories and regenerate all device files
# verify - Verify generated files match existing files (for CI)
# (default) - Generate without cleaning (preserves ignore list files)
#
set -e |
||
| set -e | ||
|
|
||
| # .ld,.s current not need generate at emb/device/avr,they are in llgo | ||
|
|
||
| declare_avr_config() { | ||
| name="avr" | ||
| repo="https://github.com/avr-rust/avr-mcu" | ||
| lib_path="lib/avr" | ||
| git_hash="6624554c02b237b23dc17d53e992bf54033fc228" | ||
| tasks=( | ||
| "lib/avr/packs/atmega" | ||
| "lib/avr/packs/tiny" | ||
| ) | ||
| ignore_list="avr.go avr_tiny85.go" | ||
| target="device/avr" | ||
| generator="gen-device-avr" | ||
| } | ||
|
|
||
| declare_esp_config() { | ||
| name="esp" | ||
| repo="https://github.com/cmsis-svd/cmsis-svd-data" | ||
| lib_path="lib/cmsis-svd" | ||
| git_hash="05a9562ec59b87945a8d7177a4b08b7aa2f2fd58" | ||
| tasks=( | ||
| "-source=https://github.com/posborne/cmsis-svd/tree/master/data/Espressif-Community -interrupts=software lib/cmsis-svd/data/Espressif-Community/" | ||
| "-source=https://github.com/posborne/cmsis-svd/tree/master/data/Espressif -interrupts=software lib/cmsis-svd/data/Espressif/" | ||
| ) | ||
| ignore_list="" | ||
| target="device/esp" | ||
| generator="gen-device-svd" | ||
| } | ||
|
|
||
| declare_nrf_config() { | ||
| name="nrf" | ||
| repo="https://github.com/NordicSemiconductor/nrfx" | ||
| lib_path="lib/nrfx" | ||
| git_hash="d779b49fc59c7a165e7da1d7cd7d57b28a059f16" | ||
| tasks=( | ||
| "-source=https://github.com/NordicSemiconductor/nrfx/tree/master/mdk lib/nrfx/mdk/" | ||
| ) | ||
| ignore_list="README.markdown" | ||
| target="device/nrf" | ||
| generator="gen-device-svd" | ||
| } | ||
|
|
||
| declare_nxp_config() { | ||
| name="nxp" | ||
| repo="https://github.com/cmsis-svd/cmsis-svd-data" | ||
| lib_path="lib/cmsis-svd" | ||
| git_hash="05a9562ec59b87945a8d7177a4b08b7aa2f2fd58" | ||
| tasks=( | ||
| "-source=https://github.com/posborne/cmsis-svd/tree/master/data/NXP lib/cmsis-svd/data/NXP/" | ||
| ) | ||
| ignore_list="hardfault.go mimxrt1062_clock.go mimxrt1062_hardfault.go mimxrt1062_mpu.go" | ||
| target="device/nxp" | ||
| generator="gen-device-svd" | ||
| } | ||
|
|
||
| declare_sam_config() { | ||
| name="sam" | ||
| repo="https://github.com/cmsis-svd/cmsis-svd-data" | ||
| lib_path="lib/cmsis-svd" | ||
| git_hash="05a9562ec59b87945a8d7177a4b08b7aa2f2fd58" | ||
| tasks=( | ||
| "-source=https://github.com/posborne/cmsis-svd/tree/master/data/Atmel lib/cmsis-svd/data/Atmel/" | ||
| ) | ||
| ignore_list="atsamd51x-bitfields.go atsame5x-bitfields.go" | ||
| target="device/sam" | ||
| generator="gen-device-svd" | ||
| } | ||
|
|
||
| declare_sifive_config() { | ||
| name="sifive" | ||
| repo="https://github.com/cmsis-svd/cmsis-svd-data" | ||
| lib_path="lib/cmsis-svd" | ||
| git_hash="05a9562ec59b87945a8d7177a4b08b7aa2f2fd58" | ||
| tasks=( | ||
| "-source=https://github.com/posborne/cmsis-svd/tree/master/data/SiFive-Community -interrupts=software lib/cmsis-svd/data/SiFive-Community/" | ||
| ) | ||
| ignore_list="" | ||
| target="device/sifive" | ||
| generator="gen-device-svd" | ||
| } | ||
|
|
||
| declare_kendryte_config() { | ||
| name="kendryte" | ||
| repo="https://github.com/cmsis-svd/cmsis-svd-data" | ||
| lib_path="lib/cmsis-svd" | ||
| git_hash="05a9562ec59b87945a8d7177a4b08b7aa2f2fd58" | ||
| tasks=( | ||
| "-source=https://github.com/posborne/cmsis-svd/tree/master/data/Kendryte-Community -interrupts=software lib/cmsis-svd/data/Kendryte-Community/" | ||
| ) | ||
| ignore_list="" | ||
| target="device/kendryte" | ||
| generator="gen-device-svd" | ||
| } | ||
|
|
||
| declare_stm32_config() { | ||
| name="stm32" | ||
| repo="https://github.com/tinygo-org/stm32-svd" | ||
| lib_path="lib/stm32-svd" | ||
| git_hash="e6db8e32d5d42293a528434ec12e7f88479a8649" | ||
| tasks=( | ||
| "-source=https://github.com/tinygo-org/stm32-svd lib/stm32-svd/svd" | ||
| ) | ||
| ignore_list="" | ||
| target="device/stm32" | ||
| generator="gen-device-svd" | ||
| } | ||
|
|
||
| declare_rp_config() { | ||
| name="rp" | ||
| repo="https://github.com/cmsis-svd/cmsis-svd-data" | ||
| lib_path="lib/cmsis-svd" | ||
| git_hash="05a9562ec59b87945a8d7177a4b08b7aa2f2fd58" | ||
| tasks=( | ||
| "-source=https://github.com/posborne/cmsis-svd/tree/master/data/RaspberryPi lib/cmsis-svd/data/RaspberryPi/" | ||
| ) | ||
| ignore_list="rp2040-extra.go rp2350-extra.go" | ||
| target="device/rp" | ||
| generator="gen-device-svd" | ||
| } | ||
|
|
||
| declare_renesas_config() { | ||
| name="renesas" | ||
| repo="https://github.com/cmsis-svd/cmsis-svd-data" | ||
| lib_path="lib/cmsis-svd" | ||
| git_hash="05a9562ec59b87945a8d7177a4b08b7aa2f2fd58" | ||
| tasks=( | ||
| "-source=https://github.com/cmsis-svd/cmsis-svd-data/tree/master/data/Renesas lib/cmsis-svd/data/Renesas/" | ||
| ) | ||
| ignore_list="" | ||
| target="device/renesas" | ||
| generator="gen-device-svd" | ||
| } | ||
|
|
||
| # List of device configuration functions | ||
| DEVICE_CONFIGS=( | ||
| "declare_avr_config" | ||
| "declare_esp_config" | ||
| "declare_nrf_config" | ||
| "declare_nxp_config" | ||
| "declare_sam_config" | ||
| "declare_sifive_config" | ||
| "declare_kendryte_config" | ||
| "declare_stm32_config" | ||
| "declare_rp_config" | ||
| "declare_renesas_config" | ||
| ) | ||
|
|
||
| # Generate device files from all tasks to specified directory | ||
| generate_device_files() { | ||
| local device_name="$1" | ||
| shift | ||
| local generator="${@: -2:1}" | ||
| local target_dir="${@: -1}" | ||
| # Remove generator and target_dir from args to get tasks | ||
| set -- "${@:1:$#-2}" | ||
| local tasks_array=("$@") | ||
|
|
||
| echo "[$device_name] Processing ${#tasks_array[@]} tasks..." | ||
| for task in "${tasks_array[@]}"; do | ||
| echo "[$device_name] Processing task: $task" | ||
| "$generator" $task "$target_dir/" | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Security: Potential Command Injection The Recommendation: "$generator" "$task" "$target_dir/" |
||
| echo "[$device_name] Generated to $target_dir" | ||
| done | ||
| echo "[$device_name] All tasks processed successfully" | ||
|
|
||
| # Format Go files in target directory | ||
| echo "[$device_name] Formatting Go files in $target_dir..." | ||
| (cd "$target_dir" && GO111MODULE=off ${GO:-go} fmt .) | ||
| echo "[$device_name] Go formatting completed" | ||
| } | ||
|
|
||
| # Generate devices for a specific device configuration | ||
| generate_devices() { | ||
| local config_func="$1" | ||
| local mode="$2" | ||
|
|
||
| # Call the configuration function to set variables | ||
| $config_func | ||
|
|
||
| # Validate configuration | ||
| if [[ -z "$repo" || -z "$lib_path" || -z "$git_hash" || -z "$generator" || -z "$target" || ${#tasks[@]} -eq 0 ]]; then | ||
| echo "Error: Missing configuration for device '$name'" | ||
| return 1 | ||
| fi | ||
|
|
||
| # Use target directory from configuration | ||
| local target_dir="$target" | ||
| case "$mode" in | ||
| generate) | ||
| echo "[$name] Running in generation mode - will clean and generate to $target_dir" | ||
| ;; | ||
| verify) | ||
| echo "[$name] Running in verification mode - will verify generated content matches $target_dir" | ||
| ;; | ||
| *) | ||
| echo "[$name] Running in default mode - will generate to $target_dir" | ||
| ;; | ||
| esac | ||
|
|
||
| # Clone and setup repository | ||
| echo "[$name] Setting up repository..." | ||
| rm -rf "$lib_path" | ||
| git clone "$repo" "$lib_path" | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Performance: Sequential Git Operations (Critical Bottleneck) Git clone operations run sequentially for all 10 devices, wasting 100-600 seconds. Additionally, 7 devices share the same Recommendations:
|
||
| cd "$lib_path" | ||
| git checkout "$git_hash" | ||
| cd ../../ | ||
|
|
||
| # Create target directory | ||
| mkdir -p "$target_dir" | ||
|
|
||
| # Handle verification mode | ||
| if [ "$mode" = "verify" ]; then | ||
| echo "[$name] Starting verification process..." | ||
|
|
||
| # Check if target directory exists and has content | ||
| if [ ! -d "$target_dir" ] || [ -z "$(ls -A "$target_dir" 2>/dev/null)" ]; then | ||
| echo "[$name] Verification failed: target directory is empty or does not exist" | ||
| return 1 | ||
| fi | ||
|
|
||
| # Create temporary directory with same structure | ||
| temp_target=".verify/$target" | ||
| echo "[$name] Creating temporary directory: $temp_target" | ||
| mkdir -p "$temp_target" | ||
|
|
||
| # Generate files to temporary directory | ||
| echo "[$name] Generating files to temporary directory..." | ||
| generate_device_files "$name" "${tasks[@]}" "$generator" "$temp_target" | ||
|
|
||
| # Copy ignore list files to temporary directory | ||
| if [ -n "$ignore_list" ]; then | ||
| echo "[$name] Copying ignore list files to temporary directory: $ignore_list" | ||
| for file in $ignore_list; do | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The For example, in ignore_list=("avr.go" "avr_tiny85.go")And then in for file in "${ignore_list[@]}"; doThis change should be applied to all |
||
| if [ -f "$target_dir/$file" ]; then | ||
| cp "$target_dir/$file" "$temp_target/" | ||
| echo "[$name] Copied: $file" | ||
| fi | ||
| done | ||
| fi | ||
|
|
||
| # Compare directories | ||
| echo "[$name] Comparing original directory with generated directory..." | ||
| if diff -u -r "$target_dir" "$temp_target" > /dev/null 2>&1; then | ||
| echo "[$name] Verification passed: generated files match existing files" | ||
| VERIFY_RESULT=0 | ||
| else | ||
| echo "[$name] Verification failed: differences found" | ||
| echo "[$name] Detailed differences:" | ||
| diff -u -r "$target_dir" "$temp_target" || true | ||
| VERIFY_RESULT=1 | ||
| fi | ||
|
|
||
| return $VERIFY_RESULT | ||
| fi | ||
|
|
||
| # Clean target directory if in generation mode | ||
| if [ "$mode" = "generate" ]; then | ||
| echo "[$name] Cleaning $target_dir" | ||
|
|
||
| # Backup ignored files if ignore_list is not empty | ||
| if [ -n "$ignore_list" ]; then | ||
| echo "[$name] Preserving ignore list: $ignore_list" | ||
| # Create temp directory to store ignored files | ||
| TEMP_DIR=$(mktemp -d) | ||
|
|
||
| # Backup ignored files if they exist | ||
| for file in $ignore_list; do | ||
| if [ -f "$target_dir/$file" ]; then | ||
| cp "$target_dir/$file" "$TEMP_DIR/" | ||
| echo "[$name] Backed up: $file" | ||
| fi | ||
| done | ||
| fi | ||
|
|
||
| # Remove all files from target directory | ||
| rm -rf "$target_dir"/* | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Code Quality: Unsafe Glob Deletion If Recommendation: if [ -z "$target_dir" ] || [ "$target_dir" = "/" ]; then
echo "[$name] Error: Invalid target directory"
return 1
fi
rm -rf "${target_dir:?}"/* |
||
|
|
||
| # Restore ignored files if ignore_list is not empty | ||
| if [ -n "$ignore_list" ]; then | ||
| for file in $ignore_list; do | ||
| if [ -f "$TEMP_DIR/$file" ]; then | ||
| cp "$TEMP_DIR/$file" "$target_dir/" | ||
| echo "[$name] Restored: $file" | ||
| fi | ||
| done | ||
|
|
||
| # Clean up temp directory | ||
| rm -rf "$TEMP_DIR" | ||
| fi | ||
| fi | ||
|
|
||
| # Generate device files from all tasks | ||
| generate_device_files "$name" "${tasks[@]}" "$generator" "$target_dir" | ||
| } | ||
|
|
||
| # Parse command line arguments | ||
| MODE="" | ||
| case "$1" in | ||
| generate) | ||
| MODE="generate" | ||
| ;; | ||
| verify) | ||
| MODE="verify" | ||
| ;; | ||
| *) | ||
| MODE="default" | ||
| ;; | ||
| esac | ||
|
|
||
| # Initialize verification tracking | ||
| VERIFICATION_FAILED=0 | ||
|
|
||
| # Process all enabled devices | ||
| for config_func in "${DEVICE_CONFIGS[@]}"; do | ||
| if ! generate_devices "$config_func" "$MODE"; then | ||
| if [ "$MODE" = "verify" ]; then | ||
| VERIFICATION_FAILED=1 | ||
| fi | ||
| fi | ||
| done | ||
|
|
||
| if [ "$MODE" = "verify" ]; then | ||
| if [ $VERIFICATION_FAILED -eq 0 ]; then | ||
| echo "All device verifications passed" | ||
| else | ||
| echo "Device verification failed: inconsistencies found" | ||
| exit 1 | ||
| fi | ||
| else | ||
| echo "All device generations completed!" | ||
| fi | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
llgo versionverification step currently echoes a message on failure but allows the action to continue. This could mask installation or setup problems. To ensure the integrity of the setup, this step should fail ifllgois not found or fails to report its version.llgo version