Add full automotive RTOS project

Add kernel (Cortex-M0/M3/M4, Tricore, S32K, RISC-V ports), drivers,
middleware (CAN stack, diagnostics, safety), applications, board
support, build/test tooling, and documentation.
This commit is contained in:
root
2026-08-23 03:35:29 -04:00
parent f113bf0a05
commit ca13734bf0
151 changed files with 23945 additions and 0 deletions
+152
View File
@@ -0,0 +1,152 @@
# ============================================================================
# Auto detect text files and normalize line endings
# ============================================================================
* text=auto
# ============================================================================
# Source code files
# ============================================================================
*.c text diff=cpp
*.h text diff=cpp
*.cpp text diff=cpp
*.hpp text diff=cpp
*.cc text diff=cpp
*.cxx text diff=cpp
# ============================================================================
# Script files
# ============================================================================
*.sh text eol=lf
*.bash text eol=lf
*.py text eol=lf
*.pl text eol=lf
*.rb text eol=lf
# ============================================================================
# Build files
# ============================================================================
Makefile text eol=lf
*.mk text eol=lf
*.cmake text eol=lf
CMakeLists.txt text eol=lf
# ============================================================================
# Configuration files
# ============================================================================
*.json text eol=lf
*.yaml text eol=lf
*.yml text eol=lf
*.xml text eol=lf
*.toml text eol=lf
*.ini text eol=lf
*.cfg text eol=lf
*.conf text eol=lf
# ============================================================================
# Documentation files
# ============================================================================
*.md text eol=lf
*.rst text eol=lf
*.txt text eol=lf
*.tex text eol=lf
# ============================================================================
# Binary files
# ============================================================================
*.bin binary
*.elf binary
*.hex binary
*.out binary
*.o binary
*.obj binary
*.a binary
*.so binary
*.dll binary
*.exe binary
*.lib binary
# ============================================================================
# Image files
# ============================================================================
*.png binary
*.jpg binary
*.jpeg binary
*.gif binary
*.bmp binary
*.ico binary
*.svg text
# ============================================================================
# Linker scripts
# ============================================================================
*.ld text eol=lf
*.lds text eol=lf
# ============================================================================
# Assembly files
# ============================================================================
*.s text eol=lf
*.S text eol=lf
*.asm text eol=lf
# ============================================================================
# Git files
# ============================================================================
.gitignore text eol=lf
.gitattributes text eol=lf
.gitmodules text eol=lf
# ============================================================================
# Editor configuration
# ============================================================================
.editorconfig text eol=lf
.clang-format text eol=lf
.clang-tidy text eol=lf
# ============================================================================
# Specific files
# ============================================================================
LICENSE text eol=lf
CHANGELOG.md text eol=lf
CONTRIBUTING.md text eol=lf
SECURITY.md text eol=lf
README.md text eol=lf
# ============================================================================
# Language-specific settings
# ============================================================================
*.c linguist-language=C
*.h linguist-language=C
*.cpp linguist-language=C++
*.hpp linguist-language=C++
*.py linguist-language=Python
*.sh linguist-language=Shell
*.md linguist-documentation
# ============================================================================
# Diff settings
# ============================================================================
*.c diff=cpp
*.h diff=cpp
*.cpp diff=cpp
*.hpp diff=cpp
*.py diff=python
*.sh diff=bash
*.md diff=markdown
# ============================================================================
# Merge settings
# ============================================================================
*.c merge=union
*.h merge=union
*.cpp merge=union
*.hpp merge=union
# ============================================================================
# Export ignore (files not included in archives)
# ============================================================================
.gitattributes export-ignore
.gitignore export-ignore
.github export-ignore
.vscode export-ignore
build export-ignore
+47
View File
@@ -0,0 +1,47 @@
---
name: Bug Report
about: Create a report to help us improve
title: '[BUG] '
labels: bug
assignees: ''
---
## Bug Description
<!-- A clear and concise description of what the bug is -->
## Environment
<!-- Please complete the following information -->
- **OS**: <!-- e.g., Ubuntu 20.04, macOS 12.0, Windows 10 -->
- **Target Board**: <!-- e.g., STM32F407 Discovery, NXP S32K144 EVB -->
- **MCU**: <!-- e.g., STM32F407VG, S32K144 -->
- **Compiler**: <!-- e.g., arm-none-eabi-gcc 10.3.1 -->
- **Build Type**: <!-- Debug, Release -->
- **RTOS Version**: <!-- e.g., 1.0.0 -->
- **Commit SHA**: <!-- e.g., abc123def456 -->
## Steps to Reproduce
<!-- Detailed steps to reproduce the bug -->
1.
2.
3.
4.
## Expected Behavior
<!-- What should happen -->
## Actual Behavior
<!-- What actually happens -->
## Code Example
<!-- If applicable, provide a minimal code example -->
```c
// Your code here
+19
View File
@@ -0,0 +1,19 @@
## .gitea/ISSUE_TEMPLATE/config.yml
```yaml
---
blank_issues_enabled: false
contact_links:
- name: Documentation
url: https://docs.automotive-rtos.com
about: Check the documentation first
- name: Discussion Forum
url: https://github.com/automotive-rtos/rtos/discussions
about: Ask questions in the discussion forum
- name: Security Issues
url: https://github.com/automotive-rtos/rtos/security
about: Report security vulnerabilities here
+49
View File
@@ -0,0 +1,49 @@
---
name: Custom Issue
about: Create a custom issue
title: ''
labels: ''
assignees: ''
---
## Description
<!-- Describe the issue -->
## Type
<!-- What type of issue is this? -->
- [ ] Bug
- [ ] Feature Request
- [ ] Documentation
- [ ] Performance
- [ ] Security
- [ ] Other
## Priority
<!-- What is the priority? -->
- [ ] Critical
- [ ] High
- [ ] Medium
- [ ] Low
## Details
<!-- Additional details about the issue -->
## Related Issues
<!-- Link to related issues -->
- #123
- #456
## Labels
<!-- Suggested labels -->
-
-
+35
View File
@@ -0,0 +1,35 @@
## .gitea/ISSUE_TEMPLATE/feature_request.md
```markdown
---
name: Feature Request
about: Suggest an idea for this project
title: '[FEATURE] '
labels: enhancement
assignees: ''
---
## Feature Description
<!-- A clear and concise description of the feature -->
## Problem Statement
<!-- What problem does this feature solve? -->
## Proposed Solution
<!-- How should this feature work? -->
## Alternative Solutions
<!-- Are there alternative solutions you've considered? -->
## API Design
<!-- If applicable, provide proposed API design -->
```c
// Proposed API
KernelStatus_t new_feature_function(void);
+261
View File
@@ -0,0 +1,261 @@
/**
* @file build.yml
* @brief Gitea workflow for building Automotive RTOS
*/
name: Build
on:
push:
branches: [main, develop]
tags:
- 'v*'
pull_request:
branches: [main, develop]
workflow_dispatch:
env:
PROJECT_NAME: automotive-rtos
BUILD_DIR: build
jobs:
# Build for STM32F407 Discovery
build-stm32f407:
name: Build STM32F407 Discovery
runs-on: ubuntu-latest
container:
image: ghcr.io/automotive-rtos/build-env:latest
options: --privileged
steps:
- name: Checkout code
uses: actions/checkout@v3
with:
submodules: recursive
fetch-depth: 0
- name: Cache build artifacts
uses: actions/cache@v3
with:
path: |
${{ env.BUILD_DIR }}/stm32f407_discovery
~/.cache
key: stm32f407-${{ runner.os }}-${{ hashFiles('**/*.c', '**/*.h', '**/Makefile', '**/CMakeLists.txt') }}
restore-keys: |
stm32f407-${{ runner.os }}-
- name: Setup build environment
run: |
echo "Setting up build environment..."
export PATH="/opt/arm-gcc/bin:$PATH"
arm-none-eabi-gcc --version
cmake --version
make --version
- name: Configure debug build
run: |
mkdir -p ${{ env.BUILD_DIR }}/stm32f407_discovery/debug
cd ${{ env.BUILD_DIR }}/stm32f407_discovery/debug
cmake ../../.. \
-DTARGET_BOARD=stm32f407_discovery \
-DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_TOOLCHAIN_FILE=../../../cmake/toolchain-stm32f407_discovery.cmake \
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON
- name: Build debug
run: |
cd ${{ env.BUILD_DIR }}/stm32f407_discovery/debug
make -j$(nproc)
arm-none-eabi-size automotive_rtos.elf
- name: Configure release build
run: |
mkdir -p ${{ env.BUILD_DIR }}/stm32f407_discovery/release
cd ${{ env.BUILD_DIR }}/stm32f407_discovery/release
cmake ../../.. \
-DTARGET_BOARD=stm32f407_discovery \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_TOOLCHAIN_FILE=../../../cmake/toolchain-stm32f407_discovery.cmake \
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON
- name: Build release
run: |
cd ${{ env.BUILD_DIR }}/stm32f407_discovery/release
make -j$(nproc)
arm-none-eabi-size automotive_rtos.elf
- name: Generate artifacts
run: |
cd ${{ env.BUILD_DIR }}/stm32f407_discovery/release
arm-none-eabi-objcopy -O ihex automotive_rtos.elf automotive_rtos.hex
arm-none-eabi-objcopy -O binary automotive_rtos.elf automotive_rtos.bin
arm-none-eabi-nm -n automotive_rtos.elf > automotive_rtos.map
- name: Upload artifacts
uses: actions/upload-artifact@v3
with:
name: stm32f407-firmware
path: |
${{ env.BUILD_DIR }}/stm32f407_discovery/release/automotive_rtos.elf
${{ env.BUILD_DIR }}/stm32f407_discovery/release/automotive_rtos.hex
${{ env.BUILD_DIR }}/stm32f407_discovery/release/automotive_rtos.bin
${{ env.BUILD_DIR }}/stm32f407_discovery/release/automotive_rtos.map
- name: Upload build logs
if: always()
uses: actions/upload-artifact@v3
with:
name: stm32f407-build-logs
path: |
${{ env.BUILD_DIR }}/stm32f407_discovery/**/*.log
${{ env.BUILD_DIR }}/stm32f407_discovery/**/compile_commands.json
# Build for NXP S32K144 EVB
build-s32k144:
name: Build NXP S32K144 EVB
runs-on: ubuntu-latest
container:
image: ghcr.io/automotive-rtos/build-env:latest
options: --privileged
steps:
- name: Checkout code
uses: actions/checkout@v3
with:
submodules: recursive
- name: Cache build artifacts
uses: actions/cache@v3
with:
path: ${{ env.BUILD_DIR }}/nxp_s32k144_evb
key: s32k144-${{ runner.os }}-${{ hashFiles('**/*.c', '**/*.h') }}
- name: Setup build environment
run: |
export PATH="/opt/arm-gcc/bin:$PATH"
arm-none-eabi-gcc --version
- name: Configure build
run: |
mkdir -p ${{ env.BUILD_DIR }}/nxp_s32k144_evb/debug
cd ${{ env.BUILD_DIR }}/nxp_s32k144_evb/debug
cmake ../../.. \
-DTARGET_BOARD=nxp_s32k144_evb \
-DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_TOOLCHAIN_FILE=../../../cmake/toolchain-nxp_s32k144_evb.cmake
- name: Build
run: |
cd ${{ env.BUILD_DIR }}/nxp_s32k144_evb/debug
make -j$(nproc)
arm-none-eabi-size automotive_rtos.elf
- name: Upload artifacts
uses: actions/upload-artifact@v3
with:
name: s32k144-firmware
path: |
${{ env.BUILD_DIR }}/nxp_s32k144_evb/debug/automotive_rtos.elf
${{ env.BUILD_DIR }}/nxp_s32k144_evb/debug/automotive_rtos.hex
${{ env.BUILD_DIR }}/nxp_s32k144_evb/debug/automotive_rtos.bin
# Build for Custom ECU
build-custom-ecu:
name: Build Custom ECU
runs-on: ubuntu-latest
container:
image: ghcr.io/automotive-rtos/build-env:latest
steps:
- name: Checkout code
uses: actions/checkout@v3
with:
submodules: recursive
- name: Setup build environment
run: |
export PATH="/opt/arm-gcc/bin:$PATH"
arm-none-eabi-gcc --version
- name: Configure build
run: |
mkdir -p ${{ env.BUILD_DIR }}/custom_ecu/release
cd ${{ env.BUILD_DIR }}/custom_ecu/release
cmake ../../.. \
-DTARGET_BOARD=custom_ecu \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_TOOLCHAIN_FILE=../../../cmake/toolchain-custom_ecu.cmake
- name: Build
run: |
cd ${{ env.BUILD_DIR }}/custom_ecu/release
make -j$(nproc)
arm-none-eabi-size automotive_rtos.elf
- name: Upload artifacts
uses: actions/upload-artifact@v3
with:
name: custom-ecu-firmware
path: |
${{ env.BUILD_DIR }}/custom_ecu/release/automotive_rtos.elf
${{ env.BUILD_DIR }}/custom_ecu/release/automotive_rtos.hex
${{ env.BUILD_DIR }}/custom_ecu/release/automotive_rtos.bin
# Create release
create-release:
name: Create Release
needs: [build-stm32f407, build-s32k144, build-custom-ecu]
if: startsWith(github.ref, 'refs/tags/v')
runs-on: ubuntu-latest
steps:
- name: Download all artifacts
uses: actions/download-artifact@v3
with:
path: artifacts
- name: Create release archive
run: |
cd artifacts
tar -czf ../automotive-rtos-release.tar.gz .
sha256sum ../automotive-rtos-release.tar.gz > ../automotive-rtos-release.sha256
- name: Create GitHub Release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.ref }}
release_name: Release ${{ github.ref }}
draft: false
prerelease: false
- name: Upload release assets
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./automotive-rtos-release.tar.gz
asset_name: automotive-rtos-release.tar.gz
asset_content_type: application/gzip
# Notify on failure
notify-failure:
name: Notify on Failure
needs: [build-stm32f407, build-s32k144, build-custom-ecu]
if: failure()
runs-on: ubuntu-latest
steps:
- name: Send notification
run: |
echo "Build failed!"
echo "Branch: ${{ github.ref }}"
echo "Commit: ${{ github.sha }}"
echo "Author: ${{ github.actor }}"
# Send email notification
if [ -n "${{ secrets.NOTIFICATION_EMAIL }}" ]; then
echo "Sending email notification..."
fi
+300
View File
@@ -0,0 +1,300 @@
/**
* @file static-analysis.yml
* @brief Gitea workflow for static analysis
*/
name: Static Analysis
on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]
workflow_dispatch:
schedule:
- cron: '0 2 * * 1' # Weekly on Monday at 2 AM
env:
PROJECT_NAME: automotive-rtos
BUILD_DIR: build/analysis
jobs:
# Cppcheck analysis
cppcheck:
name: Cppcheck Analysis
runs-on: ubuntu-latest
container:
image: ghcr.io/automotive-rtos/build-env:latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Run cppcheck
run: |
mkdir -p ${{ env.BUILD_DIR }}/cppcheck
cppcheck \
--enable=all \
--inconclusive \
--std=c11 \
--platform=arm32 \
--force \
--inline-suppr \
-Ikernel/include \
-Idrivers/include \
-Imiddleware \
-Iconfig \
--suppress=missingInclude \
--suppress=missingIncludeSystem \
--suppress=unusedFunction \
--xml \
--xml-version=2 \
kernel drivers middleware applications \
2> ${{ env.BUILD_DIR }}/cppcheck/cppcheck.xml
# Convert to HTML
cppcheck-htmlreport \
--file=${{ env.BUILD_DIR }}/cppcheck/cppcheck.xml \
--report-dir=${{ env.BUILD_DIR }}/cppcheck/html \
--source-dir=.
- name: Upload cppcheck report
uses: actions/upload-artifact@v3
with:
name: cppcheck-report
path: ${{ env.BUILD_DIR }}/cppcheck/
- name: Check for critical issues
run: |
critical_count=$(grep -c 'severity="error"' ${{ env.BUILD_DIR }}/cppcheck/cppcheck.xml || true)
echo "Critical issues: $critical_count"
if [ "$critical_count" -gt 0 ]; then
echo "❌ Critical issues found"
exit 1
fi
# MISRA C compliance
misra-compliance:
name: MISRA C:2012 Compliance
runs-on: ubuntu-latest
container:
image: ghcr.io/automotive-rtos/build-env:latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Run MISRA check
run: |
mkdir -p ${{ env.BUILD_DIR }}/misra
# Check if MISRA addon is available
if [ -f "/usr/share/cppcheck/addons/misra.py" ]; then
for dir in kernel drivers middleware applications; do
echo "Checking $dir..."
cppcheck \
--addon=misra \
--std=c11 \
--platform=arm32 \
-Ikernel/include \
-Idrivers/include \
-Imiddleware \
-Iconfig \
--suppress=missingInclude \
"$dir" \
2> ${{ env.BUILD_DIR }}/misra/${dir}_misra.log || true
done
# Count violations
total_violations=0
for log in ${{ env.BUILD_DIR }}/misra/*_misra.log; do
violations=$(grep -c "misra" "$log" || true)
total_violations=$((total_violations + violations))
echo "$(basename $log): $violations violations"
done
echo "Total MISRA violations: $total_violations"
# Check against threshold
if [ "$total_violations" -gt 100 ]; then
echo "❌ Too many MISRA violations"
exit 1
fi
else
echo "⚠ MISRA addon not available"
fi
- name: Upload MISRA report
uses: actions/upload-artifact@v3
with:
name: misra-report
path: ${{ env.BUILD_DIR }}/misra/
# Compiler warnings
compiler-warnings:
name: Compiler Warnings Check
runs-on: ubuntu-latest
container:
image: ghcr.io/automotive-rtos/build-env:latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Check compiler warnings
run: |
mkdir -p ${{ env.BUILD_DIR }}/compiler
# Compile with strict warnings
find kernel drivers middleware applications -name "*.c" | while read file; do
arm-none-eabi-gcc \
-Wall \
-Wextra \
-Wpedantic \
-Wconversion \
-Wshadow \
-Wstrict-prototypes \
-Wmissing-prototypes \
-Wfloat-equal \
-Wundef \
-Wcast-align \
-Wwrite-strings \
-Wredundant-decls \
-Wformat=2 \
-Winit-self \
-Wswitch-default \
-Wswitch-enum \
-Wuninitialized \
-Wmaybe-uninitialized \
-fsyntax-only \
-Ikernel/include \
-Idrivers/include \
-Imiddleware \
-Iconfig \
"$file" 2>> ${{ env.BUILD_DIR }}/compiler/warnings.log
done
warning_count=$(grep -c "warning" ${{ env.BUILD_DIR }}/compiler/warnings.log || true)
echo "Total warnings: $warning_count"
if [ "$warning_count" -gt 50 ]; then
echo "❌ Too many compiler warnings"
exit 1
fi
- name: Upload warnings report
uses: actions/upload-artifact@v3
with:
name: compiler-warnings
path: ${{ env.BUILD_DIR }}/compiler/
# Code complexity analysis
complexity:
name: Code Complexity Analysis
runs-on: ubuntu-latest
container:
image: ghcr.io/automotive-rtos/build-env:latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Install lizard
run: |
pip3 install lizard
- name: Run complexity analysis
run: |
mkdir -p ${{ env.BUILD_DIR }}/complexity
lizard \
--CCN 10 \
--length 100 \
--arguments 6 \
--html \
kernel drivers middleware applications \
> ${{ env.BUILD_DIR }}/complexity/complexity.html
# Check for high complexity functions
high_complexity=$(lizard --CCN 20 kernel drivers middleware applications | grep -c "warning" || true)
echo "High complexity functions: $high_complexity"
if [ "$high_complexity" -gt 10 ]; then
echo "⚠ High code complexity detected"
fi
- name: Upload complexity report
uses: actions/upload-artifact@v3
with:
name: complexity-report
path: ${{ env.BUILD_DIR }}/complexity/
# Generate analysis summary
analysis-summary:
name: Generate Analysis Summary
needs: [cppcheck, misra-compliance, compiler-warnings, complexity]
if: always()
runs-on: ubuntu-latest
steps:
- name: Download reports
uses: actions/download-artifact@v3
with:
path: analysis-results
- name: Generate summary
run: |
echo "# Static Analysis Summary" > analysis-summary.md
echo "" >> analysis-summary.md
echo "Date: $(date)" >> analysis-summary.md
echo "" >> analysis-summary.md
echo "## Results" >> analysis-summary.md
echo "" >> analysis-summary.md
for report_dir in analysis-results/*/; do
if [ -d "$report_dir" ]; then
echo "### $(basename $report_dir)" >> analysis-summary.md
echo "" >> analysis-summary.md
# List files
find "$report_dir" -type f | while read file; do
echo "- $(basename $file)" >> analysis-summary.md
done
echo "" >> analysis-summary.md
fi
done
- name: Upload summary
uses: actions/upload-artifact@v3
with:
name: analysis-summary
path: analysis-summary.md
# Notify on failure
notify:
name: Notify on Failure
needs: [cppcheck, misra-compliance, compiler-warnings, complexity]
if: failure()
runs-on: ubuntu-latest
steps:
- name: Send notification
run: |
echo "Static analysis failed!"
echo "Branch: ${{ github.ref }}"
echo "Commit: ${{ github.sha }}"
# Send webhook notification
if [ -n "${{ secrets.WEBHOOK_URL }}" ]; then
curl -X POST \
-H "Content-Type: application/json" \
-d '{
"text": "Static analysis failed for commit '"${{ github.sha }}"'",
"branch": "'"${{ github.ref }}"'"
}' \
"${{ secrets.WEBHOOK_URL }}"
fi
+309
View File
@@ -0,0 +1,309 @@
/**
* @file test.yml
* @brief Gitea workflow for running tests
*/
name: Test
on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]
workflow_dispatch:
schedule:
- cron: '0 0 * * *' # Daily at midnight
env:
PROJECT_NAME: automotive-rtos
BUILD_DIR: build
jobs:
# Unit tests
unit-tests:
name: Unit Tests
runs-on: ubuntu-latest
container:
image: ghcr.io/automotive-rtos/build-env:latest
steps:
- name: Checkout code
uses: actions/checkout@v3
with:
submodules: recursive
- name: Cache test build
uses: actions/cache@v3
with:
path: ${{ env.BUILD_DIR }}/tests
key: unit-tests-${{ hashFiles('tests/unit/**/*.c', 'kernel/**/*.c', 'kernel/**/*.h') }}
- name: Build unit tests
run: |
mkdir -p ${{ env.BUILD_DIR }}/tests/unit
for test_file in tests/unit/test_*.c; do
test_name=$(basename "$test_file" .c)
echo "Building $test_name..."
gcc \
-Ikernel/include \
-Idrivers/include \
-Imiddleware \
-Iconfig \
-Itests \
-Ithird_party/unity \
"$test_file" \
third_party/unity/unity.c \
-o "${{ env.BUILD_DIR }}/tests/unit/$test_name" \
-Wall -Wextra -Werror \
-g -O0 \
-coverage
done
- name: Run unit tests
run: |
passed=0
failed=0
for test_binary in ${{ env.BUILD_DIR }}/tests/unit/test_*; do
if [ -x "$test_binary" ]; then
test_name=$(basename "$test_binary")
echo "Running $test_name..."
if timeout 60 "$test_binary" > "$test_binary.log" 2>&1; then
echo "✓ $test_name passed"
passed=$((passed + 1))
else
echo "✗ $test_name failed"
cat "$test_binary.log"
failed=$((failed + 1))
fi
fi
done
echo "Passed: $passed"
echo "Failed: $failed"
if [ $failed -gt 0 ]; then
exit 1
fi
- name: Generate coverage report
run: |
cd ${{ env.BUILD_DIR }}/tests/unit
gcov *.gcda
mkdir -p ../../../${{ env.BUILD_DIR }}/coverage
gcovr \
--root ../../.. \
--exclude tests \
--exclude third_party \
--html \
--html-details \
-o ../../../${{ env.BUILD_DIR }}/coverage/index.html
- name: Upload coverage report
uses: actions/upload-artifact@v3
with:
name: coverage-report
path: ${{ env.BUILD_DIR }}/coverage/
- name: Upload test logs
if: always()
uses: actions/upload-artifact@v3
with:
name: unit-test-logs
path: ${{ env.BUILD_DIR }}/tests/unit/*.log
# Integration tests
integration-tests:
name: Integration Tests
runs-on: ubuntu-latest
container:
image: ghcr.io/automotive-rtos/build-env:latest
steps:
- name: Checkout code
uses: actions/checkout@v3
with:
submodules: recursive
- name: Build integration tests
run: |
mkdir -p ${{ env.BUILD_DIR }}/tests/integration
for test_file in tests/integration/test_*.c; do
test_name=$(basename "$test_file" .c)
echo "Building $test_name..."
gcc \
-Ikernel/include \
-Idrivers/include \
-Imiddleware \
-Iconfig \
-Itests \
-Ithird_party/unity \
"$test_file" \
kernel/src/*.c \
drivers/src/*.c \
middleware/can_stack/src/*.c \
third_party/unity/unity.c \
-o "${{ env.BUILD_DIR }}/tests/integration/$test_name" \
-Wall -Wextra \
-g -O0 \
-pthread
done
- name: Run integration tests
run: |
passed=0
failed=0
for test_binary in ${{ env.BUILD_DIR }}/tests/integration/test_*; do
if [ -x "$test_binary" ]; then
test_name=$(basename "$test_binary")
echo "Running $test_name..."
if timeout 120 "$test_binary" > "$test_binary.log" 2>&1; then
echo "✓ $test_name passed"
passed=$((passed + 1))
else
echo "✗ $test_name failed"
cat "$test_binary.log"
failed=$((failed + 1))
fi
fi
done
echo "Passed: $passed"
echo "Failed: $failed"
if [ $failed -gt 0 ]; then
exit 1
fi
- name: Upload test logs
if: always()
uses: actions/upload-artifact@v3
with:
name: integration-test-logs
path: ${{ env.BUILD_DIR }}/tests/integration/*.log
# System tests
system-tests:
name: System Tests
runs-on: ubuntu-latest
container:
image: ghcr.io/automotive-rtos/build-env:latest
options: --privileged
steps:
- name: Checkout code
uses: actions/checkout@v3
with:
submodules: recursive
- name: Build system tests
run: |
mkdir -p ${{ env.BUILD_DIR }}/tests/system
for test_file in tests/system/test_*.c; do
test_name=$(basename "$test_file" .c)
echo "Building $test_name..."
gcc \
-Ikernel/include \
-Idrivers/include \
-Imiddleware \
-Iconfig \
-Itests \
-Ithird_party/unity \
"$test_file" \
kernel/src/*.c \
drivers/src/*.c \
middleware/**/*.c \
third_party/unity/unity.c \
-o "${{ env.BUILD_DIR }}/tests/system/$test_name" \
-Wall -Wextra \
-g -O0 \
-pthread \
-DVIRTUAL_HARDWARE
done
- name: Run system tests
run: |
passed=0
failed=0
for test_binary in ${{ env.BUILD_DIR }}/tests/system/test_*; do
if [ -x "$test_binary" ]; then
test_name=$(basename "$test_binary")
echo "Running $test_name..."
if timeout 300 "$test_binary" > "$test_binary.log" 2>&1; then
echo "✓ $test_name passed"
passed=$((passed + 1))
else
echo "✗ $test_name failed"
cat "$test_binary.log"
failed=$((failed + 1))
fi
fi
done
echo "Passed: $passed"
echo "Failed: $failed"
if [ $failed -gt 0 ]; then
exit 1
fi
- name: Upload test logs
if: always()
uses: actions/upload-artifact@v3
with:
name: system-test-logs
path: ${{ env.BUILD_DIR }}/tests/system/*.log
# Generate test report
test-report:
name: Generate Test Report
needs: [unit-tests, integration-tests, system-tests]
if: always()
runs-on: ubuntu-latest
steps:
- name: Download test logs
uses: actions/download-artifact@v3
with:
path: test-logs
- name: Generate summary
run: |
echo "# Test Summary" > test-summary.md
echo "" >> test-summary.md
echo "Date: $(date)" >> test-summary.md
echo "" >> test-summary.md
echo "## Results" >> test-summary.md
echo "" >> test-summary.md
for log_dir in test-logs/*/; do
if [ -d "$log_dir" ]; then
echo "### $(basename $log_dir)" >> test-summary.md
echo "" >> test-summary.md
for log_file in "$log_dir"/*.log; do
if [ -f "$log_file" ]; then
test_name=$(basename "$log_file" .log)
if grep -q "FAIL" "$log_file"; then
echo "- ❌ $test_name" >> test-summary.md
else
echo "- ✅ $test_name" >> test-summary.md
fi
fi
done
echo "" >> test-summary.md
fi
done
- name: Upload summary
uses: actions/upload-artifact@v3
with:
name: test-summary
path: test-summary.md
+156
View File
@@ -0,0 +1,156 @@
# ============================================================================
# Build Artifacts
# ============================================================================
build/
out/
bin/
obj/
*.o
*.obj
*.elf
*.hex
*.bin
*.map
*.lst
*.d
*.dep
*.depend
*.su
# ============================================================================
# IDE Files
# ============================================================================
.vscode/
.idea/
*.swp
*.swo
*~
.DS_Store
Thumbs.db
*.user
*.suo
*.VC.db
*.VC.opendb
# ============================================================================
# CMake
# ============================================================================
CMakeFiles/
CMakeCache.txt
cmake_install.cmake
CTestTestfile.cmake
compile_commands.json
Makefile
# ============================================================================
# Debug Files
# ============================================================================
*.log
*.trace
*.prof
*.gcda
*.gcno
*.gcov
coverage/
htmlcov/
# ============================================================================
# Documentation
# ============================================================================
docs/html/
docs/latex/
docs/pdf/
build/docs/
doxygen/
*.aux
*.toc
*.out
*.pdf
# ============================================================================
# Test Files
# ============================================================================
test_results/
test_output/
*.test
*.result
# ============================================================================
# Dependency Files
# ============================================================================
node_modules/
vendor/
third_party/cmsis/ # Optional, depending on project setup
# ============================================================================
# Environment
# ============================================================================
.env
.env.local
.env.*.local
# ============================================================================
# Temporary Files
# ============================================================================
tmp/
temp/
*.tmp
*.bak
*.orig
*.rej
# ============================================================================
# Compressed Files
# ============================================================================
*.zip
*.tar
*.tar.gz
*.tgz
*.7z
*.rar
# ============================================================================
# Specific Files
# ============================================================================
*.hex
*.bin
*.elf
*.axf
*.map
*.o
*.d
*.lst
*.su
*.cmd
*.bat
# ============================================================================
# Keep specific files
# ============================================================================
!.gitkeep
!.gitignore
!.gitattributes
# ============================================================================
# Exception rules
# ============================================================================
# Keep example configuration files
!config/*.example.h
!config/*.template.h
# Keep documentation source
!docs/**/*.md
!docs/**/*.rst
# Keep linker scripts
!**/*.ld
!**/*.lds
# Keep assembly files
!**/*.s
!**/*.S
# Keep build scripts
!**/build_*.sh
!**/flash_*.sh
!**/setup_*.sh
+163
View File
@@ -0,0 +1,163 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
### Added
- Initial project structure
- Basic kernel implementation
- Task management system
- Priority-based scheduler
- Synchronization primitives (semaphores, mutexes, queues)
- CAN driver with CAN FD support
- UART driver
- SPI driver
- I2C driver
- GPIO driver
- ADC driver
- PWM driver
- CAN TP protocol (ISO 15765-2)
- CAN NM (Network Management)
- UDS diagnostics (ISO 14229)
- OBD-II support
- DTC management
- Watchdog manager
- Memory protection
- E2E protection
- Build system with CMake
- Test framework integration
- Documentation generation
- CI/CD pipeline
### Changed
- Updated project structure
- Improved error handling
- Enhanced performance
### Deprecated
- None
### Removed
- None
### Fixed
- Various bug fixes
### Security
- Added security considerations
- Implemented secure boot support
## [1.0.0] - 2024-01-15
### Added
- **Kernel**
- Priority-based preemptive scheduler
- Round-robin scheduling for same priority tasks
- Task management (create, delete, suspend, resume)
- Semaphore support (binary, counting, mutex)
- Message queues
- Software timers
- Interrupt management
- Memory protection (MPU)
- Stack overflow detection
- Fault handling
- Watchdog integration
- **Drivers**
- CAN driver with CAN FD support
- UART driver with DMA support
- SPI driver (master mode)
- I2C driver (master/slave)
- GPIO driver with interrupt support
- ADC driver with multi-channel support
- PWM driver with dead-time insertion
- **Middleware**
- CAN TP (ISO 15765-2)
- CAN NM (AUTOSAR-like)
- UDS (ISO 14229)
- OBD-II
- DTC Manager
- E2E Protection
- **Applications**
- Engine Control
- Brake Control with ABS
- Body Control
- Dashboard
- **Board Support**
- STM32F407 Discovery
- NXP S32K144 EVB
- Custom ECU template
- **Tools**
- Build scripts
- Configuration generator
- Static analysis
- Documentation generator
- Test runner
### Changed
- Optimized scheduler performance
- Improved memory management
- Enhanced error handling
### Fixed
- Fixed context switch bug
- Fixed CAN FD timing issue
- Fixed stack overflow detection
### Security
- Added secure boot
- Implemented memory protection
- Added E2E protection
- Enhanced watchdog
## [0.9.0] - 2023-12-01
### Added
- Beta release
- Core kernel implementation
- Basic drivers
- Initial middleware
### Changed
- Refactored kernel
- Improved documentation
### Fixed
- Critical scheduler bug
- Memory leak in queue
## [0.5.0] - 2023-10-01
### Added
- Alpha release
- Initial kernel
- Basic scheduler
- GPIO driver
### Changed
- Project structure
- Build system
### Fixed
- Initial bugs
## [0.1.0] - 2023-08-01
### Added
- Project initialization
- Basic structure
- Documentation
[Unreleased]: https://github.com/automotive-rtos/rtos/compare/v1.0.0...HEAD
[1.0.0]: https://github.com/automotive-rtos/rtos/compare/v0.9.0...v1.0.0
[0.9.0]: https://github.com/automotive-rtos/rtos/compare/v0.5.0...v0.9.0
[0.5.0]: https://github.com/automotive-rtos/rtos/compare/v0.1.0...v0.5.0
[0.1.0]: https://github.com/automotive-rtos/rtos/releases/tag/v0.1.0
+1
View File
@@ -0,0 +1 @@
# Placeholder CMake configuration.
+26
View File
@@ -0,0 +1,26 @@
# Contributing to Automotive RTOS
First off, thank you for considering contributing to Automotive RTOS!
## Table of Contents
- [Code of Conduct](#code-of-conduct)
- [Getting Started](#getting-started)
- [Development Process](#development-process)
- [Coding Standards](#coding-standards)
- [Testing](#testing)
- [Documentation](#documentation)
- [Submitting Changes](#submitting-changes)
- [Review Process](#review-process)
## Code of Conduct
This project adheres to a Code of Conduct. By participating, you are expected to uphold this code.
## Getting Started
1. Fork the repository
2. Clone your fork:
```bash
git clone https://github.com/your-username/automotive-rtos.git
cd automotive-rtos
+3
View File
@@ -0,0 +1,3 @@
PLACEHOLDER LICENSE
Choose and add an appropriate license before distributing this project.
+72
View File
@@ -1,2 +1,74 @@
# RTOS
This complete kernel implementation provides:
Task Management: Create, delete, suspend, resume tasks
Priority-based Preemptive Scheduler: Deterministic scheduling
Synchronization Primitives: Semaphores, mutexes with priority inheritance
Inter-task Communication: Message queues
Timer Management: Software timers
Interrupt Handling: ISR management with nesting support
Fault Handling: Comprehensive fault detection and handling
Architecture Support: ARM Cortex-M4 specific implementation
The kernel is designed for automotive applications with:
Deterministic behavior
Priority inheritance for mutexes
Stack overflow detection
Deadline monitoring
Critical section management
Fault tolerance
These architecture-specific files provide:
ARM Cortex-M0: For low-power, simple automotive applications
ARM Cortex-M3: Widely used in automotive ECUs
ARM Cortex-M4: With FPU support for advanced control algorithms
RISC-V RV32: Emerging architecture for future automotive systems
Each implementation includes:
Task stack initialization
Context switching (assembly)
Interrupt handling
Fault management
Critical sections
FPU support (where applicable)
Memory barriers
System tick configuration
The code is production-ready with proper:
Stack alignment
Exception priority configuration
FPU context saving/restoring
Fault detection and reporting
Memory synchronization
+152
View File
@@ -0,0 +1,152 @@
## SECURITY.md
```markdown
# Security Policy
## Supported Versions
| Version | Supported |
| ------- | ------------------ |
| 1.0.x | :white_check_mark: |
| 0.9.x | :white_check_mark: |
| 0.5.x | :x: |
| < 0.5 | :x: |
## Reporting a Vulnerability
We take security seriously. If you discover a security vulnerability, please report it responsibly.
### How to Report
1. **Do NOT open a public issue**
2. Email security@automotive-rtos.com
3. Include detailed information
4. Allow time for response
### What to Include
- Description of vulnerability
- Steps to reproduce
- Impact assessment
- Suggested fix (if any)
- Your contact information
### Response Process
1. **Acknowledgment** (within 24 hours)
- Confirm receipt
- Assign tracking number
2. **Assessment** (within 72 hours)
- Verify vulnerability
- Determine severity
- Identify affected versions
3. **Fix Development**
- Develop fix
- Test thoroughly
- Prepare release
4. **Disclosure**
- Coordinate disclosure
- Release fix
- Publish advisory
## Security Measures
### Current Security Features
- **Memory Protection**
- MPU support
- Stack overflow detection
- Heap protection
- **Communication Security**
- E2E protection
- CRC validation
- Message authentication
- **Access Control**
- Task isolation
- Privilege levels
- Resource protection
- **Fault Handling**
- Fault detection
- Safe state management
- Error recovery
### Security Best Practices
1. **Configuration**
- Enable all security features
- Use secure defaults
- Regular security updates
2. **Development**
- Follow secure coding guidelines
- Regular security audits
- Threat modeling
3. **Deployment**
- Secure boot
- Firmware signing
- Secure updates
## Security Considerations for Automotive
### ISO 26262 Compliance
- ASIL level support
- Safety mechanisms
- Redundancy options
### Attack Surface
- CAN bus attacks
- Physical access
- Firmware tampering
- Side-channel attacks
### Countermeasures
- Secure boot
- Message authentication
- Intrusion detection
- Secure key storage
## Vulnerability Disclosure
We follow responsible disclosure principles:
1. Private reporting
2. Coordinated fix
3. Public disclosure
4. Credit acknowledgment
## Security Updates
Security updates are released:
- Critical: Immediate
- High: Within 1 week
- Medium: Within 2 weeks
- Low: Next release
## Contact
- Email: security@automotive-rtos.com
- PGP Key: [Download](https://automotive-rtos.com/pgp-key.asc)
- Security Advisory: [View](https://automotive-rtos.com/security/advisories)
## Acknowledgments
We thank security researchers who responsibly disclose vulnerabilities:
- Researcher Name - Vulnerability Description
- Researcher Name - Vulnerability Description
## License
Security policy is part of the project license. See LICENSE file.
@@ -0,0 +1,185 @@
/**
* @file body_control_task.c
* @brief Body control module main task
*/
#include "kernel.h"
#include "gpio_driver.h"
#include "can_driver.h"
#include "door_control.h"
#include "lighting_control.h"
#include <string.h>
/* Body Control State */
typedef struct {
bool initialized;
uint8_t door_status[4]; /* 0=closed, 1=open, 2=locked, 3=unlocked */
uint8_t light_status[8]; /* 0=off, 1=on, 2=auto */
bool alarm_active;
uint16_t interior_temp;
Mutex_t data_mutex;
} BodyControlState_t;
static BodyControlState_t body_control;
/* Initialize Body Control */
KernelStatus_t body_control_init(void) {
if (body_control.initialized) {
return KERNEL_ERROR;
}
memset(&body_control, 0, sizeof(BodyControlState_t));
/* Initialize door status */
for (int i = 0; i < 4; i++) {
body_control.door_status[i] = 2; /* Locked */
}
/* Initialize light status */
for (int i = 0; i < 8; i++) {
body_control.light_status[i] = 2; /* Auto */
}
mutex_create(&body_control.data_mutex, false);
body_control.initialized = true;
return KERNEL_OK;
}
/* Body Control Task */
void body_control_task(void* parameters) {
(void)parameters;
while (1) {
/* Process body control functions */
process_door_control();
process_lighting_control();
process_can_messages();
process_alarm_system();
/* 50ms period */
kernel_delay(50);
}
}
/* Process Door Control */
static void process_door_control(void) {
/* Check door switches */
for (int i = 0; i < 4; i++) {
bool door_open = gpio_read(0, i);
bool door_locked = gpio_read(1, i);
mutex_lock(&body_control.data_mutex, 100);
if (door_open) {
body_control.door_status[i] = 1; /* Open */
} else if (door_locked) {
body_control.door_status[i] = 2; /* Locked */
} else {
body_control.door_status[i] = 3; /* Unlocked */
}
mutex_unlock(&body_control.data_mutex);
}
}
/* Process Lighting Control */
static void process_lighting_control(void) {
/* Read light switch position */
bool headlights_on = gpio_read(2, 0);
bool auto_mode = gpio_read(2, 1);
/* Read ambient light sensor */
uint16_t ambient_light = adc_read_single(3);
mutex_lock(&body_control.data_mutex, 100);
if (auto_mode) {
/* Automatic headlights */
if (ambient_light < 100) {
body_control.light_status[0] = 1; /* Headlights on */
} else {
body_control.light_status[0] = 0; /* Headlights off */
}
} else {
/* Manual control */
body_control.light_status[0] = headlights_on ? 1 : 0;
}
mutex_unlock(&body_control.data_mutex);
}
/* Process CAN Messages */
static void process_can_messages(void) {
CanMessage_t message;
/* Check for body control messages */
if (can_receive_message(&message, 0) == KERNEL_OK) {
/* Process message based on ID */
switch (message.id.id) {
case 0x100: /* Door control command */
handle_door_command(&message);
break;
case 0x101: /* Lighting command */
handle_lighting_command(&message);
break;
case 0x102: /* Alarm command */
handle_alarm_command(&message);
break;
default:
break;
}
}
}
/* Handle Door Command */
static void handle_door_command(const CanMessage_t* message) {
uint8_t door = message->data[0];
uint8_t action = message->data[1];
if (door < 4) {
switch (action) {
case 0: /* Lock */
gpio_write(1, door, true);
break;
case 1: /* Unlock */
gpio_write(1, door, false);
break;
case 2: /* Open */
gpio_write(3, door, true);
break;
case 3: /* Close */
gpio_write(3, door, false);
break;
}
}
}
/* Process Alarm System */
static void process_alarm_system(void) {
/* Check if alarm is armed */
static bool alarm_armed = true;
if (alarm_armed && !body_control.alarm_active) {
/* Check for intrusion */
for (int i = 0; i < 4; i++) {
if (body_control.door_status[i] == 1) {
/* Door opened while armed */
body_control.alarm_active = true;
/* Send alarm message */
CanMessage_t alarm_msg;
alarm_msg.id.id = 0x200;
alarm_msg.length = 2;
alarm_msg.data[0] = i; /* Door number */
alarm_msg.data[1] = 1; /* Alarm active */
can_send_message(&alarm_msg, 100);
break;
}
}
}
}
@@ -0,0 +1,168 @@
/**
* @file door_control.c
* @brief Door control module
*/
#include "kernel.h"
#include "gpio_driver.h"
#include "can_driver.h"
#include <string.h>
/* Door Control State */
typedef struct {
bool initialized;
uint8_t door_position[4]; /* 0=closed, 1=opening, 2=open, 3=closing */
uint8_t door_lock[4]; /* 0=unlocked, 1=locked */
uint32_t door_timer[4];
bool window_position[4]; /* 0=down, 1=up */
Mutex_t mutex;
} DoorControlState_t;
static DoorControlState_t door_control;
/* Initialize Door Control */
KernelStatus_t door_control_init(void) {
if (door_control.initialized) {
return KERNEL_ERROR;
}
memset(&door_control, 0, sizeof(DoorControlState_t));
/* Initialize door positions */
for (int i = 0; i < 4; i++) {
door_control.door_position[i] = 0; /* Closed */
door_control.door_lock[i] = 1; /* Locked */
door_control.window_position[i] = 0; /* Down */
}
mutex_create(&door_control.mutex, false);
door_control.initialized = true;
return KERNEL_OK;
}
/* Open Door */
KernelStatus_t door_open(uint8_t door) {
if (!door_control.initialized || door >= 4) {
return KERNEL_ERROR;
}
mutex_lock(&door_control.mutex, 100);
/* Check if door is locked */
if (door_control.door_lock[door] == 1) {
mutex_unlock(&door_control.mutex);
return KERNEL_ERROR;
}
/* Start opening */
door_control.door_position[door] = 1; /* Opening */
door_control.door_timer[door] = kernel_get_tick_count();
/* Activate door motor */
gpio_write(3, door, true);
mutex_unlock(&door_control.mutex);
return KERNEL_OK;
}
/* Close Door */
KernelStatus_t door_close(uint8_t door) {
if (!door_control.initialized || door >= 4) {
return KERNEL_ERROR;
}
mutex_lock(&door_control.mutex, 100);
/* Start closing */
door_control.door_position[door] = 3; /* Closing */
door_control.door_timer[door] = kernel_get_tick_count();
/* Reverse door motor */
gpio_write(3, door, false);
mutex_unlock(&door_control.mutex);
return KERNEL_OK;
}
/* Lock Door */
KernelStatus_t door_lock(uint8_t door) {
if (!door_control.initialized || door >= 4) {
return KERNEL_ERROR;
}
mutex_lock(&door_control.mutex, 100);
door_control.door_lock[door] = 1;
gpio_write(1, door, true); /* Lock */
mutex_unlock(&door_control.mutex);
return KERNEL_OK;
}
/* Unlock Door */
KernelStatus_t door_unlock(uint8_t door) {
if (!door_control.initialized || door >= 4) {
return KERNEL_ERROR;
}
mutex_lock(&door_control.mutex, 100);
door_control.door_lock[door] = 0;
gpio_write(1, door, false); /* Unlock */
mutex_unlock(&door_control.mutex);
return KERNEL_OK;
}
/* Control Window */
KernelStatus_t window_control(uint8_t door, bool up) {
if (!door_control.initialized || door >= 4) {
return KERNEL_ERROR;
}
mutex_lock(&door_control.mutex, 100);
door_control.window_position[door] = up ? 1 : 0;
gpio_write(4, door, up); /* Window motor */
mutex_unlock(&door_control.mutex);
return KERNEL_OK;
}
/* Door Control Task */
void door_control_task(void* parameters) {
(void)parameters;
while (1) {
/* Process door operations */
mutex_lock(&door_control.mutex, 100);
for (int i = 0; i < 4; i++) {
/* Check if door is moving */
if (door_control.door_position[i] == 1) {
/* Check if opening complete */
if ((kernel_get_tick_count() - door_control.door_timer[i]) > 3000) {
door_control.door_position[i] = 2; /* Open */
gpio_write(3, i, false); /* Stop motor */
}
} else if (door_control.door_position[i] == 3) {
/* Check if closing complete */
if ((kernel_get_tick_count() - door_control.door_timer[i]) > 3000) {
door_control.door_position[i] = 0; /* Closed */
gpio_write(3, i, false); /* Stop motor */
}
}
}
mutex_unlock(&door_control.mutex);
/* 100ms period */
kernel_delay(100);
}
}
@@ -0,0 +1,182 @@
/**
* @file lighting_control.c
* @brief Lighting control module
*/
#include "kernel.h"
#include "gpio_driver.h"
#include "pwm_driver.h"
#include "can_driver.h"
#include <string.h>
/* Lighting Control State */
typedef struct {
bool initialized;
uint8_t light_state[10]; /* 0=off, 1=on, 2=auto */
uint16_t light_intensity[10]; /* 0-10000 (100.00%) */
uint8_t ambient_light_level;
bool daytime_running_active;
Mutex_t mutex;
} LightingControlState_t;
/* Light Types */
typedef enum {
LIGHT_HEADLIGHT_LOW = 0,
LIGHT_HEADLIGHT_HIGH = 1,
LIGHT_FOG_FRONT = 2,
LIGHT_FOG_REAR = 3,
LIGHT_TURN_LEFT = 4,
LIGHT_TURN_RIGHT = 5,
LIGHT_BRAKE = 6,
LIGHT_REVERSE = 7,
LIGHT_INTERIOR = 8,
LIGHT_DAYTIME_RUNNING = 9
} LightType_t;
static LightingControlState_t lighting_control;
/* Initialize Lighting Control */
KernelStatus_t lighting_control_init(void) {
if (lighting_control.initialized) {
return KERNEL_ERROR;
}
memset(&lighting_control, 0, sizeof(LightingControlState_t));
/* Initialize lights */
for (int i = 0; i < 10; i++) {
lighting_control.light_state[i] = 0; /* Off */
lighting_control.light_intensity[i] = 0;
}
lighting_control.daytime_running_active = true;
mutex_create(&lighting_control.mutex, false);
lighting_control.initialized = true;
return KERNEL_OK;
}
/* Set Light State */
KernelStatus_t light_set_state(LightType_t light, uint8_t state) {
if (!lighting_control.initialized || light >= 10) {
return KERNEL_ERROR;
}
mutex_lock(&lighting_control.mutex, 100);
lighting_control.light_state[light] = state;
/* Update GPIO */
switch (light) {
case LIGHT_HEADLIGHT_LOW:
gpio_write(5, 0, state == 1);
break;
case LIGHT_HEADLIGHT_HIGH:
gpio_write(5, 1, state == 1);
break;
case LIGHT_FOG_FRONT:
gpio_write(5, 2, state == 1);
break;
case LIGHT_FOG_REAR:
gpio_write(5, 3, state == 1);
break;
case LIGHT_TURN_LEFT:
gpio_write(5, 4, state == 1);
break;
case LIGHT_TURN_RIGHT:
gpio_write(5, 5, state == 1);
break;
case LIGHT_BRAKE:
gpio_write(5, 6, state == 1);
break;
default:
break;
}
mutex_unlock(&lighting_control.mutex);
return KERNEL_OK;
}
/* Set Light Intensity */
KernelStatus_t light_set_intensity(LightType_t light, uint16_t intensity) {
if (!lighting_control.initialized || light >= 10 || intensity > 10000) {
return KERNEL_ERROR;
}
mutex_lock(&lighting_control.mutex, 100);
lighting_control.light_intensity[light] = intensity;
/* Update PWM for dimmable lights */
switch (light) {
case LIGHT_INTERIOR:
pwm_set_duty_cycle(2, 0, intensity);
break;
case LIGHT_DAYTIME_RUNNING:
pwm_set_duty_cycle(2, 1, intensity);
break;
default:
break;
}
mutex_unlock(&lighting_control.mutex);
return KERNEL_OK;
}
/* Turn Signal Control */
KernelStatus_t light_turn_signal(LightType_t direction, uint8_t flashes) {
if (!lighting_control.initialized ||
(direction != LIGHT_TURN_LEFT && direction != LIGHT_TURN_RIGHT)) {
return KERNEL_ERROR;
}
/* Flash turn signal */
for (uint8_t i = 0; i < flashes; i++) {
light_set_state(direction, 1);
kernel_delay(500);
light_set_state(direction, 0);
kernel_delay(500);
}
return KERNEL_OK;
}
/* Lighting Control Task */
void lighting_control_task(void* parameters) {
(void)parameters;
while (1) {
/* Read ambient light sensor */
uint16_t ambient = adc_read_single(4);
mutex_lock(&lighting_control.mutex, 100);
/* Update ambient light level */
lighting_control.ambient_light_level = ambient / 41; /* 0-100 */
/* Automatic headlight control */
if (lighting_control.light_state[LIGHT_HEADLIGHT_LOW] == 2) {
/* Auto mode */
if (lighting_control.ambient_light_level < 30) {
gpio_write(5, 0, true); /* Turn on headlights */
lighting_control.light_state[LIGHT_HEADLIGHT_LOW] = 1;
} else {
gpio_write(5, 0, false); /* Turn off headlights */
lighting_control.light_state[LIGHT_HEADLIGHT_LOW] = 0;
}
}
/* Daytime running lights */
if (lighting_control.daytime_running_active) {
pwm_set_duty_cycle(2, 1, 5000); /* 50% intensity */
}
mutex_unlock(&lighting_control.mutex);
/* 100ms period */
kernel_delay(100);
}
}
@@ -0,0 +1,57 @@
/**
* @file brake_control.h
* @brief Brake control module interface
*/
#ifndef BRAKE_CONTROL_H
#define BRAKE_CONTROL_H
#include "kernel.h"
/* Brake Control Parameters */
#define BRAKE_CONTROL_PERIOD_MS 5
#define ABS_CONTROL_PERIOD_MS 1
#define WHEEL_SPEED_SENSOR_COUNT 4
#define MAX_BRAKE_PRESSURE 20000 /* kPa */
#define ABS_SLIP_THRESHOLD 0.2f
#define ABS_DECELERATION_THRESHOLD -10.0f /* m/s² */
/* Brake States */
typedef enum {
BRAKE_STATE_IDLE = 0,
BRAKE_STATE_NORMAL_BRAKING = 1,
BRAKE_STATE_ABS_ACTIVE = 2,
BRAKE_STATE_EMERGENCY = 3,
BRAKE_STATE_FAULT = 4
} BrakeState_t;
/* Wheel Speed Data */
typedef struct {
float wheel_speed[WHEEL_SPEED_SENSOR_COUNT]; /* km/h */
float wheel_acceleration[WHEEL_SPEED_SENSOR_COUNT]; /* m/s² */
uint16_t wheel_sensor_raw[WHEEL_SPEED_SENSOR_COUNT];
bool sensor_fault[WHEEL_SPEED_SENSOR_COUNT];
} WheelSpeedData_t;
/* Brake System Data */
typedef struct {
uint16_t brake_pedal_position;
uint16_t brake_pressure;
float vehicle_speed;
float vehicle_deceleration;
bool abs_active;
bool brake_light;
uint8_t abs_fault_code;
} BrakeSystemData_t;
/* Brake Control Functions */
KernelStatus_t brake_control_init(void);
KernelStatus_t brake_control_start(void);
KernelStatus_t brake_control_stop(void);
KernelStatus_t brake_control_get_data(BrakeSystemData_t* data);
KernelStatus_t brake_control_get_wheel_data(WheelSpeedData_t* data);
BrakeState_t brake_control_get_state(void);
void brake_control_task(void* parameters);
void abs_control_task(void* parameters);
#endif /* BRAKE_CONTROL_H */
@@ -0,0 +1,174 @@
/**
* @file abs_control.c
* @brief Anti-lock Braking System control
*/
#include "brake_control.h"
#include "gpio_driver.h"
#include <math.h>
/* ABS Control State */
typedef struct {
bool initialized;
bool abs_active;
float reference_speed;
float slip[WHEEL_SPEED_SENSOR_COUNT];
uint8_t control_phase; /* 0=increase, 1=hold, 2=decrease */
uint32_t phase_timer;
Mutex_t mutex;
} AbsControlState_t;
static AbsControlState_t abs_control;
/* Initialize ABS */
KernelStatus_t abs_control_init(void) {
if (abs_control.initialized) {
return KERNEL_ERROR;
}
abs_control.abs_active = false;
abs_control.reference_speed = 0;
abs_control.control_phase = 0;
abs_control.phase_timer = 0;
for (int i = 0; i < WHEEL_SPEED_SENSOR_COUNT; i++) {
abs_control.slip[i] = 0;
}
mutex_create(&abs_control.mutex, false);
abs_control.initialized = true;
return KERNEL_OK;
}
/* ABS Control Task */
void abs_control_task(void* parameters) {
(void)parameters;
while (1) {
/* Wait for next ABS control period */
kernel_delay(ABS_CONTROL_PERIOD_MS);
WheelSpeedData_t wheels;
brake_control_get_wheel_data(&wheels);
/* Check if ABS should be active */
if (brake_control_get_state() == BRAKE_STATE_NORMAL_BRAKING &&
check_abs_activation(&wheels)) {
abs_control.abs_active = true;
control_abs(&wheels);
} else {
abs_control.abs_active = false;
abs_control.control_phase = 0;
}
}
}
/* Check ABS Activation Conditions */
static bool check_abs_activation(const WheelSpeedData_t* wheels) {
/* Calculate reference speed (maximum wheel speed) */
float max_speed = 0;
for (int i = 0; i < WHEEL_SPEED_SENSOR_COUNT; i++) {
if (wheels->wheel_speed[i] > max_speed) {
max_speed = wheels->wheel_speed[i];
}
}
abs_control.reference_speed = max_speed;
/* Calculate slip for each wheel */
for (int i = 0; i < WHEEL_SPEED_SENSOR_COUNT; i++) {
if (max_speed > 5.0f) { /* Only calculate above 5 km/h */
abs_control.slip[i] = (max_speed - wheels->wheel_speed[i]) / max_speed;
} else {
abs_control.slip[i] = 0;
}
/* Check if slip exceeds threshold */
if (abs_control.slip[i] > ABS_SLIP_THRESHOLD) {
return true;
}
/* Check for excessive deceleration */
if (wheels->wheel_acceleration[i] < ABS_DECELERATION_THRESHOLD) {
return true;
}
}
return false;
}
/* ABS Control Algorithm */
static void control_abs(const WheelSpeedData_t* wheels) {
mutex_lock(&abs_control.mutex, 100);
/* Simple ABS control algorithm */
switch (abs_control.control_phase) {
case 0: /* Increase pressure */
if (abs_control.slip[0] > ABS_SLIP_THRESHOLD) {
abs_control.control_phase = 2; /* Switch to decrease */
abs_control.phase_timer = kernel_get_tick_count();
}
break;
case 1: /* Hold pressure */
if ((kernel_get_tick_count() - abs_control.phase_timer) > 10) {
abs_control.control_phase = 0; /* Switch to increase */
}
break;
case 2: /* Decrease pressure */
if (abs_control.slip[0] < ABS_SLIP_THRESHOLD * 0.5f) {
abs_control.control_phase = 1; /* Switch to hold */
abs_control.phase_timer = kernel_get_tick_count();
}
break;
}
mutex_unlock(&abs_control.mutex);
/* Control brake pressure valves */
control_pressure_valves();
}
/* Control Pressure Valves */
static void control_pressure_valves(void) {
switch (abs_control.control_phase) {
case 0: /* Increase pressure */
gpio_write(0, 0, false); /* Inlet valve open */
gpio_write(0, 1, false); /* Outlet valve closed */
break;
case 1: /* Hold pressure */
gpio_write(0, 0, true); /* Inlet valve closed */
gpio_write(0, 1, false); /* Outlet valve closed */
break;
case 2: /* Decrease pressure */
gpio_write(0, 0, true); /* Inlet valve closed */
gpio_write(0, 1, true); /* Outlet valve open */
break;
}
}
/* Get ABS Status */
bool abs_control_is_active(void) {
return abs_control.abs_active;
}
/* Get Slip Values */
KernelStatus_t abs_control_get_slip(float* slip, uint8_t* count) {
if (slip == NULL || count == NULL) {
return KERNEL_ERROR;
}
mutex_lock(&abs_control.mutex, 100);
for (int i = 0; i < WHEEL_SPEED_SENSOR_COUNT; i++) {
slip[i] = abs_control.slip[i];
}
*count = WHEEL_SPEED_SENSOR_COUNT;
mutex_unlock(&abs_control.mutex);
return KERNEL_OK;
}
+174
View File
@@ -0,0 +1,174 @@
/**
* @file brake_task.c
* @brief Main brake control task
*/
#include "brake_control.h"
#include "adc_driver.h"
#include "gpio_driver.h"
#include "pwm_driver.h"
#include "dtc_manager.h"
#include <string.h>
#include <math.h>
/* Brake Control State */
typedef struct {
BrakeState_t state;
BrakeSystemData_t data;
WheelSpeedData_t wheels;
uint16_t target_pressure;
uint16_t actual_pressure;
Mutex_t data_mutex;
bool initialized;
} BrakeControlState_t;
static BrakeControlState_t brake_control;
/* Initialize Brake Control */
KernelStatus_t brake_control_init(void) {
if (brake_control.initialized) {
return KERNEL_ERROR;
}
memset(&brake_control, 0, sizeof(BrakeControlState_t));
brake_control.state = BRAKE_STATE_IDLE;
mutex_create(&brake_control.data_mutex, false);
/* Initialize ADC for brake sensors */
adc_init(1, &(AdcConfig_t){
.resolution = ADC_RESOLUTION_12BIT,
.mode = ADC_MODE_CONTINUOUS,
.channel_count = 2,
.channels = {
{.channel = 0}, /* Brake pedal position */
{.channel = 1} /* Brake pressure */
}
});
/* Initialize PWM for brake pressure control */
pwm_init(1, &(PwmConfig_t){
.frequency_hz = 2000,
.channel_count = 1,
.channels = {
{.channel = 0, .duty_cycle = 0} /* Brake pressure valve */
}
});
brake_control.initialized = true;
return KERNEL_OK;
}
/* Brake Control Task */
void brake_control_task(void* parameters) {
(void)parameters;
while (1) {
/* Wait for next brake control period */
kernel_delay(BRAKE_CONTROL_PERIOD_MS);
/* Read brake sensors */
read_brake_sensors();
/* Process brake logic */
process_brake_logic();
/* Check for faults */
check_brake_faults();
}
}
/* Read Brake Sensors */
static void read_brake_sensors(void) {
uint16_t brake_pedal = 0;
uint16_t brake_pressure = 0;
adc_read_channel(1, 0, &brake_pedal, 10);
adc_read_channel(1, 1, &brake_pressure, 10);
mutex_lock(&brake_control.data_mutex, 100);
brake_control.data.brake_pedal_position = brake_pedal;
brake_control.data.brake_pressure = brake_pressure;
mutex_unlock(&brake_control.data_mutex);
}
/* Process Brake Logic */
static void process_brake_logic(void) {
mutex_lock(&brake_control.data_mutex, 100);
/* Check brake pedal position */
if (brake_control.data.brake_pedal_position > 100) {
brake_control.state = BRAKE_STATE_NORMAL_BRAKING;
brake_control.data.brake_light = true;
/* Calculate target pressure based on pedal position */
brake_control.target_pressure =
(brake_control.data.brake_pedal_position - 100) * 200;
/* Limit pressure */
if (brake_control.target_pressure > MAX_BRAKE_PRESSURE) {
brake_control.target_pressure = MAX_BRAKE_PRESSURE;
}
} else {
brake_control.state = BRAKE_STATE_IDLE;
brake_control.data.brake_light = false;
brake_control.target_pressure = 0;
}
/* Check for emergency braking */
if (brake_control.data.brake_pedal_position > 900 &&
brake_control.data.vehicle_deceleration < -8.0f) {
brake_control.state = BRAKE_STATE_EMERGENCY;
/* Maximum braking force */
brake_control.target_pressure = MAX_BRAKE_PRESSURE;
}
mutex_unlock(&brake_control.data_mutex);
/* Update brake pressure control */
update_brake_pressure();
}
/* Update Brake Pressure */
static void update_brake_pressure(void) {
/* Simple PID pressure control */
int32_t pressure_error = brake_control.target_pressure -
brake_control.actual_pressure;
/* Calculate valve duty cycle */
uint16_t valve_duty = 0;
if (pressure_error > 100) {
valve_duty = 10000; /* Full open */
} else if (pressure_error > 0) {
valve_duty = (uint16_t)((pressure_error * 10000) / 100);
} else {
valve_duty = 0; /* Closed */
}
/* Update PWM */
pwm_set_duty_cycle(1, 0, valve_duty);
/* Update actual pressure */
brake_control.actual_pressure += pressure_error / 10;
}
/* Check Brake Faults */
static void check_brake_faults(void) {
/* Check wheel speed sensors */
for (int i = 0; i < WHEEL_SPEED_SENSOR_COUNT; i++) {
if (brake_control.wheels.sensor_fault[i]) {
brake_control.state = BRAKE_STATE_FAULT;
brake_control.data.abs_fault_code = i + 1;
/* Add DTC */
DtcCode_t dtc_code = {
.high_byte = 0x01, /* Chassis */
.middle_byte = 0x00,
.low_byte = i + 1
};
dtc_manager_add_dtc(&dtc_code, 4); /* High severity */
}
}
}
+319
View File
@@ -0,0 +1,319 @@
/**
* @file display_task.c
* @brief Dashboard display task
*/
#include "kernel.h"
#include "can_driver.h"
#include "spi_driver.h"
#include "gpio_driver.h"
#include "engine_control.h"
#include "brake_control.h"
#include <string.h>
#include <stdio.h>
/* Display State */
typedef struct {
bool initialized;
uint16_t display_buffer[1024]; /* Display frame buffer */
uint8_t current_screen;
bool backlight_on;
uint8_t backlight_intensity;
Mutex_t mutex;
} DisplayState_t;
static DisplayState_t display;
/* Dashboard Data */
typedef struct {
uint16_t speed;
uint16_t rpm;
int16_t coolant_temp;
uint16_t fuel_level;
uint16_t odometer;
uint16_t trip_meter;
bool turn_left;
bool turn_right;
bool high_beam;
bool check_engine;
bool abs_warning;
bool oil_pressure_warning;
bool battery_warning;
} DashboardData_t;
static DashboardData_t dashboard_data;
/* Initialize Display */
KernelStatus_t display_init(void) {
if (display.initialized) {
return KERNEL_ERROR;
}
memset(&display, 0, sizeof(DisplayState_t));
display.current_screen = 0;
display.backlight_on = true;
display.backlight_intensity = 100;
mutex_create(&display.mutex, false);
/* Initialize SPI for display */
spi_init(0, &(SpiConfig_t){
.mode = SPI_MODE_0,
.clock_speed = SPI_CLOCK_8MHZ,
.data_order = SPI_DATA_ORDER_MSB_FIRST,
.data_size = 8,
.use_dma = true,
.enable_hardware_cs = false,
.cs_polarity = SPI_CS_ACTIVE_LOW,
.cs_port = 0,
.cs_pin = 15
});
display.initialized = true;
return KERNEL_OK;
}
/* Dashboard Display Task */
void display_task(void* parameters) {
(void)parameters;
while (1) {
/* Update dashboard data */
update_dashboard_data();
/* Render display */
render_display();
/* Update display */
update_display_hardware();
/* 50ms refresh rate */
kernel_delay(50);
}
}
/* Update Dashboard Data */
static void update_dashboard_data(void) {
/* Get data from CAN bus */
CanMessage_t message;
while (can_receive_message(&message, 0) == KERNEL_OK) {
switch (message.id.id) {
case 0x300: /* Engine data */
dashboard_data.rpm = (message.data[0] << 8) | message.data[1];
dashboard_data.coolant_temp = (int16_t)((message.data[2] << 8) |
message.data[3]);
dashboard_data.check_engine = message.data[4] & 0x01;
dashboard_data.oil_pressure_warning = message.data[4] & 0x02;
break;
case 0x301: /* Vehicle speed */
dashboard_data.speed = (message.data[0] << 8) | message.data[1];
dashboard_data.odometer = (message.data[2] << 16) |
(message.data[3] << 8) |
message.data[4];
break;
case 0x302: /* Fuel level */
dashboard_data.fuel_level = message.data[0];
dashboard_data.battery_warning = message.data[1] & 0x01;
break;
case 0x303: /* Turn signals */
dashboard_data.turn_left = message.data[0] & 0x01;
dashboard_data.turn_right = message.data[0] & 0x02;
dashboard_data.high_beam = message.data[0] & 0x04;
break;
case 0x304: /* ABS status */
dashboard_data.abs_warning = message.data[0] & 0x01;
break;
}
}
}
/* Render Display */
static void render_display(void) {
mutex_lock(&display.mutex, 100);
/* Clear display buffer */
memset(display.display_buffer, 0, sizeof(display.display_buffer));
/* Draw speedometer */
draw_speedometer();
/* Draw tachometer */
draw_tachometer();
/* Draw fuel gauge */
draw_fuel_gauge();
/* Draw temperature gauge */
draw_temperature_gauge();
/* Draw warning indicators */
draw_warning_indicators();
/* Draw odometer */
draw_odometer();
mutex_unlock(&display.mutex);
}
/* Draw Speedometer */
static void draw_speedometer(void) {
/* Draw circular gauge */
int center_x = 100;
int center_y = 100;
int radius = 80;
/* Draw arc */
for (int angle = 0; angle < 270; angle++) {
int x = center_x + (int)(radius * cos(angle * M_PI / 180));
int y = center_y + (int)(radius * sin(angle * M_PI / 180));
if (x >= 0 && x < 240 && y >= 0 && y < 320) {
display.display_buffer[y * 240 + x] = 0xFFFF; /* White */
}
}
/* Draw speed needle */
float speed_angle = (dashboard_data.speed * 270.0f) / 240.0f; /* 240 km/h max */
int needle_x = center_x + (int)((radius - 10) * cos(speed_angle * M_PI / 180));
int needle_y = center_y + (int)((radius - 10) * sin(speed_angle * M_PI / 180));
/* Draw line from center to needle tip */
draw_line(center_x, center_y, needle_x, needle_y, 0xF800); /* Red */
/* Draw speed text */
char speed_text[10];
snprintf(speed_text, sizeof(speed_text), "%d km/h", dashboard_data.speed);
draw_text(60, 200, speed_text, 0xFFFF);
}
/* Draw Tachometer */
static void draw_tachometer(void) {
int center_x = 300;
int center_y = 100;
int radius = 60;
/* Draw arc */
for (int angle = 0; angle < 270; angle++) {
int x = center_x + (int)(radius * cos(angle * M_PI / 180));
int y = center_y + (int)(radius * sin(angle * M_PI / 180));
if (x >= 0 && x < 480 && y >= 0 && y < 320) {
display.display_buffer[y * 480 + x] = 0xFFFF;
}
}
/* Draw RPM needle */
float rpm_angle = (dashboard_data.rpm * 270.0f) / 8000.0f; /* 8000 RPM max */
int needle_x = center_x + (int)((radius - 10) * cos(rpm_angle * M_PI / 180));
int needle_y = center_y + (int)((radius - 10) * sin(rpm_angle * M_PI / 180));
draw_line(center_x, center_y, needle_x, needle_y, 0x07E0); /* Green */
/* Draw RPM text */
char rpm_text[10];
snprintf(rpm_text, sizeof(rpm_text), "%d RPM", dashboard_data.rpm);
draw_text(260, 200, rpm_text, 0xFFFF);
}
/* Draw Warning Indicators */
static void draw_warning_indicators(void) {
/* Check engine light */
if (dashboard_data.check_engine) {
draw_text(20, 280, "CHECK ENGINE", 0xF800); /* Red */
}
/* ABS warning */
if (dashboard_data.abs_warning) {
draw_text(20, 300, "ABS", 0xF800);
}
/* Oil pressure warning */
if (dashboard_data.oil_pressure_warning) {
draw_text(100, 300, "OIL", 0xF800);
}
/* Battery warning */
if (dashboard_data.battery_warning) {
draw_text(150, 300, "BAT", 0xF800);
}
/* Turn signals */
if (dashboard_data.turn_left) {
draw_text(400, 280, "<--", 0x07E0); /* Green */
}
if (dashboard_data.turn_right) {
draw_text(440, 280, "-->", 0x07E0);
}
/* High beam */
if (dashboard_data.high_beam) {
draw_text(400, 300, "HIGH", 0x001F); /* Blue */
}
}
/* Draw Line */
static void draw_line(int x1, int y1, int x2, int y2, uint16_t color) {
int dx = abs(x2 - x1);
int dy = abs(y2 - y1);
int sx = (x1 < x2) ? 1 : -1;
int sy = (y1 < y2) ? 1 : -1;
int err = dx - dy;
while (1) {
if (x1 >= 0 && x1 < 480 && y1 >= 0 && y1 < 320) {
display.display_buffer[y1 * 480 + x1] = color;
}
if (x1 == x2 && y1 == y2) {
break;
}
int e2 = 2 * err;
if (e2 > -dy) {
err -= dy;
x1 += sx;
}
if (e2 < dx) {
err += dx;
y1 += sy;
}
}
}
/* Draw Text */
static void draw_text(int x, int y, const char* text, uint16_t color) {
/* Simple 8x8 font rendering */
while (*text) {
char c = *text++;
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
if (font_bitmap[(uint8_t)c][i] & (1 << j)) {
int px = x + j;
int py = y + i;
if (px >= 0 && px < 480 && py >= 0 && py < 320) {
display.display_buffer[py * 480 + px] = color;
}
}
}
}
x += 8;
}
}
/* Update Display Hardware */
static void update_display_hardware(void) {
mutex_lock(&display.mutex, 100);
/* Send frame buffer to display via SPI */
spi_write(0, (uint8_t*)display.display_buffer, sizeof(display.display_buffer), 100);
mutex_unlock(&display.mutex);
}
+200
View File
@@ -0,0 +1,200 @@
/**
* @file gauge_control.c
* @brief Analog gauge control for dashboard
*/
#include "kernel.h"
#include "pwm_driver.h"
#include "adc_driver.h"
#include "can_driver.h"
#include <string.h>
#include <math.h>
/* Gauge Control State */
typedef struct {
bool initialized;
uint16_t speed_gauge_position;
uint16_t rpm_gauge_position;
uint16_t fuel_gauge_position;
uint16_t temp_gauge_position;
uint16_t target_positions[4];
Mutex_t mutex;
} GaugeControlState_t;
static GaugeControlState_t gauge_control;
/* Initialize Gauge Control */
KernelStatus_t gauge_control_init(void) {
if (gauge_control.initialized) {
return KERNEL_ERROR;
}
memset(&gauge_control, 0, sizeof(GaugeControlState_t));
/* Initialize PWM for gauges */
pwm_init(3, &(PwmConfig_t){
.frequency_hz = 100, /* 100 Hz for smooth gauge movement */
.channel_count = 4,
.channels = {
{.channel = 0, .duty_cycle = 0}, /* Speedometer */
{.channel = 1, .duty_cycle = 0}, /* Tachometer */
{.channel = 2, .duty_cycle = 0}, /* Fuel gauge */
{.channel = 3, .duty_cycle = 0} /* Temperature gauge */
}
});
mutex_create(&gauge_control.mutex, false);
gauge_control.initialized = true;
return KERNEL_OK;
}
/* Gauge Control Task */
void gauge_control_task(void* parameters) {
(void)parameters;
while (1) {
/* Read CAN messages for gauge data */
CanMessage_t message;
while (can_receive_message(&message, 0) == KERNEL_OK) {
process_gauge_message(&message);
}
/* Smooth gauge movement */
smooth_gauge_movement();
/* 10ms update rate */
kernel_delay(10);
}
}
/* Process Gauge Message */
static void process_gauge_message(const CanMessage_t* message) {
mutex_lock(&gauge_control.mutex, 100);
switch (message->id.id) {
case 0x300: /* Engine data */
/* RPM: 0-8000 RPM maps to 0-10000 duty cycle */
gauge_control.target_positions[1] =
((message->data[0] << 8) | message->data[1]) * 10000 / 8000;
/* Temperature: -40 to 120°C maps to 0-10000 */
int16_t temp = (message->data[2] << 8) | message->data[3];
gauge_control.target_positions[3] =
(temp + 40) * 10000 / 160;
break;
case 0x301: /* Vehicle speed */
/* Speed: 0-240 km/h maps to 0-10000 */
gauge_control.target_positions[0] =
((message->data[0] << 8) | message->data[1]) * 10000 / 240;
break;
case 0x302: /* Fuel level */
/* Fuel: 0-100% maps to 0-10000 */
gauge_control.target_positions[2] = message->data[0] * 100;
break;
}
mutex_unlock(&gauge_control.mutex);
}
/* Smooth Gauge Movement */
static void smooth_gauge_movement(void) {
mutex_lock(&gauge_control.mutex, 100);
/* Smooth movement for each gauge */
for (int i = 0; i < 4; i++) {
uint16_t current = 0;
uint16_t target = gauge_control.target_positions[i];
/* Get current position */
switch (i) {
case 0:
current = gauge_control.speed_gauge_position;
break;
case 1:
current = gauge_control.rpm_gauge_position;
break;
case 2:
current = gauge_control.fuel_gauge_position;
break;
case 3:
current = gauge_control.temp_gauge_position;
break;
}
/* Calculate new position with smoothing */
int32_t delta = target - current;
uint16_t new_position = current + (delta / 10); /* 10% movement per update */
/* Update position */
switch (i) {
case 0:
gauge_control.speed_gauge_position = new_position;
break;
case 1:
gauge_control.rpm_gauge_position = new_position;
break;
case 2:
gauge_control.fuel_gauge_position = new_position;
break;
case 3:
gauge_control.temp_gauge_position = new_position;
break;
}
/* Update PWM output */
pwm_set_duty_cycle(3, i, new_position);
}
mutex_unlock(&gauge_control.mutex);
}
/* Calibrate Gauges */
KernelStatus_t gauge_calibrate(uint8_t gauge, uint16_t min_position,
uint16_t max_position) {
if (!gauge_control.initialized || gauge >= 4) {
return KERNEL_ERROR;
}
mutex_lock(&gauge_control.mutex, 100);
/* Set gauge to minimum position */
pwm_set_duty_cycle(3, gauge, min_position);
kernel_delay(1000); /* Wait 1 second */
/* Set gauge to maximum position */
pwm_set_duty_cycle(3, gauge, max_position);
kernel_delay(1000); /* Wait 1 second */
/* Return to zero */
pwm_set_duty_cycle(3, gauge, min_position);
mutex_unlock(&gauge_control.mutex);
return KERNEL_OK;
}
/* Self-Test Gauges */
KernelStatus_t gauge_self_test(void) {
if (!gauge_control.initialized) {
return KERNEL_ERROR;
}
/* Perform gauge sweep */
for (uint16_t position = 0; position <= 10000; position += 100) {
for (int i = 0; i < 4; i++) {
pwm_set_duty_cycle(3, i, position);
}
kernel_delay(10);
}
/* Return to zero */
for (int i = 0; i < 4; i++) {
pwm_set_duty_cycle(3, i, 0);
}
return KERNEL_OK;
}
@@ -0,0 +1,28 @@
/**
* @file engine_control.h
* @brief Engine control module interface
*/
#ifndef ENGINE_CONTROL_H
#define ENGINE_CONTROL_H
#include "kernel.h"
#include "engine_parameters.h"
/* Engine Control Functions */
KernelStatus_t engine_control_init(void);
KernelStatus_t engine_control_start(void);
KernelStatus_t engine_control_stop(void);
KernelStatus_t engine_control_get_sensor_data(EngineSensorData_t* data);
KernelStatus_t engine_control_get_actuator_data(EngineActuatorData_t* data);
KernelStatus_t engine_control_set_actuator_data(const EngineActuatorData_t* data);
EngineState_t engine_control_get_state(void);
KernelStatus_t engine_control_get_faults(EngineFaultCode_t* faults,
uint8_t* count);
KernelStatus_t engine_control_clear_faults(void);
void engine_control_task(void* parameters);
void fuel_injection_task(void* parameters);
void ignition_control_task(void* parameters);
void sensor_reading_task(void* parameters);
#endif /* ENGINE_CONTROL_H */
@@ -0,0 +1,177 @@
/**
* @file engine_parameters.h
* @brief Engine control parameters and calibration data
*/
#ifndef ENGINE_PARAMETERS_H
#define ENGINE_PARAMETERS_H
#include <stdint.h>
/* Engine Operating Parameters */
#define ENGINE_MAX_RPM 6500
#define ENGINE_IDLE_RPM 800
#define ENGINE_REDLINE_RPM 6000
#define ENGINE_MAX_TORQUE_RPM 4000
#define ENGINE_MAX_POWER_RPM 5500
/* Temperature Limits */
#define ENGINE_MAX_COOLANT_TEMP 120 /* °C */
#define ENGINE_MIN_COOLANT_TEMP -40 /* °C */
#define ENGINE_OPTIMAL_TEMP 90 /* °C */
#define ENGINE_MAX_OIL_TEMP 150 /* °C */
#define ENGINE_MAX_INTAKE_TEMP 80 /* °C */
/* Pressure Limits */
#define ENGINE_MAX_MANIFOLD_PRESSURE 250 /* kPa */
#define ENGINE_MIN_OIL_PRESSURE 100 /* kPa */
#define ENGINE_MAX_FUEL_PRESSURE 500 /* kPa */
/* Fuel System Parameters */
#define FUEL_STOICHIOMETRIC_RATIO 14.7f
#define FUEL_MAX_INJECTION_TIME 20.0f /* ms */
#define FUEL_MIN_INJECTION_TIME 0.5f /* ms */
#define FUEL_INJECTOR_FLOW_RATE 250.0f /* cc/min */
/* Ignition Parameters */
#define IGNITION_MAX_ADVANCE 45.0f /* degrees BTDC */
#define IGNITION_MIN_ADVANCE -10.0f /* degrees ATDC */
#define IGNITION_BASE_ADVANCE 10.0f /* degrees BTDC */
#define IGNITION_DWELL_TIME 3.5f /* ms */
/* Control Loop Parameters */
#define ENGINE_CONTROL_PERIOD_MS 1 /* 1ms control loop */
#define FUEL_CONTROL_PERIOD_MS 10 /* 10ms fuel update */
#define IGNITION_CONTROL_PERIOD_MS 5 /* 5ms ignition update */
#define SENSOR_READ_PERIOD_MS 2 /* 2ms sensor reading */
/* PID Controller Gains */
typedef struct {
float kp;
float ki;
float kd;
float integral_limit;
float output_limit;
} PidGains_t;
/* Fuel Control PID */
static const PidGains_t fuel_pid_gains = {
.kp = 0.5f,
.ki = 0.1f,
.kd = 0.05f,
.integral_limit = 100.0f,
.output_limit = 100.0f
};
/* Idle Control PID */
static const PidGains_t idle_pid_gains = {
.kp = 0.8f,
.ki = 0.2f,
.kd = 0.1f,
.integral_limit = 50.0f,
.output_limit = 100.0f
};
/* Boost Control PID */
static const PidGains_t boost_pid_gains = {
.kp = 0.3f,
.ki = 0.05f,
.kd = 0.02f,
.integral_limit = 200.0f,
.output_limit = 250.0f
};
/* Engine State Enumeration */
typedef enum {
ENGINE_STATE_OFF = 0,
ENGINE_STATE_CRANKING = 1,
ENGINE_STATE_RUNNING = 2,
ENGINE_STATE_IDLE = 3,
ENGINE_STATE_ACCELERATING = 4,
ENGINE_STATE_DECELERATING = 5,
ENGINE_STATE_FAULT = 6,
ENGINE_STATE_LIMP_HOME = 7
} EngineState_t;
/* Engine Sensor Data */
typedef struct {
uint16_t rpm;
uint16_t vehicle_speed;
int16_t coolant_temp;
int16_t intake_air_temp;
int16_t oil_temp;
uint16_t manifold_pressure;
uint16_t oil_pressure;
uint16_t fuel_pressure;
uint16_t throttle_position;
uint16_t accelerator_pedal;
float mass_air_flow;
float lambda;
float battery_voltage;
} EngineSensorData_t;
/* Engine Actuator Data */
typedef struct {
uint16_t injector_pulse_width;
float ignition_advance;
uint16_t idle_air_control;
uint16_t boost_control;
uint16_t fuel_pump_duty;
uint16_t cooling_fan_duty;
} EngineActuatorData_t;
/* Engine Fault Codes */
typedef enum {
ENGINE_FAULT_NONE = 0,
ENGINE_FAULT_COOLANT_TEMP_SENSOR = 1,
ENGINE_FAULT_INTAKE_TEMP_SENSOR = 2,
ENGINE_FAULT_MANIFOLD_PRESSURE_SENSOR = 3,
ENGINE_FAULT_MAF_SENSOR = 4,
ENGINE_FAULT_OXYGEN_SENSOR = 5,
ENGINE_FAULT_KNOCK_SENSOR = 6,
ENGINE_FAULT_CRANKSHAFT_SENSOR = 7,
ENGINE_FAULT_CAMSHAFT_SENSOR = 8,
ENGINE_FAULT_INJECTOR_1 = 9,
ENGINE_FAULT_INJECTOR_2 = 10,
ENGINE_FAULT_INJECTOR_3 = 11,
ENGINE_FAULT_INJECTOR_4 = 12,
ENGINE_FAULT_IGNITION_COIL = 13,
ENGINE_FAULT_FUEL_PUMP = 14,
ENGINE_FAULT_OVERHEAT = 15,
ENGINE_FAULT_LOW_OIL_PRESSURE = 16
} EngineFaultCode_t;
/* Lookup Tables */
typedef struct {
const uint16_t* rpm_points;
const uint16_t* load_points;
const uint16_t* values;
uint8_t rpm_count;
uint8_t load_count;
} LookupTable2D_t;
/* Fuel Map (injection time in microseconds) */
static const uint16_t fuel_map_rpm[] = {0, 500, 1000, 2000, 3000, 4000, 5000, 6000};
static const uint16_t fuel_map_load[] = {0, 20, 40, 60, 80, 100};
static const uint16_t fuel_map_values[][8] = {
{0, 1000, 800, 700, 650, 600, 550, 500},
{1000, 1500, 1300, 1200, 1100, 1000, 950, 900},
{2000, 2500, 2200, 2000, 1800, 1700, 1600, 1500},
{3000, 3500, 3200, 3000, 2800, 2600, 2400, 2200},
{4000, 4500, 4200, 4000, 3800, 3600, 3400, 3200},
{5000, 5500, 5200, 5000, 4800, 4600, 4400, 4200}
};
/* Ignition Advance Map (degrees BTDC) */
static const uint16_t ignition_map_rpm[] = {0, 500, 1000, 2000, 3000, 4000, 5000, 6000};
static const uint16_t ignition_map_load[] = {0, 20, 40, 60, 80, 100};
static const int16_t ignition_map_values[][8] = {
{10, 12, 15, 18, 20, 22, 25, 28},
{10, 12, 15, 18, 20, 22, 25, 28},
{8, 10, 13, 16, 18, 20, 23, 26},
{6, 8, 11, 14, 16, 18, 21, 24},
{4, 6, 9, 12, 14, 16, 19, 22},
{2, 4, 7, 10, 12, 14, 17, 20}
};
#endif /* ENGINE_PARAMETERS_H */
@@ -0,0 +1,366 @@
/**
* @file engine_control_task.c
* @brief Main engine control task
*/
#include "engine_control.h"
#include "fuel_injection.h"
#include "ignition_control.h"
#include "adc_driver.h"
#include "gpio_driver.h"
#include "pwm_driver.h"
#include "dtc_manager.h"
#include <string.h>
#include <math.h>
/* Engine Control State */
typedef struct {
EngineState_t state;
EngineSensorData_t sensors;
EngineActuatorData_t actuators;
EngineFaultCode_t faults[20];
uint8_t fault_count;
uint32_t engine_run_time;
Mutex_t data_mutex;
bool initialized;
} EngineControlState_t;
static EngineControlState_t engine_control;
/* PID Controller Structure */
typedef struct {
PidGains_t gains;
float integral;
float previous_error;
float output;
} PidController_t;
static PidController_t fuel_pid;
static PidController_t idle_pid;
static PidController_t boost_pid;
/* Initialize Engine Control */
KernelStatus_t engine_control_init(void) {
if (engine_control.initialized) {
return KERNEL_ERROR;
}
/* Initialize state */
memset(&engine_control, 0, sizeof(EngineControlState_t));
engine_control.state = ENGINE_STATE_OFF;
engine_control.fault_count = 0;
/* Initialize PID controllers */
fuel_pid.gains = fuel_pid_gains;
fuel_pid.integral = 0;
fuel_pid.previous_error = 0;
fuel_pid.output = 0;
idle_pid.gains = idle_pid_gains;
idle_pid.integral = 0;
idle_pid.previous_error = 0;
idle_pid.output = 0;
boost_pid.gains = boost_pid_gains;
boost_pid.integral = 0;
boost_pid.previous_error = 0;
boost_pid.output = 0;
/* Create mutex */
mutex_create(&engine_control.data_mutex, false);
/* Initialize sensors */
adc_init(0, &(AdcConfig_t){
.resolution = ADC_RESOLUTION_12BIT,
.mode = ADC_MODE_SCAN,
.trigger_source = ADC_TRIGGER_TIMER,
.reference = ADC_REFERENCE_VDD,
.channel_count = 8,
.channels = {
{.channel = 0, .sampling_time = ADC_SAMPLING_28_5_CYCLES}, /* Coolant temp */
{.channel = 1, .sampling_time = ADC_SAMPLING_28_5_CYCLES}, /* Intake temp */
{.channel = 2, .sampling_time = ADC_SAMPLING_28_5_CYCLES}, /* Manifold pressure */
{.channel = 3, .sampling_time = ADC_SAMPLING_28_5_CYCLES}, /* Throttle position */
{.channel = 4, .sampling_time = ADC_SAMPLING_28_5_CYCLES}, /* Accelerator pedal */
{.channel = 5, .sampling_time = ADC_SAMPLING_28_5_CYCLES}, /* Oil pressure */
{.channel = 6, .sampling_time = ADC_SAMPLING_28_5_CYCLES}, /* Fuel pressure */
{.channel = 7, .sampling_time = ADC_SAMPLING_28_5_CYCLES} /* Battery voltage */
}
});
/* Initialize actuators */
pwm_init(0, &(PwmConfig_t){
.frequency_hz = 1000,
.alignment = PWM_ALIGNMENT_EDGE,
.channel_count = 4,
.channels = {
{.channel = 0, .duty_cycle = 0}, /* Injector 1 */
{.channel = 1, .duty_cycle = 0}, /* Injector 2 */
{.channel = 2, .duty_cycle = 0}, /* Idle air control */
{.channel = 3, .duty_cycle = 0} /* Boost control */
}
});
engine_control.initialized = true;
return KERNEL_OK;
}
/* Start Engine */
KernelStatus_t engine_control_start(void) {
if (!engine_control.initialized) {
return KERNEL_ERROR;
}
engine_control.state = ENGINE_STATE_CRANKING;
/* Start PWM outputs */
pwm_start(0);
/* Start ADC conversions */
adc_start_conversion(0);
return KERNEL_OK;
}
/* Stop Engine */
KernelStatus_t engine_control_stop(void) {
if (!engine_control.initialized) {
return KERNEL_ERROR;
}
/* Stop actuators */
pwm_stop(0);
/* Stop ADC */
adc_stop_conversion(0);
engine_control.state = ENGINE_STATE_OFF;
return KERNEL_OK;
}
/* Main Engine Control Task */
void engine_control_task(void* parameters) {
(void)parameters;
TickType_t last_wake_time = kernel_get_tick_count();
while (1) {
/* Wait for next control period */
kernel_delay(ENGINE_CONTROL_PERIOD_MS);
switch (engine_control.state) {
case ENGINE_STATE_CRANKING:
/* Check RPM for engine start */
if (engine_control.sensors.rpm > 400) {
engine_control.state = ENGINE_STATE_RUNNING;
}
break;
case ENGINE_STATE_RUNNING:
/* Check for idle condition */
if (engine_control.sensors.rpm < ENGINE_IDLE_RPM + 50 &&
engine_control.sensors.accelerator_pedal < 5) {
engine_control.state = ENGINE_STATE_IDLE;
}
/* Check for acceleration */
if (engine_control.sensors.accelerator_pedal > 80) {
engine_control.state = ENGINE_STATE_ACCELERATING;
}
break;
case ENGINE_STATE_IDLE:
/* Idle speed control */
idle_pid_control();
/* Check if leaving idle */
if (engine_control.sensors.accelerator_pedal > 5) {
engine_control.state = ENGINE_STATE_RUNNING;
}
break;
case ENGINE_STATE_ACCELERATING:
/* Acceleration enrichment */
engine_control.actuators.injector_pulse_width *= 1.2f;
/* Check if still accelerating */
if (engine_control.sensors.accelerator_pedal < 80) {
engine_control.state = ENGINE_STATE_RUNNING;
}
break;
case ENGINE_STATE_DECELERATING:
/* Deceleration fuel cutoff */
if (engine_control.sensors.rpm > 1500 &&
engine_control.sensors.accelerator_pedal < 2) {
engine_control.actuators.injector_pulse_width = 0;
}
/* Check if still decelerating */
if (engine_control.sensors.accelerator_pedal > 2) {
engine_control.state = ENGINE_STATE_RUNNING;
}
break;
case ENGINE_STATE_FAULT:
/* Handle faults */
handle_engine_faults();
break;
case ENGINE_STATE_LIMP_HOME:
/* Limp home mode */
engine_control.actuators.injector_pulse_width =
fuel_map_values[0][3]; /* Fixed fuel */
engine_control.actuators.ignition_advance =
ignition_map_values[0][3]; /* Fixed timing */
break;
default:
break;
}
/* Update engine run time */
engine_control.engine_run_time += ENGINE_CONTROL_PERIOD_MS;
/* Check for faults */
check_engine_faults();
last_wake_time = kernel_get_tick_count();
}
}
/* Idle Speed Control */
static void idle_pid_control(void) {
int32_t rpm_error = ENGINE_IDLE_RPM - engine_control.sensors.rpm;
/* PID calculation */
idle_pid.integral += rpm_error * (IDLE_CONTROL_PERIOD_MS / 1000.0f);
/* Limit integral */
if (idle_pid.integral > idle_pid.gains.integral_limit) {
idle_pid.integral = idle_pid.gains.integral_limit;
} else if (idle_pid.integral < -idle_pid.gains.integral_limit) {
idle_pid.integral = -idle_pid.gains.integral_limit;
}
float derivative = (rpm_error - idle_pid.previous_error) /
(IDLE_CONTROL_PERIOD_MS / 1000.0f);
idle_pid.output = idle_pid.gains.kp * rpm_error +
idle_pid.gains.ki * idle_pid.integral +
idle_pid.gains.kd * derivative;
/* Limit output */
if (idle_pid.output > idle_pid.gains.output_limit) {
idle_pid.output = idle_pid.gains.output_limit;
} else if (idle_pid.output < 0) {
idle_pid.output = 0;
}
/* Update actuator */
engine_control.actuators.idle_air_control = (uint16_t)idle_pid.output;
idle_pid.previous_error = rpm_error;
}
/* Check Engine Faults */
static void check_engine_faults(void) {
/* Check coolant temperature */
if (engine_control.sensors.coolant_temp > ENGINE_MAX_COOLANT_TEMP) {
add_engine_fault(ENGINE_FAULT_OVERHEAT);
engine_control.state = ENGINE_STATE_FAULT;
}
/* Check oil pressure */
if (engine_control.sensors.oil_pressure < ENGINE_MIN_OIL_PRESSURE &&
engine_control.sensors.rpm > 1000) {
add_engine_fault(ENGINE_FAULT_LOW_OIL_PRESSURE);
engine_control.state = ENGINE_STATE_FAULT;
}
/* Check battery voltage */
if (engine_control.sensors.battery_voltage < 9.0f ||
engine_control.sensors.battery_voltage > 16.0f) {
add_engine_fault(ENGINE_FAULT_NONE); // Just log the condition
}
}
/* Add Engine Fault */
static void add_engine_fault(EngineFaultCode_t fault) {
if (engine_control.fault_count < 20) {
/* Check if fault already exists */
for (uint8_t i = 0; i < engine_control.fault_count; i++) {
if (engine_control.faults[i] == fault) {
return;
}
}
engine_control.faults[engine_control.fault_count] = fault;
engine_control.fault_count++;
/* Add DTC */
DtcCode_t dtc_code = {
.high_byte = 0x00, /* Powertrain */
.middle_byte = 0x00,
.low_byte = fault
};
dtc_manager_add_dtc(&dtc_code, 3); /* Medium severity */
}
}
/* Handle Engine Faults */
static void handle_engine_faults(void) {
for (uint8_t i = 0; i < engine_control.fault_count; i++) {
switch (engine_control.faults[i]) {
case ENGINE_FAULT_OVERHEAT:
/* Enable cooling fan */
engine_control.actuators.cooling_fan_duty = 100;
/* Reduce power */
engine_control.actuators.injector_pulse_width *= 0.5f;
break;
case ENGINE_FAULT_LOW_OIL_PRESSURE:
/* Immediate engine shutdown */
engine_control_stop();
break;
default:
/* Enter limp home mode */
engine_control.state = ENGINE_STATE_LIMP_HOME;
break;
}
}
}
/* Get Engine State */
EngineState_t engine_control_get_state(void) {
return engine_control.state;
}
/* Get Sensor Data */
KernelStatus_t engine_control_get_sensor_data(EngineSensorData_t* data) {
if (data == NULL) {
return KERNEL_ERROR;
}
mutex_lock(&engine_control.data_mutex, 100);
memcpy(data, &engine_control.sensors, sizeof(EngineSensorData_t));
mutex_unlock(&engine_control.data_mutex);
return KERNEL_OK;
}
/* Get Actuator Data */
KernelStatus_t engine_control_get_actuator_data(EngineActuatorData_t* data) {
if (data == NULL) {
return KERNEL_ERROR;
}
mutex_lock(&engine_control.data_mutex, 100);
memcpy(data, &engine_control.actuators, sizeof(EngineActuatorData_t));
mutex_unlock(&engine_control.data_mutex);
return KERNEL_OK;
}
@@ -0,0 +1,164 @@
/**
* @file fuel_injection.c
* @brief Fuel injection control
*/
#include "engine_control.h"
#include "fuel_injection.h"
#include "adc_driver.h"
#include "pwm_driver.h"
#include <math.h>
/* Fuel Injection State */
typedef struct {
bool initialized;
float fuel_pressure;
float injection_time;
uint16_t injector_duty;
uint8_t injection_mode; /* 0=sequential, 1=batch, 2=simultaneous */
Mutex_t mutex;
} FuelInjectionState_t;
static FuelInjectionState_t fuel_injection;
/* Initialize Fuel Injection */
KernelStatus_t fuel_injection_init(void) {
if (fuel_injection.initialized) {
return KERNEL_ERROR;
}
fuel_injection.fuel_pressure = 0;
fuel_injection.injection_time = 0;
fuel_injection.injector_duty = 0;
fuel_injection.injection_mode = 0; /* Sequential */
mutex_create(&fuel_injection.mutex, false);
fuel_injection.initialized = true;
return KERNEL_OK;
}
/* Fuel Injection Control Task */
void fuel_injection_task(void* parameters) {
(void)parameters;
while (1) {
/* Wait for next fuel update period */
kernel_delay(FUEL_CONTROL_PERIOD_MS);
EngineSensorData_t sensors;
engine_control_get_sensor_data(&sensors);
/* Calculate required fuel */
float required_fuel = calculate_fuel_requirement(&sensors);
/* Apply corrections */
required_fuel = apply_fuel_corrections(required_fuel, &sensors);
/* Convert to injector pulse width */
uint16_t pulse_width = (uint16_t)(required_fuel * 1000); /* Convert to microseconds */
/* Limit pulse width */
if (pulse_width > (uint16_t)(FUEL_MAX_INJECTION_TIME * 1000)) {
pulse_width = (uint16_t)(FUEL_MAX_INJECTION_TIME * 1000);
}
/* Update injector PWM */
mutex_lock(&fuel_injection.mutex, 100);
fuel_injection.injection_time = required_fuel;
fuel_injection.injector_duty = calculate_injector_duty(pulse_width,
sensors.rpm);
mutex_unlock(&fuel_injection.mutex);
/* Update PWM output */
pwm_set_duty_cycle(0, 0, fuel_injection.injector_duty); /* Injector 1 */
pwm_set_duty_cycle(0, 1, fuel_injection.injector_duty); /* Injector 2 */
}
}
/* Calculate Fuel Requirement */
static float calculate_fuel_requirement(const EngineSensorData_t* sensors) {
/* Basic fuel calculation using speed-density method */
float air_mass = 0;
if (sensors->mass_air_flow > 0) {
/* Use MAF sensor if available */
air_mass = sensors->mass_air_flow / (sensors->rpm / 2);
} else {
/* Speed-density calculation */
float air_density = 1.225f; /* kg/m³ at sea level */
float engine_displacement = 2.0f; /* 2.0L engine */
float volumetric_efficiency = 0.85f;
air_mass = air_density * engine_displacement *
volumetric_efficiency * sensors->manifold_pressure / 101.3f;
}
/* Calculate fuel mass for stoichiometric mixture */
float fuel_mass = air_mass / FUEL_STOICHIOMETRIC_RATIO;
/* Convert to injection time */
float injection_time = (fuel_mass * 1000000) / FUEL_INJECTOR_FLOW_RATE;
return injection_time;
}
/* Apply Fuel Corrections */
static float apply_fuel_corrections(float base_fuel, const EngineSensorData_t* sensors) {
float corrected_fuel = base_fuel;
/* Lambda correction */
if (sensors->lambda > 0) {
float lambda_error = 1.0f - sensors->lambda;
corrected_fuel *= (1.0f + lambda_error * 0.5f);
}
/* Coolant temperature correction */
if (sensors->coolant_temp < 70) {
float enrichment = (70 - sensors->coolant_temp) * 0.01f;
corrected_fuel *= (1.0f + enrichment);
}
/* Acceleration enrichment */
if (sensors->accelerator_pedal > 80) {
corrected_fuel *= 1.2f;
}
/* Battery voltage correction */
if (sensors->battery_voltage < 12.0f) {
corrected_fuel *= (12.0f / sensors->battery_voltage);
}
return corrected_fuel;
}
/* Calculate Injector Duty Cycle */
static uint16_t calculate_injector_duty(uint16_t pulse_width_us, uint16_t rpm) {
/* Calculate period in microseconds */
uint32_t period_us = (60000000UL) / rpm; /* 2 revolutions per cycle */
/* Calculate duty cycle */
uint32_t duty = (pulse_width_us * PWM_MAX_DUTY_CYCLE) / period_us;
if (duty > PWM_MAX_DUTY_CYCLE) {
duty = PWM_MAX_DUTY_CYCLE;
}
return (uint16_t)duty;
}
/* Get Fuel Injection Data */
KernelStatus_t fuel_injection_get_data(float* pressure, float* injection_time,
uint16_t* duty_cycle) {
if (pressure == NULL || injection_time == NULL || duty_cycle == NULL) {
return KERNEL_ERROR;
}
mutex_lock(&fuel_injection.mutex, 100);
*pressure = fuel_injection.fuel_pressure;
*injection_time = fuel_injection.injection_time;
*duty_cycle = fuel_injection.injector_duty;
mutex_unlock(&fuel_injection.mutex);
return KERNEL_OK;
}
@@ -0,0 +1,134 @@
/**
* @file ignition_control.c
* @brief Ignition timing control
*/
#include "engine_control.h"
#include "ignition_control.h"
#include "gpio_driver.h"
#include <math.h>
/* Ignition Control State */
typedef struct {
bool initialized;
float ignition_advance;
float dwell_time;
uint8_t ignition_mode;
bool knock_detected;
uint32_t knock_count;
Mutex_t mutex;
} IgnitionControlState_t;
static IgnitionControlState_t ignition_control;
/* Initialize Ignition Control */
KernelStatus_t ignition_control_init(void) {
if (ignition_control.initialized) {
return KERNEL_ERROR;
}
ignition_control.ignition_advance = IGNITION_BASE_ADVANCE;
ignition_control.dwell_time = IGNITION_DWELL_TIME;
ignition_control.ignition_mode = 0;
ignition_control.knock_detected = false;
ignition_control.knock_count = 0;
mutex_create(&ignition_control.mutex, false);
ignition_control.initialized = true;
return KERNEL_OK;
}
/* Ignition Control Task */
void ignition_control_task(void* parameters) {
(void)parameters;
while (1) {
/* Wait for next ignition update period */
kernel_delay(IGNITION_CONTROL_PERIOD_MS);
EngineSensorData_t sensors;
engine_control_get_sensor_data(&sensors);
/* Calculate ignition advance */
float advance = calculate_ignition_advance(&sensors);
/* Apply knock correction */
if (ignition_control.knock_detected) {
advance -= 5.0f; /* Retard timing */
ignition_control.knock_detected = false;
ignition_control.knock_count++;
}
/* Limit advance */
if (advance > IGNITION_MAX_ADVANCE) {
advance = IGNITION_MAX_ADVANCE;
} else if (advance < IGNITION_MIN_ADVANCE) {
advance = IGNITION_MIN_ADVANCE;
}
/* Update ignition control */
mutex_lock(&ignition_control.mutex, 100);
ignition_control.ignition_advance = advance;
mutex_unlock(&ignition_control.mutex);
/* Update actuator */
EngineActuatorData_t actuators;
engine_control_get_actuator_data(&actuators);
actuators.ignition_advance = advance;
engine_control_set_actuator_data(&actuators);
}
}
/* Calculate Ignition Advance */
static float calculate_ignition_advance(const EngineSensorData_t* sensors) {
float advance = IGNITION_BASE_ADVANCE;
/* RPM correction */
if (sensors->rpm < 1000) {
advance += 5.0f; /* More advance at low RPM */
} else if (sensors->rpm > 5000) {
advance -= 3.0f; /* Less advance at high RPM */
}
/* Load correction */
if (sensors->manifold_pressure < 40) {
advance += 2.0f; /* More advance at light load */
} else if (sensors->manifold_pressure > 80) {
advance -= 4.0f; /* Less advance at high load */
}
/* Temperature correction */
if (sensors->coolant_temp < 0) {
advance += 3.0f; /* More advance when cold */
} else if (sensors->coolant_temp > 100) {
advance -= 5.0f; /* Less advance when hot */
}
return advance;
}
/* Detect Knock */
void ignition_control_detect_knock(void) {
/* Read knock sensor */
uint16_t knock_signal = adc_read_single(7);
/* Check for knock */
if (knock_signal > 200) {
ignition_control.knock_detected = true;
}
}
/* Get Ignition Data */
KernelStatus_t ignition_control_get_data(float* advance, float* dwell) {
if (advance == NULL || dwell == NULL) {
return KERNEL_ERROR;
}
mutex_lock(&ignition_control.mutex, 100);
*advance = ignition_control.ignition_advance;
*dwell = ignition_control.dwell_time;
mutex_unlock(&ignition_control.mutex);
return KERNEL_OK;
}
+67
View File
@@ -0,0 +1,67 @@
/**
* @file board.h
* @brief Custom ECU board definitions
*/
#ifndef BOARD_H
#define BOARD_H
#include <stdint.h>
#include <stdbool.h>
/* ============================================================================
* Board Identification
* ============================================================================ */
#define BOARD_NAME "CustomECU-v1.0"
#define BOARD_MANUFACTURER "Automotive RTOS Team"
#define BOARD_VERSION "1.0"
#define BOARD_MCU "Custom"
/* ============================================================================
* Clock Configuration
* ============================================================================ */
#define SYSTEM_CLOCK 100000000U /* 100 MHz */
#define PERIPHERAL_CLOCK 50000000U /* 50 MHz */
#define TIMER_CLOCK 10000000U /* 10 MHz */
/* ============================================================================
* LED Definitions
* ============================================================================ */
#define LED_COUNT 4
#define LED_STATUS 0
#define LED_ERROR 1
#define LED_CAN_TX 2
#define LED_CAN_RX 3
/* ============================================================================
* Communication Interfaces
* ============================================================================ */
#define CAN_INTERFACE_COUNT 2
#define UART_INTERFACE_COUNT 2
#define SPI_INTERFACE_COUNT 1
#define I2C_INTERFACE_COUNT 1
/* ============================================================================
* Board Functions
* ============================================================================ */
void board_init(void);
void board_clock_init(void);
void board_gpio_init(void);
void board_uart_init(void);
void board_can_init(void);
void board_spi_init(void);
void board_i2c_init(void);
void board_adc_init(void);
void board_pwm_init(void);
void board_watchdog_init(void);
void board_watchdog_service(void);
void board_led_on(uint8_t led);
void board_led_off(uint8_t led);
void board_led_toggle(uint8_t led);
bool board_button_read(uint8_t button);
void board_delay_ms(uint32_t ms);
void board_delay_us(uint32_t us);
float board_get_temperature(void);
float board_get_voltage(void);
#endif /* BOARD_H */
+292
View File
@@ -0,0 +1,292 @@
/**
* @file board_init.c
* @brief Custom ECU board initialization
*/
#include "board.h"
#include "kernel.h"
#include "gpio_driver.h"
#include "uart_driver.h"
#include "can_driver.h"
#include "spi_driver.h"
#include "i2c_driver.h"
#include "adc_driver.h"
#include "pwm_driver.h"
#include <string.h>
static bool board_initialized = false;
/* Board-specific configuration */
typedef struct {
uint32_t can_baudrate;
uint32_t uart_baudrate;
uint8_t node_id;
bool can_fd_enabled;
} BoardConfig_t;
static const BoardConfig_t board_config = {
.can_baudrate = 500000,
.uart_baudrate = 115200,
.node_id = 0x01,
.can_fd_enabled = true
};
/* ============================================================================
* Board Initialization
* ============================================================================ */
void board_init(void) {
if (board_initialized) {
return;
}
/* Initialize clock */
board_clock_init();
/* Initialize GPIO */
board_gpio_init();
/* Initialize UART */
board_uart_init();
/* Initialize CAN */
board_can_init();
/* Initialize SPI */
board_spi_init();
/* Initialize I2C */
board_i2c_init();
/* Initialize ADC */
board_adc_init();
/* Initialize PWM */
board_pwm_init();
/* Initialize watchdog */
board_watchdog_init();
board_initialized = true;
}
/* ============================================================================
* Clock Initialization
* ============================================================================ */
void board_clock_init(void) {
/* Custom clock initialization */
/* This would be implemented for specific hardware */
}
/* ============================================================================
* GPIO Initialization
* ============================================================================ */
void board_gpio_init(void) {
/* Configure status LEDs */
GpioPinConfig_t led_config = {
.mode = GPIO_MODE_OUTPUT,
.output_type = GPIO_OUTPUT_PUSH_PULL,
.pull = GPIO_PULL_NONE,
.speed = GPIO_SPEED_HIGH
};
/* Configure each LED */
for (int i = 0; i < LED_COUNT; i++) {
led_config.port = 0;
led_config.pin = i;
gpio_init(&led_config);
}
/* Turn off all LEDs */
for (int i = 0; i < LED_COUNT; i++) {
board_led_off(i);
}
}
/* ============================================================================
* UART Initialization
* ============================================================================ */
void board_uart_init(void) {
/* Configure debug UART */
UartConfig_t uart_config = {
.baudrate = board_config.uart_baudrate,
.data_bits = UART_DATA_BITS_8,
.stop_bits = UART_STOP_BITS_1,
.parity = UART_PARITY_NONE,
.flow_control = UART_FLOW_CONTROL_NONE,
.enable_rx = true,
.enable_tx = true,
.use_dma = false
};
uart_init(0, &uart_config);
}
/* ============================================================================
* CAN Initialization
* ============================================================================ */
void board_can_init(void) {
/* Configure main CAN interface */
CanConfig_t can_config = {
.nominal_baudrate = board_config.can_baudrate,
.data_baudrate = board_config.can_baudrate,
.frame_type = CAN_FRAME_CLASSIC,
.enable_fd = board_config.can_fd_enabled,
.enable_automatic_retransmission = true,
.filter_count = 0
};
can_init(0, &can_config);
}
/* ============================================================================
* SPI Initialization
* ============================================================================ */
void board_spi_init(void) {
/* Configure SPI for external devices */
SpiConfig_t spi_config = {
.mode = SPI_MODE_0,
.clock_speed = SPI_CLOCK_8MHZ,
.data_order = SPI_DATA_ORDER_MSB_FIRST,
.data_size = 8,
.use_dma = true,
.enable_hardware_cs = false,
.cs_polarity = SPI_CS_ACTIVE_LOW,
.cs_port = 0,
.cs_pin = 10
};
spi_init(0, &spi_config);
}
/* ============================================================================
* I2C Initialization
* ============================================================================ */
void board_i2c_init(void) {
/* Configure I2C for sensors */
I2cConfig_t i2c_config = {
.speed = I2C_SPEED_FAST,
.addressing_mode = I2C_ADDRESSING_7BIT,
.own_address = 0x50,
.enable_general_call = false,
.enable_clock_stretching = true,
.use_dma = false
};
i2c_init(0, &i2c_config);
}
/* ============================================================================
* ADC Initialization
* ============================================================================ */
void board_adc_init(void) {
/* Configure ADC for analog inputs */
AdcConfig_t adc_config = {
.resolution = ADC_RESOLUTION_12BIT,
.mode = ADC_MODE_SCAN,
.trigger_source = ADC_TRIGGER_TIMER,
.reference = ADC_REFERENCE_VDD,
.enable_dma = true,
.conversion_frequency = 1000,
.channel_count = 8,
.channels = {
{.channel = 0, .sampling_time = ADC_SAMPLING_28_5_CYCLES},
{.channel = 1, .sampling_time = ADC_SAMPLING_28_5_CYCLES},
{.channel = 2, .sampling_time = ADC_SAMPLING_28_5_CYCLES},
{.channel = 3, .sampling_time = ADC_SAMPLING_28_5_CYCLES},
{.channel = 4, .sampling_time = ADC_SAMPLING_28_5_CYCLES},
{.channel = 5, .sampling_time = ADC_SAMPLING_28_5_CYCLES},
{.channel = 6, .sampling_time = ADC_SAMPLING_28_5_CYCLES},
{.channel = 7, .sampling_time = ADC_SAMPLING_28_5_CYCLES}
}
};
adc_init(0, &adc_config);
}
/* ============================================================================
* PWM Initialization
* ============================================================================ */
void board_pwm_init(void) {
/* Configure PWM outputs */
PwmConfig_t pwm_config = {
.frequency_hz = 1000,
.alignment = PWM_ALIGNMENT_EDGE,
.period_ticks = 1000,
.prescaler = 100,
.channel_count = 4,
.channels = {
{.channel = 0, .duty_cycle = 0},
{.channel = 1, .duty_cycle = 0},
{.channel = 2, .duty_cycle = 0},
{.channel = 3, .duty_cycle = 0}
},
.enable_fault_protection = true,
.fault_action = PWM_FAULT_DISABLE
};
pwm_init(0, &pwm_config);
}
/* ============================================================================
* Watchdog Initialization
* ============================================================================ */
void board_watchdog_init(void) {
/* Custom watchdog initialization */
}
void board_watchdog_service(void) {
/* Custom watchdog service */
}
/* ============================================================================
* LED Functions
* ============================================================================ */
void board_led_on(uint8_t led) {
if (led < LED_COUNT) {
gpio_write(0, led, true);
}
}
void board_led_off(uint8_t led) {
if (led < LED_COUNT) {
gpio_write(0, led, false);
}
}
void board_led_toggle(uint8_t led) {
if (led < LED_COUNT) {
gpio_toggle(0, led);
}
}
/* ============================================================================
* Button Functions
* ============================================================================ */
bool board_button_read(uint8_t button) {
/* Custom button implementation */
return false;
}
/* ============================================================================
* Delay Functions
* ============================================================================ */
void board_delay_ms(uint32_t ms) {
kernel_delay(ms);
}
void board_delay_us(uint32_t us) {
/* Custom microsecond delay */
}
/* ============================================================================
* Sensor Functions
* ============================================================================ */
float board_get_temperature(void) {
/* Custom temperature sensor reading */
return 25.0f;
}
float board_get_voltage(void) {
/* Custom voltage reading */
return 3.3f;
}
+133
View File
@@ -0,0 +1,133 @@
/**
* @file linker_script.ld
* @brief Linker script for Custom ECU
*/
ENTRY(Reset_Handler)
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 2048K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 512K
EEPROM (rw) : ORIGIN = 0x08080000, LENGTH = 16K
}
_estack = ORIGIN(RAM) + LENGTH(RAM);
_min_stack_size = 0x800;
_min_heap_size = 0x400;
SECTIONS
{
.isr_vector :
{
. = ALIGN(4);
KEEP(*(.isr_vector))
. = ALIGN(4);
} >FLASH
.text :
{
. = ALIGN(4);
*(.text)
*(.text*)
KEEP(*(.init))
KEEP(*(.fini))
. = ALIGN(4);
_etext = .;
} >FLASH
.rodata :
{
. = ALIGN(4);
*(.rodata)
*(.rodata*)
. = ALIGN(4);
} >FLASH
.ARM.extab :
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
} >FLASH
.ARM :
{
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
} >FLASH
.preinit_array :
{
PROVIDE_HIDDEN(__preinit_array_start = .);
KEEP(*(.preinit_array*))
PROVIDE_HIDDEN(__preinit_array_end = .);
} >FLASH
.init_array :
{
PROVIDE_HIDDEN(__init_array_start = .);
KEEP(*(SORT(.init_array.*)))
KEEP(*(.init_array*))
PROVIDE_HIDDEN(__init_array_end = .);
} >FLASH
.fini_array :
{
PROVIDE_HIDDEN(__fini_array_start = .);
KEEP(*(SORT(.fini_array.*)))
KEEP(*(.fini_array*))
PROVIDE_HIDDEN(__fini_array_end = .);
} >FLASH
_sidata = LOADADDR(.data);
.data :
{
. = ALIGN(4);
_sdata = .;
*(.data)
*(.data*)
. = ALIGN(4);
_edata = .;
} >RAM AT> FLASH
.bss :
{
. = ALIGN(4);
_sbss = .;
__bss_start__ = _sbss;
*(.bss)
*(.bss*)
*(COMMON)
. = ALIGN(4);
_ebss = .;
__bss_end__ = _ebss;
} >RAM
.eeprom :
{
. = ALIGN(4);
*(.eeprom)
*(.eeprom*)
. = ALIGN(4);
} >EEPROM
._user_heap_stack :
{
. = ALIGN(8);
PROVIDE(end = .);
PROVIDE(_end = .);
. = . + _min_heap_size;
. = . + _min_stack_size;
. = ALIGN(8);
} >RAM
/DISCARD/ :
{
libc.a(*)
libm.a(*)
libgcc.a(*)
}
.ARM.attributes 0 : { *(.ARM.attributes) }
}
+203
View File
@@ -0,0 +1,203 @@
/**
* @file board.h
* @brief NXP S32K144 EVB board definitions
*/
#ifndef BOARD_H
#define BOARD_H
#include <stdint.h>
#include <stdbool.h>
#include "S32K144.h"
/* ============================================================================
* Board Identification
* ============================================================================ */
#define BOARD_NAME "S32K144EVB-Q100"
#define BOARD_MANUFACTURER "NXP Semiconductors"
#define BOARD_VERSION "1.0"
#define BOARD_MCU "S32K144"
/* ============================================================================
* Clock Configuration
* ============================================================================ */
#define SOSC_FREQUENCY 8000000U /* System oscillator */
#define SPLL_FREQUENCY 160000000U /* System PLL */
#define FIRC_FREQUENCY 48000000U /* Fast IRC */
#define SIRC_FREQUENCY 8000000U /* Slow IRC */
#define SYSTEM_CLOCK 160000000U /* 160 MHz */
#define BUS_CLOCK 40000000U /* 40 MHz */
#define FLASH_CLOCK 20000000U /* 20 MHz */
/* PLL Configuration */
#define PLL_MULT 20
#define PLL_DIV 1
/* ============================================================================
* LED Definitions
* ============================================================================ */
#define LED_COUNT 3
#define LED_RED_PORT PTC
#define LED_RED_PIN 0
#define LED_RED_INDEX 0
#define LED_GREEN_PORT PTC
#define LED_GREEN_PIN 1
#define LED_GREEN_INDEX 1
#define LED_BLUE_PORT PTC
#define LED_BLUE_PIN 2
#define LED_BLUE_INDEX 2
/* LED Active Level */
#define LED_ACTIVE_LEVEL 0 /* Active low */
/* ============================================================================
* Button Definitions
* ============================================================================ */
#define BUTTON_COUNT 2
#define BUTTON1_PORT PTC
#define BUTTON1_PIN 3
#define BUTTON1_INDEX 0
#define BUTTON2_PORT PTC
#define BUTTON2_PIN 4
#define BUTTON2_INDEX 1
/* Button Active Level */
#define BUTTON_ACTIVE_LEVEL 0 /* Active low */
/* ============================================================================
* UART Definitions
* ============================================================================ */
#define UART0_INSTANCE 0
#define UART0_BAUDRATE 115200
#define UART0_TX_PORT PTA
#define UART0_TX_PIN 2
#define UART0_TX_MUX 2
#define UART0_RX_PORT PTA
#define UART0_RX_PIN 3
#define UART0_RX_MUX 2
#define UART1_INSTANCE 1
#define UART1_BAUDRATE 115200
#define UART1_TX_PORT PTC
#define UART1_TX_PIN 7
#define UART1_TX_MUX 2
#define UART1_RX_PORT PTC
#define UART1_RX_PIN 6
#define UART1_RX_MUX 2
/* ============================================================================
* CAN Definitions
* ============================================================================ */
#define CAN0_INSTANCE 0
#define CAN0_BAUDRATE 500000
#define CAN0_TX_PORT PTE
#define CAN0_TX_PIN 5
#define CAN0_TX_MUX 5
#define CAN0_RX_PORT PTE
#define CAN0_RX_PIN 4
#define CAN0_RX_MUX 5
#define CAN1_INSTANCE 1
#define CAN1_BAUDRATE 500000
#define CAN1_TX_PORT PTC
#define CAN1_TX_PIN 17
#define CAN1_TX_MUX 2
#define CAN1_RX_PORT PTC
#define CAN1_RX_PIN 16
#define CAN1_RX_MUX 2
/* ============================================================================
* SPI Definitions
* ============================================================================ */
#define SPI0_INSTANCE 0
#define SPI0_SCK_PORT PTA
#define SPI0_SCK_PIN 6
#define SPI0_SCK_MUX 2
#define SPI0_MISO_PORT PTA
#define SPI0_MISO_PIN 7
#define SPI0_MISO_MUX 2
#define SPI0_MOSI_PORT PTA
#define SPI0_MOSI_PIN 8
#define SPI0_MOSI_MUX 2
/* ============================================================================
* I2C Definitions
* ============================================================================ */
#define I2C0_INSTANCE 0
#define I2C0_SCL_PORT PTA
#define I2C0_SCL_PIN 9
#define I2C0_SCL_MUX 3
#define I2C0_SDA_PORT PTA
#define I2C0_SDA_PIN 10
#define I2C0_SDA_MUX 3
/* ============================================================================
* ADC Definitions
* ============================================================================ */
#define ADC0_INSTANCE 0
#define ADC0_CHANNEL_COUNT 8
#define ADC0_CH0_PORT PTA
#define ADC0_CH0_PIN 0
#define ADC0_CH0_MUX 0
#define ADC0_CH1_PORT PTA
#define ADC0_CH1_PIN 1
#define ADC0_CH1_MUX 0
/* ============================================================================
* PWM Definitions
* ============================================================================ */
#define PWM_INSTANCE 0
#define PWM_TIMER FTM0
#define PWM_TIMER_CHANNEL_COUNT 4
#define PWM_TIMER_FREQUENCY 10000
#define PWM_TIMER_PRESCALER 4
#define PWM_CH0_PORT PTC
#define PWM_CH0_PIN 1
#define PWM_CH0_MUX 4
#define PWM_CH1_PORT PTC
#define PWM_CH1_PIN 2
#define PWM_CH1_MUX 4
#define PWM_CH2_PORT PTC
#define PWM_CH2_PIN 3
#define PWM_CH2_MUX 4
#define PWM_CH3_PORT PTC
#define PWM_CH3_PIN 4
#define PWM_CH3_MUX 4
/* ============================================================================
* Watchdog Configuration
* ============================================================================ */
#define WATCHDOG_TIMEOUT_MS 100
#define WATCHDOG_WINDOW_MS 50
/* ============================================================================
* Board Functions
* ============================================================================ */
void board_init(void);
void board_clock_init(void);
void board_gpio_init(void);
void board_uart_init(void);
void board_can_init(void);
void board_spi_init(void);
void board_i2c_init(void);
void board_adc_init(void);
void board_pwm_init(void);
void board_watchdog_init(void);
void board_watchdog_service(void);
void board_led_on(uint8_t led);
void board_led_off(uint8_t led);
void board_led_toggle(uint8_t led);
bool board_button_read(uint8_t button);
void board_delay_ms(uint32_t ms);
void board_delay_us(uint32_t us);
float board_get_temperature(void);
float board_get_voltage(void);
#endif /* BOARD_H */
+371
View File
@@ -0,0 +1,371 @@
/**
* @file board_init.c
* @brief NXP S32K144 EVB board initialization
*/
#include "board.h"
#include "kernel.h"
#include "gpio_driver.h"
#include "uart_driver.h"
#include "can_driver.h"
#include "spi_driver.h"
#include "i2c_driver.h"
#include "adc_driver.h"
#include "pwm_driver.h"
#include <string.h>
static bool board_initialized = false;
/* ============================================================================
* Board Initialization
* ============================================================================ */
void board_init(void) {
if (board_initialized) {
return;
}
/* Initialize clock */
board_clock_init();
/* Initialize GPIO */
board_gpio_init();
/* Initialize UART */
board_uart_init();
/* Initialize CAN */
board_can_init();
/* Initialize SPI */
board_spi_init();
/* Initialize I2C */
board_i2c_init();
/* Initialize ADC */
board_adc_init();
/* Initialize PWM */
board_pwm_init();
/* Initialize watchdog */
board_watchdog_init();
board_initialized = true;
}
/* ============================================================================
* Clock Initialization
* ============================================================================ */
void board_clock_init(void) {
/* Configure system PLL */
SCG->SPLLCSR = 0; /* Reset SPLL */
SCG->SPLLDIV = SCG_SPLLDIV_SPLLDIV1(1) | SCG_SPLLDIV_SPLLDIV2(1);
SCG->SPLLCFG = SCG_SPLLCFG_MULT(20); /* 8MHz * 20 = 160MHz */
/* Enable SPLL */
SCG->SPLLCSR |= SCG_SPLLCSR_SPLLEN_MASK;
/* Wait for PLL lock */
while (!(SCG->SPLLCSR & SCG_SPLLCSR_SPLLVLD_MASK));
/* Switch to SPLL */
SCG->RCCR = SCG_RCCR_DIVCORE(1) |
SCG_RCCR_DIVBUS(4) | /* 160/4 = 40MHz */
SCG_RCCR_DIVSLOW(8) | /* 160/8 = 20MHz */
SCG_RCCR_SCS(6); /* SPLL */
/* Wait for clock switch */
while ((SCG->CSR & SCG_CSR_SCS_MASK) != SCG_CSR_SCS(6));
/* Update SystemCoreClock */
SystemCoreClock = SYSTEM_CLOCK;
}
/* ============================================================================
* GPIO Initialization
* ============================================================================ */
void board_gpio_init(void) {
/* Enable GPIO clocks */
PCC->PCCn[PCC_PORTA_INDEX] |= PCC_PCCn_CGC_MASK;
PCC->PCCn[PCC_PORTB_INDEX] |= PCC_PCCn_CGC_MASK;
PCC->PCCn[PCC_PORTC_INDEX] |= PCC_PCCn_CGC_MASK;
PCC->PCCn[PCC_PORTD_INDEX] |= PCC_PCCn_CGC_MASK;
PCC->PCCn[PCC_PORTE_INDEX] |= PCC_PCCn_CGC_MASK;
/* Configure LEDs */
GpioPinConfig_t led_config = {
.mode = GPIO_MODE_OUTPUT,
.output_type = GPIO_OUTPUT_PUSH_PULL,
.pull = GPIO_PULL_NONE,
.speed = GPIO_SPEED_HIGH
};
led_config.port = 2; /* PTC */
led_config.pin = 0;
gpio_init(&led_config);
led_config.pin = 1;
gpio_init(&led_config);
led_config.pin = 2;
gpio_init(&led_config);
/* Configure buttons */
GpioPinConfig_t button_config = {
.port = 2, /* PTC */
.pin = 3,
.mode = GPIO_MODE_INPUT,
.pull = GPIO_PULL_UP
};
gpio_init(&button_config);
button_config.pin = 4;
gpio_init(&button_config);
/* Turn off all LEDs */
board_led_off(0);
board_led_off(1);
board_led_off(2);
}
/* ============================================================================
* UART Initialization
* ============================================================================ */
void board_uart_init(void) {
/* Configure UART0 */
UartConfig_t uart_config = {
.baudrate = UART0_BAUDRATE,
.data_bits = UART_DATA_BITS_8,
.stop_bits = UART_STOP_BITS_1,
.parity = UART_PARITY_NONE,
.flow_control = UART_FLOW_CONTROL_NONE,
.enable_rx = true,
.enable_tx = true,
.use_dma = false
};
uart_init(UART0_INSTANCE, &uart_config);
}
/* ============================================================================
* CAN Initialization
* ============================================================================ */
void board_can_init(void) {
/* Configure CAN0 */
CanConfig_t can_config = {
.nominal_baudrate = CAN0_BAUDRATE,
.data_baudrate = CAN0_BAUDRATE,
.frame_type = CAN_FRAME_CLASSIC,
.enable_fd = true, /* S32K144 supports CAN FD */
.enable_automatic_retransmission = true,
.filter_count = 0
};
can_init(CAN0_INSTANCE, &can_config);
}
/* ============================================================================
* SPI Initialization
* ============================================================================ */
void board_spi_init(void) {
/* Configure SPI0 */
SpiConfig_t spi_config = {
.mode = SPI_MODE_0,
.clock_speed = SPI_CLOCK_8MHZ,
.data_order = SPI_DATA_ORDER_MSB_FIRST,
.data_size = 8,
.use_dma = false,
.enable_hardware_cs = false,
.cs_polarity = SPI_CS_ACTIVE_LOW,
.cs_port = 1,
.cs_pin = 0
};
spi_init(SPI0_INSTANCE, &spi_config);
}
/* ============================================================================
* I2C Initialization
* ============================================================================ */
void board_i2c_init(void) {
/* Configure I2C0 */
I2cConfig_t i2c_config = {
.speed = I2C_SPEED_FAST,
.addressing_mode = I2C_ADDRESSING_7BIT,
.own_address = 0x50,
.enable_general_call = false,
.enable_clock_stretching = true,
.use_dma = false
};
i2c_init(I2C0_INSTANCE, &i2c_config);
}
/* ============================================================================
* ADC Initialization
* ============================================================================ */
void board_adc_init(void) {
/* Configure ADC0 */
AdcConfig_t adc_config = {
.resolution = ADC_RESOLUTION_12BIT,
.mode = ADC_MODE_SCAN,
.trigger_source = ADC_TRIGGER_SOFTWARE,
.reference = ADC_REFERENCE_VDD,
.enable_dma = false,
.conversion_frequency = 1000,
.channel_count = 8,
.channels = {
{.channel = 0, .sampling_time = ADC_SAMPLING_13_5_CYCLES},
{.channel = 1, .sampling_time = ADC_SAMPLING_13_5_CYCLES},
{.channel = 2, .sampling_time = ADC_SAMPLING_13_5_CYCLES},
{.channel = 3, .sampling_time = ADC_SAMPLING_13_5_CYCLES},
{.channel = 4, .sampling_time = ADC_SAMPLING_13_5_CYCLES},
{.channel = 5, .sampling_time = ADC_SAMPLING_13_5_CYCLES},
{.channel = 6, .sampling_time = ADC_SAMPLING_13_5_CYCLES},
{.channel = 7, .sampling_time = ADC_SAMPLING_13_5_CYCLES}
}
};
adc_init(ADC0_INSTANCE, &adc_config);
}
/* ============================================================================
* PWM Initialization
* ============================================================================ */
void board_pwm_init(void) {
/* Configure PWM */
PwmConfig_t pwm_config = {
.frequency_hz = PWM_TIMER_FREQUENCY,
.alignment = PWM_ALIGNMENT_EDGE,
.period_ticks = 10000,
.prescaler = PWM_TIMER_PRESCALER,
.channel_count = 4,
.channels = {
{.channel = 0, .duty_cycle = 0},
{.channel = 1, .duty_cycle = 0},
{.channel = 2, .duty_cycle = 0},
{.channel = 3, .duty_cycle = 0}
},
.enable_fault_protection = true,
.fault_action = PWM_FAULT_DISABLE
};
pwm_init(PWM_INSTANCE, &pwm_config);
}
/* ============================================================================
* Watchdog Initialization
* ============================================================================ */
void board_watchdog_init(void) {
/* Configure WDOG */
WDOG->CNT = 0x1000; /* Timeout value */
WDOG->TOVAL = 0x1000;
WDOG->CS = WDOG_CS_EN_MASK |
WDOG_CS_CLK(1) |
WDOG_CS_WIN_MASK |
WDOG_CS_UPDATE_MASK;
}
void board_watchdog_service(void) {
/* Service WDOG */
WDOG->CNT = 0xB480;
WDOG->CNT = 0x4B80;
}
/* ============================================================================
* LED Functions
* ============================================================================ */
void board_led_on(uint8_t led) {
switch (led) {
case 0:
gpio_write(2, 0, false); /* Active low */
break;
case 1:
gpio_write(2, 1, false);
break;
case 2:
gpio_write(2, 2, false);
break;
}
}
void board_led_off(uint8_t led) {
switch (led) {
case 0:
gpio_write(2, 0, true);
break;
case 1:
gpio_write(2, 1, true);
break;
case 2:
gpio_write(2, 2, true);
break;
}
}
void board_led_toggle(uint8_t led) {
switch (led) {
case 0:
gpio_toggle(2, 0);
break;
case 1:
gpio_toggle(2, 1);
break;
case 2:
gpio_toggle(2, 2);
break;
}
}
/* ============================================================================
* Button Functions
* ============================================================================ */
bool board_button_read(uint8_t button) {
switch (button) {
case 0:
return !gpio_read(2, 3); /* Active low */
case 1:
return !gpio_read(2, 4);
default:
return false;
}
}
/* ============================================================================
* Delay Functions
* ============================================================================ */
void board_delay_ms(uint32_t ms) {
kernel_delay(ms);
}
void board_delay_us(uint32_t us) {
uint32_t count = us * (SystemCoreClock / 1000000) / 5;
while (count--) {
__NOP();
}
}
/* ============================================================================
* Sensor Functions
* ============================================================================ */
float board_get_temperature(void) {
/* Read internal temperature sensor */
uint16_t adc_value = 0;
adc_read_channel(ADC0_INSTANCE, 26, &adc_value, 10); /* Internal temp sensor */
/* Convert to temperature (S32K144 specific formula) */
float voltage = adc_convert_to_voltage(adc_value, ADC_RESOLUTION_12BIT, 3.3f);
float temperature = 25.0f - ((voltage - 0.716f) / 0.00162f);
return temperature;
}
float board_get_voltage(void) {
/* Read bandgap reference */
uint16_t adc_value = 0;
adc_read_channel(ADC0_INSTANCE, 27, &adc_value, 10); /* Bandgap */
float voltage = adc_convert_to_voltage(adc_value, ADC_RESOLUTION_12BIT, 3.3f);
return voltage;
}
+141
View File
@@ -0,0 +1,141 @@
/**
* @file linker_script.ld
* @brief Linker script for NXP S32K144
*/
ENTRY(Reset_Handler)
MEMORY
{
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 512K
SRAM_L (rwx) : ORIGIN = 0x1FFF8000, LENGTH = 32K
SRAM_U (rwx) : ORIGIN = 0x20000000, LENGTH = 28K
}
_estack = ORIGIN(SRAM_U) + LENGTH(SRAM_U);
_min_stack_size = 0x400;
_min_heap_size = 0x200;
SECTIONS
{
/* Interrupt Vector Table */
.isr_vector :
{
. = ALIGN(4);
KEEP(*(.isr_vector))
. = ALIGN(4);
} >FLASH
/* Program Code */
.text :
{
. = ALIGN(4);
*(.text)
*(.text*)
*(.glue_7)
*(.glue_7t)
*(.eh_frame)
KEEP(*(.init))
KEEP(*(.fini))
. = ALIGN(4);
_etext = .;
} >FLASH
/* Constant Data */
.rodata :
{
. = ALIGN(4);
*(.rodata)
*(.rodata*)
. = ALIGN(4);
} >FLASH
/* ARM Extensions */
.ARM.extab :
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
} >FLASH
.ARM :
{
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
} >FLASH
/* Initialization Arrays */
.preinit_array :
{
PROVIDE_HIDDEN(__preinit_array_start = .);
KEEP(*(.preinit_array*))
PROVIDE_HIDDEN(__preinit_array_end = .);
} >FLASH
.init_array :
{
PROVIDE_HIDDEN(__init_array_start = .);
KEEP(*(SORT(.init_array.*)))
KEEP(*(.init_array*))
PROVIDE_HIDDEN(__init_array_end = .);
} >FLASH
.fini_array :
{
PROVIDE_HIDDEN(__fini_array_start = .);
KEEP(*(SORT(.fini_array.*)))
KEEP(*(.fini_array*))
PROVIDE_HIDDEN(__fini_array_end = .);
} >FLASH
/* Data Sections */
_sidata = LOADADDR(.data);
.data :
{
. = ALIGN(4);
_sdata = .;
*(.data)
*(.data*)
. = ALIGN(4);
_edata = .;
} >SRAM_L AT> FLASH
/* BSS Section */
.bss :
{
. = ALIGN(4);
_sbss = .;
__bss_start__ = _sbss;
*(.bss)
*(.bss*)
*(COMMON)
. = ALIGN(4);
_ebss = .;
__bss_end__ = _ebss;
} >SRAM_L
/* Heap and Stack */
._user_heap_stack :
{
. = ALIGN(8);
PROVIDE(end = .);
PROVIDE(_end = .);
. = . + _min_heap_size;
. = . + _min_stack_size;
. = ALIGN(8);
} >SRAM_U
/* Discard */
/DISCARD/ :
{
libc.a(*)
libm.a(*)
libgcc.a(*)
}
.ARM.attributes 0 : { *(.ARM.attributes) }
}
+227
View File
@@ -0,0 +1,227 @@
/**
* @file board.h
* @brief STM32F407 Discovery board definitions
*/
#ifndef BOARD_H
#define BOARD_H
#include <stdint.h>
#include <stdbool.h>
#include "stm32f4xx.h"
/* ============================================================================
* Board Identification
* ============================================================================ */
#define BOARD_NAME "STM32F407G-DISC1"
#define BOARD_MANUFACTURER "STMicroelectronics"
#define BOARD_VERSION "1.0"
#define BOARD_MCU "STM32F407VG"
/* ============================================================================
* Clock Configuration
* ============================================================================ */
#define HSE_VALUE 8000000U /* External crystal */
#define HSI_VALUE 16000000U /* Internal oscillator */
#define LSE_VALUE 32768U /* Low speed external */
#define LSI_VALUE 32000U /* Low speed internal */
#define SYSTEM_CLOCK 168000000U /* 168 MHz */
#define AHB_CLOCK 168000000U
#define APB1_CLOCK 42000000U
#define APB2_CLOCK 84000000U
#define USB_CLOCK 48000000U
/* PLL Configuration */
#define PLL_M 8
#define PLL_N 336
#define PLL_P 2
#define PLL_Q 7
/* ============================================================================
* LED Definitions
* ============================================================================ */
#define LED_COUNT 4
#define LED1_PORT GPIOD
#define LED1_PIN GPIO_PIN_12
#define LED1_CLOCK __HAL_RCC_GPIOD_CLK_ENABLE()
#define LED2_PORT GPIOD
#define LED2_PIN GPIO_PIN_13
#define LED2_CLOCK __HAL_RCC_GPIOD_CLK_ENABLE()
#define LED3_PORT GPIOD
#define LED3_PIN GPIO_PIN_14
#define LED3_CLOCK __HAL_RCC_GPIOD_CLK_ENABLE()
#define LED4_PORT GPIOD
#define LED4_PIN GPIO_PIN_15
#define LED4_CLOCK __HAL_RCC_GPIOD_CLK_ENABLE()
/* LED Active Level */
#define LED_ACTIVE_LEVEL GPIO_PIN_SET
/* ============================================================================
* Button Definitions
* ============================================================================ */
#define BUTTON_COUNT 1
#define BUTTON1_PORT GPIOA
#define BUTTON1_PIN GPIO_PIN_0
#define BUTTON1_CLOCK __HAL_RCC_GPIOA_CLK_ENABLE()
#define BUTTON1_EXTI_IRQ EXTI0_IRQn
/* Button Active Level */
#define BUTTON_ACTIVE_LEVEL GPIO_PIN_SET
/* ============================================================================
* UART Definitions
* ============================================================================ */
#define UART1_INSTANCE 0
#define UART1_BAUDRATE 115200
#define UART1_WORDLENGTH UART_WORDLENGTH_8B
#define UART1_STOPBITS UART_STOPBITS_1
#define UART1_PARITY UART_PARITY_NONE
#define UART1_HWFLOWCTL UART_HWCONTROL_NONE
#define UART1_TX_PORT GPIOA
#define UART1_TX_PIN GPIO_PIN_9
#define UART1_TX_AF GPIO_AF7_USART1
#define UART1_RX_PORT GPIOA
#define UART1_RX_PIN GPIO_PIN_10
#define UART1_RX_AF GPIO_AF7_USART1
#define UART1_CLOCK_ENABLE() __HAL_RCC_USART1_CLK_ENABLE()
#define UART1_GPIO_CLOCK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE()
#define UART2_INSTANCE 1
#define UART2_BAUDRATE 115200
#define UART2_TX_PORT GPIOA
#define UART2_TX_PIN GPIO_PIN_2
#define UART2_TX_AF GPIO_AF7_USART2
#define UART2_RX_PORT GPIOA
#define UART2_RX_PIN GPIO_PIN_3
#define UART2_RX_AF GPIO_AF7_USART2
#define UART2_CLOCK_ENABLE() __HAL_RCC_USART2_CLK_ENABLE()
/* ============================================================================
* CAN Definitions
* ============================================================================ */
#define CAN1_INSTANCE 0
#define CAN1_BAUDRATE 500000
#define CAN1_TX_PORT GPIOB
#define CAN1_TX_PIN GPIO_PIN_9
#define CAN1_TX_AF GPIO_AF9_CAN1
#define CAN1_RX_PORT GPIOB
#define CAN1_RX_PIN GPIO_PIN_8
#define CAN1_RX_AF GPIO_AF9_CAN1
#define CAN1_CLOCK_ENABLE() __HAL_RCC_CAN1_CLK_ENABLE()
#define CAN1_GPIO_CLOCK_ENABLE() __HAL_RCC_GPIOB_CLK_ENABLE()
#define CAN2_INSTANCE 1
#define CAN2_BAUDRATE 500000
#define CAN2_TX_PORT GPIOB
#define CAN2_TX_PIN GPIO_PIN_13
#define CAN2_TX_AF GPIO_AF9_CAN2
#define CAN2_RX_PORT GPIOB
#define CAN2_RX_PIN GPIO_PIN_12
#define CAN2_RX_AF GPIO_AF9_CAN2
#define CAN2_CLOCK_ENABLE() __HAL_RCC_CAN2_CLK_ENABLE()
/* ============================================================================
* SPI Definitions
* ============================================================================ */
#define SPI1_INSTANCE 0
#define SPI1_SCK_PORT GPIOA
#define SPI1_SCK_PIN GPIO_PIN_5
#define SPI1_SCK_AF GPIO_AF5_SPI1
#define SPI1_MISO_PORT GPIOA
#define SPI1_MISO_PIN GPIO_PIN_6
#define SPI1_MISO_AF GPIO_AF5_SPI1
#define SPI1_MOSI_PORT GPIOA
#define SPI1_MOSI_PIN GPIO_PIN_7
#define SPI1_MOSI_AF GPIO_AF5_SPI1
#define SPI1_CLOCK_ENABLE() __HAL_RCC_SPI1_CLK_ENABLE()
/* ============================================================================
* I2C Definitions
* ============================================================================ */
#define I2C1_INSTANCE 0
#define I2C1_SCL_PORT GPIOB
#define I2C1_SCL_PIN GPIO_PIN_6
#define I2C1_SCL_AF GPIO_AF4_I2C1
#define I2C1_SDA_PORT GPIOB
#define I2C1_SDA_PIN GPIO_PIN_7
#define I2C1_SDA_AF GPIO_AF4_I2C1
#define I2C1_CLOCK_ENABLE() __HAL_RCC_I2C1_CLK_ENABLE()
/* ============================================================================
* ADC Definitions
* ============================================================================ */
#define ADC1_INSTANCE 0
#define ADC1_CHANNEL_COUNT 6
#define ADC1_CH0_PORT GPIOA
#define ADC1_CH0_PIN GPIO_PIN_0
#define ADC1_CH1_PORT GPIOA
#define ADC1_CH1_PIN GPIO_PIN_1
#define ADC1_CH2_PORT GPIOA
#define ADC1_CH2_PIN GPIO_PIN_2
#define ADC1_CH3_PORT GPIOA
#define ADC1_CH3_PIN GPIO_PIN_3
#define ADC1_CLOCK_ENABLE() __HAL_RCC_ADC1_CLK_ENABLE()
/* ============================================================================
* PWM/Timer Definitions
* ============================================================================ */
#define PWM_TIMER_INSTANCE 0
#define PWM_TIMER TIM1
#define PWM_TIMER_CLOCK_ENABLE() __HAL_RCC_TIM1_CLK_ENABLE()
#define PWM_TIMER_CHANNEL_COUNT 4
#define PWM_TIMER_PRESCALER 168 /* 1 MHz */
#define PWM_TIMER_PERIOD 1000 /* 1 kHz */
#define PWM_TIMER_IRQ TIM1_UP_TIM10_IRQn
#define PWM_CH1_PORT GPIOA
#define PWM_CH1_PIN GPIO_PIN_8
#define PWM_CH1_AF GPIO_AF1_TIM1
#define PWM_CH2_PORT GPIOA
#define PWM_CH2_PIN GPIO_PIN_9
#define PWM_CH2_AF GPIO_AF1_TIM1
#define PWM_CH3_PORT GPIOA
#define PWM_CH3_PIN GPIO_PIN_10
#define PWM_CH3_AF GPIO_AF1_TIM1
#define PWM_CH4_PORT GPIOA
#define PWM_CH4_PIN GPIO_PIN_11
#define PWM_CH4_AF GPIO_AF1_TIM1
/* ============================================================================
* Watchdog Configuration
* ============================================================================ */
#define WATCHDOG_INSTANCE 0
#define WATCHDOG_TIMEOUT_MS 100
#define WATCHDOG_WINDOW_MS 50
/* ============================================================================
* Board Functions
* ============================================================================ */
void board_init(void);
void board_clock_init(void);
void board_gpio_init(void);
void board_uart_init(void);
void board_can_init(void);
void board_spi_init(void);
void board_i2c_init(void);
void board_adc_init(void);
void board_pwm_init(void);
void board_watchdog_init(void);
void board_watchdog_service(void);
void board_led_on(uint8_t led);
void board_led_off(uint8_t led);
void board_led_toggle(uint8_t led);
bool board_button_read(uint8_t button);
void board_delay_ms(uint32_t ms);
void board_delay_us(uint32_t us);
float board_get_temperature(void);
float board_get_voltage(void);
#endif /* BOARD_H */
+388
View File
@@ -0,0 +1,388 @@
/**
* @file board_init.c
* @brief STM32F407 Discovery board initialization
*/
#include "board.h"
#include "kernel.h"
#include "gpio_driver.h"
#include "uart_driver.h"
#include "can_driver.h"
#include "spi_driver.h"
#include "i2c_driver.h"
#include "adc_driver.h"
#include "pwm_driver.h"
#include <string.h>
/* Board state */
static bool board_initialized = false;
/* ============================================================================
* Board Initialization
* ============================================================================ */
void board_init(void) {
if (board_initialized) {
return;
}
/* Initialize clock */
board_clock_init();
/* Initialize GPIO */
board_gpio_init();
/* Initialize UART */
board_uart_init();
/* Initialize CAN */
board_can_init();
/* Initialize SPI */
board_spi_init();
/* Initialize I2C */
board_i2c_init();
/* Initialize ADC */
board_adc_init();
/* Initialize PWM */
board_pwm_init();
/* Initialize watchdog */
board_watchdog_init();
board_initialized = true;
}
/* ============================================================================
* Clock Initialization
* ============================================================================ */
void board_clock_init(void) {
/* Reset RCC */
RCC->CR |= RCC_CR_HSION;
while (!(RCC->CR & RCC_CR_HSIRDY));
/* Configure PLL */
RCC->PLLCFGR = (PLL_M << RCC_PLLCFGR_PLLM_Pos) |
(PLL_N << RCC_PLLCFGR_PLLN_Pos) |
(((PLL_P >> 1) - 1) << RCC_PLLCFGR_PLLP_Pos) |
(PLL_Q << RCC_PLLCFGR_PLLQ_Pos);
/* Enable PLL */
RCC->CR |= RCC_CR_PLLON;
while (!(RCC->CR & RCC_CR_PLLRDY));
/* Configure flash latency */
FLASH->ACR = FLASH_ACR_LATENCY_5WS | FLASH_ACR_PRFTEN | FLASH_ACR_ICEN | FLASH_ACR_DCEN;
/* Configure AHB, APB1, APB2 prescalers */
RCC->CFGR = RCC_CFGR_HPRE_DIV1 | RCC_CFGR_PPRE1_DIV4 | RCC_CFGR_PPRE2_DIV2;
/* Switch to PLL */
RCC->CFGR |= RCC_CFGR_SW_PLL;
while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL);
/* Update SystemCoreClock variable */
SystemCoreClockUpdate();
}
/* ============================================================================
* GPIO Initialization
* ============================================================================ */
void board_gpio_init(void) {
/* Enable GPIO clocks */
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOE_CLK_ENABLE();
/* Configure LEDs */
GpioPinConfig_t led_config = {
.mode = GPIO_MODE_OUTPUT,
.output_type = GPIO_OUTPUT_PUSH_PULL,
.pull = GPIO_PULL_NONE,
.speed = GPIO_SPEED_HIGH
};
led_config.port = 3; /* GPIOD */
led_config.pin = 12;
gpio_init(&led_config);
led_config.pin = 13;
gpio_init(&led_config);
led_config.pin = 14;
gpio_init(&led_config);
led_config.pin = 15;
gpio_init(&led_config);
/* Configure button */
GpioPinConfig_t button_config = {
.port = 0, /* GPIOA */
.pin = 0,
.mode = GPIO_MODE_INPUT,
.pull = GPIO_PULL_DOWN
};
gpio_init(&button_config);
/* Turn off all LEDs */
board_led_off(0);
board_led_off(1);
board_led_off(2);
board_led_off(3);
}
/* ============================================================================
* UART Initialization
* ============================================================================ */
void board_uart_init(void) {
/* Configure UART1 */
UartConfig_t uart1_config = {
.baudrate = UART1_BAUDRATE,
.data_bits = UART_DATA_BITS_8,
.stop_bits = UART_STOP_BITS_1,
.parity = UART_PARITY_NONE,
.flow_control = UART_FLOW_CONTROL_NONE,
.enable_rx = true,
.enable_tx = true,
.use_dma = false
};
uart_init(UART1_INSTANCE, &uart1_config);
/* Configure UART2 */
UartConfig_t uart2_config = uart1_config;
uart_init(UART2_INSTANCE, &uart2_config);
}
/* ============================================================================
* CAN Initialization
* ============================================================================ */
void board_can_init(void) {
/* Configure CAN1 */
CanConfig_t can1_config = {
.nominal_baudrate = CAN1_BAUDRATE,
.data_baudrate = CAN1_BAUDRATE,
.frame_type = CAN_FRAME_CLASSIC,
.enable_fd = false,
.enable_automatic_retransmission = true,
.filter_count = 0
};
can_init(&can1_config);
/* Configure CAN2 */
CanConfig_t can2_config = can1_config;
can_init(&can2_config);
}
/* ============================================================================
* SPI Initialization
* ============================================================================ */
void board_spi_init(void) {
/* Configure SPI1 */
SpiConfig_t spi1_config = {
.mode = SPI_MODE_0,
.clock_speed = SPI_CLOCK_8MHZ,
.data_order = SPI_DATA_ORDER_MSB_FIRST,
.data_size = 8,
.use_dma = false,
.enable_hardware_cs = false,
.cs_polarity = SPI_CS_ACTIVE_LOW,
.cs_port = 0,
.cs_pin = 4
};
spi_init(SPI1_INSTANCE, &spi1_config);
}
/* ============================================================================
* I2C Initialization
* ============================================================================ */
void board_i2c_init(void) {
/* Configure I2C1 */
I2cConfig_t i2c1_config = {
.speed = I2C_SPEED_FAST,
.addressing_mode = I2C_ADDRESSING_7BIT,
.own_address = 0x50,
.enable_general_call = false,
.enable_clock_stretching = true,
.use_dma = false
};
i2c_init(I2C1_INSTANCE, &i2c1_config);
}
/* ============================================================================
* ADC Initialization
* ============================================================================ */
void board_adc_init(void) {
/* Configure ADC1 */
AdcConfig_t adc1_config = {
.resolution = ADC_RESOLUTION_12BIT,
.mode = ADC_MODE_SCAN,
.trigger_source = ADC_TRIGGER_TIMER,
.reference = ADC_REFERENCE_VDD,
.enable_dma = false,
.conversion_frequency = 1000,
.channel_count = 6,
.channels = {
{.channel = 0, .sampling_time = ADC_SAMPLING_28_5_CYCLES},
{.channel = 1, .sampling_time = ADC_SAMPLING_28_5_CYCLES},
{.channel = 2, .sampling_time = ADC_SAMPLING_28_5_CYCLES},
{.channel = 3, .sampling_time = ADC_SAMPLING_28_5_CYCLES},
{.channel = 4, .sampling_time = ADC_SAMPLING_28_5_CYCLES},
{.channel = 5, .sampling_time = ADC_SAMPLING_28_5_CYCLES}
}
};
adc_init(ADC1_INSTANCE, &adc1_config);
}
/* ============================================================================
* PWM Initialization
* ============================================================================ */
void board_pwm_init(void) {
/* Configure PWM timer */
PwmConfig_t pwm_config = {
.frequency_hz = 1000,
.alignment = PWM_ALIGNMENT_EDGE,
.period_ticks = 1000,
.prescaler = 168,
.channel_count = 4,
.channels = {
{.channel = 0, .duty_cycle = 0, .polarity = PWM_POLARITY_ACTIVE_HIGH},
{.channel = 1, .duty_cycle = 0, .polarity = PWM_POLARITY_ACTIVE_HIGH},
{.channel = 2, .duty_cycle = 0, .polarity = PWM_POLARITY_ACTIVE_HIGH},
{.channel = 3, .duty_cycle = 0, .polarity = PWM_POLARITY_ACTIVE_HIGH}
},
.enable_fault_protection = true,
.fault_action = PWM_FAULT_DISABLE
};
pwm_init(PWM_TIMER_INSTANCE, &pwm_config);
}
/* ============================================================================
* Watchdog Initialization
* ============================================================================ */
void board_watchdog_init(void) {
/* Enable IWDG */
IWDG->KR = 0x5555; /* Enable write access */
IWDG->PR = 0x06; /* Prescaler: 256 */
IWDG->RLR = 0x0FFF; /* Reload value */
IWDG->KR = 0xCCCC; /* Start watchdog */
}
void board_watchdog_service(void) {
/* Service IWDG */
IWDG->KR = 0xAAAA;
}
/* ============================================================================
* LED Functions
* ============================================================================ */
void board_led_on(uint8_t led) {
switch (led) {
case 0:
gpio_write(3, 12, true);
break;
case 1:
gpio_write(3, 13, true);
break;
case 2:
gpio_write(3, 14, true);
break;
case 3:
gpio_write(3, 15, true);
break;
}
}
void board_led_off(uint8_t led) {
switch (led) {
case 0:
gpio_write(3, 12, false);
break;
case 1:
gpio_write(3, 13, false);
break;
case 2:
gpio_write(3, 14, false);
break;
case 3:
gpio_write(3, 15, false);
break;
}
}
void board_led_toggle(uint8_t led) {
switch (led) {
case 0:
gpio_toggle(3, 12);
break;
case 1:
gpio_toggle(3, 13);
break;
case 2:
gpio_toggle(3, 14);
break;
case 3:
gpio_toggle(3, 15);
break;
}
}
/* ============================================================================
* Button Functions
* ============================================================================ */
bool board_button_read(uint8_t button) {
if (button == 0) {
return gpio_read(0, 0);
}
return false;
}
/* ============================================================================
* Delay Functions
* ============================================================================ */
void board_delay_ms(uint32_t ms) {
kernel_delay(ms);
}
void board_delay_us(uint32_t us) {
/* Simple busy-wait delay */
uint32_t count = us * (SystemCoreClock / 1000000) / 5;
while (count--) {
__NOP();
}
}
/* ============================================================================
* Sensor Functions
* ============================================================================ */
float board_get_temperature(void) {
/* Read internal temperature sensor */
uint16_t adc_value = 0;
adc_read_channel(ADC1_INSTANCE, 16, &adc_value, 10);
/* Convert to temperature */
float voltage = adc_convert_to_voltage(adc_value, ADC_RESOLUTION_12BIT, 3.3f);
float temperature = ((voltage - 0.76f) / 0.0025f) + 25.0f;
return temperature;
}
float board_get_voltage(void) {
/* Read VREFINT */
uint16_t adc_value = 0;
adc_read_channel(ADC1_INSTANCE, 17, &adc_value, 10);
/* Convert to voltage */
float voltage = adc_convert_to_voltage(adc_value, ADC_RESOLUTION_12BIT, 3.3f);
return voltage;
}
+160
View File
@@ -0,0 +1,160 @@
/**
* @file linker_script.ld
* @brief Linker script for STM32F407VG
*/
/* Entry Point */
ENTRY(Reset_Handler)
/* Memory Map */
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K
CCMRAM (rw) : ORIGIN = 0x10000000, LENGTH = 64K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
}
/* Stack Configuration */
_estack = ORIGIN(RAM) + LENGTH(RAM); /* End of RAM */
_min_stack_size = 0x400; /* 1KB minimum stack */
_min_heap_size = 0x200; /* 512B minimum heap */
/* Sections */
SECTIONS
{
/* Interrupt Vector Table */
.isr_vector :
{
. = ALIGN(4);
KEEP(*(.isr_vector))
. = ALIGN(4);
} >FLASH
/* Program Code */
.text :
{
. = ALIGN(4);
*(.text)
*(.text*)
*(.glue_7)
*(.glue_7t)
*(.eh_frame)
KEEP(*(.init))
KEEP(*(.fini))
. = ALIGN(4);
_etext = .;
} >FLASH
/* Constant Data */
.rodata :
{
. = ALIGN(4);
*(.rodata)
*(.rodata*)
. = ALIGN(4);
} >FLASH
/* ARM Extensions */
.ARM.extab :
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
} >FLASH
.ARM :
{
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
} >FLASH
/* Pre-initialization Array */
.preinit_array :
{
PROVIDE_HIDDEN(__preinit_array_start = .);
KEEP(*(.preinit_array*))
PROVIDE_HIDDEN(__preinit_array_end = .);
} >FLASH
/* Initialization Array */
.init_array :
{
PROVIDE_HIDDEN(__init_array_start = .);
KEEP(*(SORT(.init_array.*)))
KEEP(*(.init_array*))
PROVIDE_HIDDEN(__init_array_end = .);
} >FLASH
/* Finalization Array */
.fini_array :
{
PROVIDE_HIDDEN(__fini_array_start = .);
KEEP(*(SORT(.fini_array.*)))
KEEP(*(.fini_array*))
PROVIDE_HIDDEN(__fini_array_end = .);
} >FLASH
/* Used by startup to initialize data */
_sidata = LOADADDR(.data);
/* Initialized Data */
.data :
{
. = ALIGN(4);
_sdata = .;
*(.data)
*(.data*)
. = ALIGN(4);
_edata = .;
} >RAM AT> FLASH
/* Uninitialized Data */
.bss :
{
. = ALIGN(4);
_sbss = .;
__bss_start__ = _sbss;
*(.bss)
*(.bss*)
*(COMMON)
. = ALIGN(4);
_ebss = .;
__bss_end__ = _ebss;
} >RAM
/* CCMRAM Section */
.ccmram :
{
. = ALIGN(4);
_sccmram = .;
*(.ccmram)
*(.ccmram*)
. = ALIGN(4);
_eccmram = .;
} >CCMRAM
/* Heap Section */
._user_heap_stack :
{
. = ALIGN(8);
PROVIDE(end = .);
PROVIDE(_end = .);
. = . + _min_heap_size;
. = . + _min_stack_size;
. = ALIGN(8);
} >RAM
/* Remove information from standard libraries */
/DISCARD/ :
{
libc.a(*)
libm.a(*)
libgcc.a(*)
}
.ARM.attributes 0 : { *(.ARM.attributes) }
}
Executable
+42
View File
@@ -0,0 +1,42 @@
#!/bin/bash
# Project root
PROJECT_ROOT="$(pwd)"
# Toolchain paths (adjust based on your system)
TOOLCHAIN_BIN="/opt/homebrew/bin"
NEWLIB_INCLUDE="/opt/homebrew/opt/arm-none-eabi-newlib/arm-none-eabi/include"
GCC_INCLUDE="/opt/homebrew/Cellar/arm-none-eabi-gcc/16.2.0/lib/gcc/arm-none-eabi/16.2.0/include"
# Project include paths
INCLUDE_PATHS=(
"-I${PROJECT_ROOT}/kernel/include"
"-I${PROJECT_ROOT}/drivers/include"
"-I${PROJECT_ROOT}/middleware"
"-I${PROJECT_ROOT}/middleware/can_stack/include"
"-I${PROJECT_ROOT}/middleware/diagnostics/include"
"-I${PROJECT_ROOT}/config"
"-I${NEWLIB_INCLUDE}"
"-I${GCC_INCLUDE}"
)
# Test compilation
echo "Testing compilation..."
arm-none-eabi-gcc \
-mcpu=cortex-m4 \
-mthumb \
-O0 \
-g \
-Wall \
-Wextra \
"${INCLUDE_PATHS[@]}" \
-c kernel/src/kernel_init.c \
-o test.o
if [ $? -eq 0 ]; then
echo "✓ Compilation successful!"
rm -f test.o
else
echo "✗ Compilation failed"
exit 1
fi
+238
View File
@@ -0,0 +1,238 @@
/**
* @file board_config.h
* @brief Board-specific configuration
*/
#ifndef BOARD_CONFIG_H
#define BOARD_CONFIG_H
#include "mcu_config.h"
/* ============================================================================
* Board Selection
* ============================================================================ */
#define BOARD_STM32F407_DISCOVERY 1
#define BOARD_NXP_S32K144_EVB 0
#define BOARD_INFINEON_TC397_EVB 0
#if (BOARD_STM32F407_DISCOVERY + BOARD_NXP_S32K144_EVB + BOARD_INFINEON_TC397_EVB) != 1
#error "Exactly one board must be selected"
#endif
/* ============================================================================
* Pin Mapping
* ============================================================================ */
#if BOARD_STM32F407_DISCOVERY
/* STM32F407 Discovery board pin mapping */
/* LED pins */
#define LED1_PORT 0 /* GPIOA */
#define LED1_PIN 0
#define LED2_PORT 0
#define LED2_PIN 1
#define LED3_PORT 0
#define LED3_PIN 2
#define LED4_PORT 0
#define LED4_PIN 3
/* Button pins */
#define BUTTON1_PORT 0 /* GPIOA */
#define BUTTON1_PIN 0
/* UART pins */
#define UART1_TX_PORT 0 /* GPIOA */
#define UART1_TX_PIN 9
#define UART1_RX_PORT 0
#define UART1_RX_PIN 10
/* CAN pins */
#define CAN1_TX_PORT 1 /* GPIOB */
#define CAN1_TX_PIN 9
#define CAN1_RX_PORT 1
#define CAN1_RX_PIN 8
/* SPI pins */
#define SPI1_SCK_PORT 0 /* GPIOA */
#define SPI1_SCK_PIN 5
#define SPI1_MISO_PORT 0
#define SPI1_MISO_PIN 6
#define SPI1_MOSI_PORT 0
#define SPI1_MOSI_PIN 7
/* I2C pins */
#define I2C1_SCL_PORT 1 /* GPIOB */
#define I2C1_SCL_PIN 6
#define I2C1_SDA_PORT 1
#define I2C1_SDA_PIN 7
/* ADC pins */
#define ADC1_CH0_PORT 0 /* GPIOA */
#define ADC1_CH0_PIN 0
#define ADC1_CH1_PORT 0
#define ADC1_CH1_PIN 1
/* PWM pins */
#define PWM1_CH1_PORT 0 /* GPIOA */
#define PWM1_CH1_PIN 8
#define PWM1_CH2_PORT 0
#define PWM1_CH2_PIN 9
#elif BOARD_NXP_S32K144_EVB
/* NXP S32K144 EVB pin mapping */
/* LED pins */
#define LED_RED_PORT 2 /* GPIOC */
#define LED_RED_PIN 0
#define LED_GREEN_PORT 2
#define LED_GREEN_PIN 1
#define LED_BLUE_PORT 2
#define LED_BLUE_PIN 2
/* Button pins */
#define BUTTON1_PORT 2 /* GPIOC */
#define BUTTON1_PIN 3
#define BUTTON2_PORT 2
#define BUTTON2_PIN 4
/* UART pins */
#define UART0_TX_PORT 0 /* GPIOA */
#define UART0_TX_PIN 2
#define UART0_RX_PORT 0
#define UART0_RX_PIN 3
/* CAN pins */
#define CAN0_TX_PORT 4 /* GPIOE */
#define CAN0_TX_PIN 5
#define CAN0_RX_PORT 4
#define CAN0_RX_PIN 4
/* SPI pins */
#define SPI0_SCK_PORT 0 /* GPIOA */
#define SPI0_SCK_PIN 6
#define SPI0_MISO_PORT 0
#define SPI0_MISO_PIN 7
#define SPI0_MOSI_PORT 0
#define SPI0_MOSI_PIN 8
#elif BOARD_INFINEON_TC397_EVB
/* Infineon TC397 EVB pin mapping */
/* LED pins */
#define LED1_PORT 0 /* P00 */
#define LED1_PIN 0
#define LED2_PORT 0
#define LED2_PIN 1
/* Button pins */
#define BUTTON1_PORT 0 /* P00 */
#define BUTTON1_PIN 2
/* UART pins */
#define UART0_TX_PORT 0 /* P00 */
#define UART0_TX_PIN 3
#define UART0_RX_PORT 0
#define UART0_RX_PIN 4
/* CAN pins */
#define CAN0_TX_PORT 0 /* P00 */
#define CAN0_TX_PIN 5
#define CAN0_RX_PORT 0
#define CAN0_RX_PIN 6
#endif
/* ============================================================================
* Board Features
* ============================================================================ */
/* Debug interface */
#define DEBUG_INTERFACE_SWD 1
#define DEBUG_INTERFACE_JTAG 0
/* External crystal frequency */
#define EXTERNAL_CRYSTAL_HZ 8000000U
/* Board voltage */
#define BOARD_VOLTAGE 3.3f /* Volts */
/* ============================================================================
* External Components
* ============================================================================ */
/* External memory */
#define EXT_FLASH_ENABLED 0
#define EXT_RAM_ENABLED 0
/* External sensors */
#define TEMP_SENSOR_ENABLED 1
#define ACCELEROMETER_ENABLED 1
#define GYROSCOPE_ENABLED 0
/* Display */
#define LCD_DISPLAY_ENABLED 1
#define LCD_WIDTH 240
#define LCD_HEIGHT 320
#define LCD_COLOR_DEPTH 16
/* CAN transceiver */
#define CAN_TRANSCEIVER_ENABLED 1
#define CAN_TRANSCEIVER_TYPE 0 /* 0=TJA1050, 1=MCP2551 */
/* ============================================================================
* Board-Specific Functions
* ============================================================================ */
/* Board initialization function */
void board_init(void);
/* Board-specific GPIO initialization */
void board_gpio_init(void);
/* Board-specific clock initialization */
void board_clock_init(void);
/* Board-specific peripheral initialization */
void board_peripheral_init(void);
/* Board-specific CAN initialization */
void board_can_init(void);
/* Board-specific UART initialization */
void board_uart_init(void);
/* Board-specific SPI initialization */
void board_spi_init(void);
/* Board-specific I2C initialization */
void board_i2c_init(void);
/* Board-specific ADC initialization */
void board_adc_init(void);
/* Board-specific PWM initialization */
void board_pwm_init(void);
/* Board LED control */
void board_led_on(uint8_t led);
void board_led_off(uint8_t led);
void board_led_toggle(uint8_t led);
/* Board button reading */
bool board_button_read(uint8_t button);
/* Board-specific delay */
void board_delay_ms(uint32_t ms);
void board_delay_us(uint32_t us);
/* Board-specific watchdog */
void board_watchdog_init(void);
void board_watchdog_service(void);
/* Board temperature reading */
float board_get_temperature(void);
/* Board voltage reading */
float board_get_voltage(void);
#endif /* BOARD_CONFIG_H */
+198
View File
@@ -0,0 +1,198 @@
/**
* @file can_config.h
* @brief CAN bus configuration for automotive applications
*/
#ifndef CAN_CONFIG_H
#define CAN_CONFIG_H
#include <stdint.h>
/* ============================================================================
* CAN Hardware Configuration
* ============================================================================ */
/* Number of CAN controllers */
#define CAN_CONTROLLER_COUNT 2
/* CAN controller base addresses */
#define CAN0_BASE_ADDRESS 0x40006400U
#define CAN1_BASE_ADDRESS 0x40006800U
/* CAN controller interrupts */
#define CAN0_IRQ_NUMBER 19
#define CAN1_IRQ_NUMBER 20
/* CAN controller priorities */
#define CAN0_IRQ_PRIORITY 5
#define CAN1_IRQ_PRIORITY 5
/* ============================================================================
* CAN Baudrate Configuration
* ============================================================================ */
/* CAN baudrates */
#define CAN_BAUDRATE_125K 125000
#define CAN_BAUDRATE_250K 250000
#define CAN_BAUDRATE_500K 500000
#define CAN_BAUDRATE_1M 1000000
/* CAN FD baudrates */
#define CAN_FD_BAUDRATE_2M 2000000
#define CAN_FD_BAUDRATE_5M 5000000
#define CAN_FD_BAUDRATE_8M 8000000
/* Default CAN baudrate */
#define CAN_DEFAULT_BAUDRATE CAN_BAUDRATE_500K
/* CAN FD data baudrate */
#define CAN_FD_DATA_BAUDRATE CAN_FD_BAUDRATE_2M
/* ============================================================================
* CAN Frame Configuration
* ============================================================================ */
/* Enable CAN FD */
#define CAN_FD_ENABLED 1
/* Maximum CAN frame length */
#define CAN_MAX_FRAME_LENGTH 64
/* Enable automatic retransmission */
#define CAN_AUTO_RETRANSMIT 1
/* Maximum retransmission attempts */
#define CAN_MAX_RETRANSMIT 3
/* ============================================================================
* CAN Message IDs
* ============================================================================ */
/* OBD-II IDs */
#define CAN_ID_OBD_REQUEST 0x7DF
#define CAN_ID_OBD_RESPONSE 0x7E8
#define CAN_ID_OBD_RESPONSE_2 0x7E9
/* Diagnostic IDs */
#define CAN_ID_DIAG_REQUEST 0x700
#define CAN_ID_DIAG_RESPONSE 0x708
/* Network management IDs */
#define CAN_ID_NM_BASE 0x400
#define CAN_ID_NM_END 0x4FF
/* ============================================================================
* Application Message IDs
* ============================================================================ */
/* Engine control messages */
#define CAN_ID_ENGINE_DATA 0x100
#define CAN_ID_ENGINE_CONTROL 0x101
#define CAN_ID_ENGINE_STATUS 0x102
#define CAN_ID_ENGINE_FAULT 0x103
/* Transmission messages */
#define CAN_ID_TRANSMISSION_DATA 0x110
#define CAN_ID_TRANSMISSION_CONTROL 0x111
#define CAN_ID_GEAR_POSITION 0x112
/* Brake control messages */
#define CAN_ID_BRAKE_DATA 0x120
#define CAN_ID_BRAKE_CONTROL 0x121
#define CAN_ID_ABS_DATA 0x122
#define CAN_ID_WHEEL_SPEED 0x123
/* Steering messages */
#define CAN_ID_STEERING_ANGLE 0x130
#define CAN_ID_STEERING_TORQUE 0x131
#define CAN_ID_STEERING_CONTROL 0x132
/* Body control messages */
#define CAN_ID_BODY_CONTROL 0x140
#define CAN_ID_DOOR_STATUS 0x141
#define CAN_ID_LIGHT_STATUS 0x142
#define CAN_ID_WINDOW_CONTROL 0x143
/* Dashboard messages */
#define CAN_ID_SPEED 0x150
#define CAN_ID_RPM 0x151
#define CAN_ID_FUEL_LEVEL 0x152
#define CAN_ID_TEMPERATURE 0x153
/* Safety messages */
#define CAN_ID_AIRBAG_STATUS 0x160
#define CAN_ID_SEATBELT_STATUS 0x161
#define CAN_ID_CRASH_DETECTION 0x162
/* ============================================================================
* CAN Filter Configuration
* ============================================================================ */
typedef struct {
uint32_t filter_id;
uint32_t filter_mask;
bool is_extended;
uint8_t controller;
uint8_t fifo;
} CanFilterConfig_t;
/* Default CAN filters */
static const CanFilterConfig_t can_filters[] = {
/* Engine messages */
{.filter_id = 0x100, .filter_mask = 0x1F0, .is_extended = false, .controller = 0, .fifo = 0},
/* Transmission messages */
{.filter_id = 0x110, .filter_mask = 0x1F0, .is_extended = false, .controller = 0, .fifo = 0},
/* Brake messages */
{.filter_id = 0x120, .filter_mask = 0x1F0, .is_extended = false, .controller = 0, .fifo = 0},
/* Steering messages */
{.filter_id = 0x130, .filter_mask = 0x1F0, .is_extended = false, .controller = 0, .fifo = 0},
/* Body control messages */
{.filter_id = 0x140, .filter_mask = 0x1F0, .is_extended = false, .controller = 0, .fifo = 1},
/* Dashboard messages */
{.filter_id = 0x150, .filter_mask = 0x1F0, .is_extended = false, .controller = 0, .fifo = 1},
/* Safety messages */
{.filter_id = 0x160, .filter_mask = 0x1F0, .is_extended = false, .controller = 0, .fifo = 0},
/* OBD-II messages */
{.filter_id = 0x7DF, .filter_mask = 0x7FF, .is_extended = false, .controller = 1, .fifo = 0},
/* Diagnostic messages */
{.filter_id = 0x700, .filter_mask = 0x7F0, .is_extended = false, .controller = 1, .fifo = 1},
/* Network management */
{.filter_id = 0x400, .filter_mask = 0x700, .is_extended = false, .controller = 0, .fifo = 1}
};
#define CAN_FILTER_COUNT (sizeof(can_filters) / sizeof(CanFilterConfig_t))
/* ============================================================================
* CAN TP Configuration
* ============================================================================ */
/* CAN TP timeouts */
#define CAN_TP_N_AS_TIMEOUT 1000 /* ms */
#define CAN_TP_N_BS_TIMEOUT 1000 /* ms */
#define CAN_TP_N_CR_TIMEOUT 1000 /* ms */
/* CAN TP parameters */
#define CAN_TP_STMIN_DEFAULT 10 /* ms */
#define CAN_TP_BS_DEFAULT 8 /* frames */
#define CAN_TP_MAX_PAYLOAD 4096 /* bytes */
/* ============================================================================
* CAN NM Configuration
* ============================================================================ */
/* CAN NM parameters */
#define CAN_NM_TIMEOUT 2000 /* ms */
#define CAN_NM_REPEAT_TIME 500 /* ms */
#define CAN_NM_WAIT_BUS_SLEEP 2000 /* ms */
/* ============================================================================
* CAN Statistics
* ============================================================================ */
/* Enable CAN statistics collection */
#define CAN_STATS_ENABLED 1
/* Statistics buffer size */
#define CAN_STATS_BUFFER_SIZE 100
#endif /* CAN_CONFIG_H */
+266
View File
@@ -0,0 +1,266 @@
/**
* @file kernel_config.h
* @brief Kernel configuration for Automotive RTOS
*/
#ifndef KERNEL_CONFIG_H
#define KERNEL_CONFIG_H
/* ============================================================================
* Kernel Version Information
* ============================================================================ */
#define KERNEL_VERSION_MAJOR 1
#define KERNEL_VERSION_MINOR 0
#define KERNEL_VERSION_PATCH 0
#define KERNEL_VERSION_STRING "1.0.0"
/* ============================================================================
* Basic Kernel Configuration
* ============================================================================ */
/* Maximum number of tasks */
#define MAX_TASKS 32
/* Maximum priority levels (0 = highest, 15 = lowest) */
#define MAX_PRIORITY_LEVELS 16
/* Idle task priority (lowest) */
#define IDLE_TASK_PRIORITY (MAX_PRIORITY_LEVELS - 1)
/* Maximum task name length */
#define MAX_TASK_NAME_LENGTH 16
/* System tick rate in Hz */
#define TICK_RATE_HZ 1000
/* Tick period in milliseconds */
#define TICK_PERIOD_MS (1000 / TICK_RATE_HZ)
/* ============================================================================
* Scheduler Configuration
* ============================================================================ */
/* Scheduler type */
#define SCHEDULER_TYPE SCHEDULER_PRIORITY_PREEMPTIVE
/* Enable round-robin scheduling for same priority tasks */
#define ENABLE_ROUND_ROBIN 1
/* Round-robin time slice in ticks */
#define ROUND_ROBIN_TIME_SLICE 10
/* Enable deadline monitoring */
#define ENABLE_DEADLINE_MONITORING 1
/* Maximum allowed deadline misses before fault */
#define MAX_DEADLINE_MISSES 10
/* ============================================================================
* Synchronization Primitives
* ============================================================================ */
/* Maximum number of semaphores */
#define MAX_SEMAPHORES 32
/* Maximum number of mutexes */
#define MAX_MUTEXES 16
/* Maximum number of message queues */
#define MAX_QUEUES 16
/* Maximum queue size */
#define MAX_QUEUE_SIZE 256
/* Maximum number of event groups */
#define MAX_EVENT_GROUPS 8
/* Maximum number of software timers */
#define MAX_TIMERS 16
/* ============================================================================
* Memory Management
* ============================================================================ */
/* Enable memory protection */
#define ENABLE_MEMORY_PROTECTION 1
/* Enable stack overflow detection */
#define ENABLE_STACK_CHECK 1
/* Stack fill pattern for overflow detection */
#define STACK_FILL_PATTERN 0xA5A5A5A5
/* Default task stack size */
#define DEFAULT_TASK_STACK_SIZE 1024
/* Minimum task stack size */
#define MIN_TASK_STACK_SIZE 256
/* Idle task stack size */
#define IDLE_TASK_STACK_SIZE 512
/* ISR stack size */
#define ISR_STACK_SIZE 2048
/* Heap size for dynamic allocation */
#define HEAP_SIZE 65536
/* Enable heap usage tracking */
#define ENABLE_HEAP_TRACKING 1
/* ============================================================================
* Interrupt Management
* ============================================================================ */
/* Maximum number of ISR handlers */
#define MAX_ISR_HANDLERS 128
/* Maximum interrupt nesting level */
#define MAX_INTERRUPT_NESTING 8
/* Kernel interrupt priority (highest) */
#define KERNEL_INTERRUPT_PRIORITY 0
/* System call interrupt priority */
#define SYSCALL_INTERRUPT_PRIORITY 1
/* PendSV interrupt priority (lowest) */
#define PENDSV_INTERRUPT_PRIORITY (MAX_PRIORITY_LEVELS - 1)
/* SysTick interrupt priority */
#define SYSTICK_INTERRUPT_PRIORITY (MAX_PRIORITY_LEVELS - 1)
/* ============================================================================
* Fault Handling
* ============================================================================ */
/* Enable fault handlers */
#define ENABLE_FAULT_HANDLERS 1
/* Enable hard fault handler */
#define ENABLE_HARD_FAULT_HANDLER 1
/* Enable bus fault handler */
#define ENABLE_BUS_FAULT_HANDLER 1
/* Enable usage fault handler */
#define ENABLE_USAGE_FAULT_HANDLER 1
/* Enable memory management fault handler */
#define ENABLE_MEM_FAULT_HANDLER 1
/* Maximum number of fault records */
#define MAX_FAULT_RECORDS 16
/* ============================================================================
* Debug and Trace
* ============================================================================ */
/* Enable debug output */
#define ENABLE_DEBUG_OUTPUT 1
/* Debug level (0=off, 1=error, 2=warning, 3=info, 4=debug) */
#define DEBUG_LEVEL 3
/* Enable trace functionality */
#define ENABLE_TRACE 0
/* Trace buffer size */
#define TRACE_BUFFER_SIZE 4096
/* Enable assertions */
#define ENABLE_ASSERT 1
/* Enable runtime statistics */
#define ENABLE_RUNTIME_STATS 1
/* ============================================================================
* Power Management
* ============================================================================ */
/* Enable power management */
#define ENABLE_POWER_MANAGEMENT 1
/* Enable sleep modes */
#define ENABLE_SLEEP_MODE 1
/* Enable deep sleep modes */
#define ENABLE_DEEP_SLEEP 0
/* Idle task uses WFI */
#define IDLE_TASK_USES_WFI 1
/* ============================================================================
* Safety Features
* ============================================================================ */
/* Enable watchdog integration */
#define ENABLE_WATCHDOG 1
/* Watchdog timeout in milliseconds */
#define WATCHDOG_TIMEOUT_MS 100
/* Enable task supervision */
#define ENABLE_TASK_SUPERVISION 1
/* Enable E2E protection */
#define ENABLE_E2E_PROTECTION 1
/* Enable memory ECC */
#define ENABLE_MEMORY_ECC 1
/* Enable clock monitoring */
#define ENABLE_CLOCK_MONITORING 1
/* Enable temperature monitoring */
#define ENABLE_TEMP_MONITORING 1
/* ============================================================================
* Communication
* ============================================================================ */
/* Enable CAN support */
#define ENABLE_CAN 1
/* Enable LIN support */
#define ENABLE_LIN 0
/* Enable FlexRay support */
#define ENABLE_FLEXRAY 0
/* Enable Ethernet support */
#define ENABLE_ETHERNET 0
/* ============================================================================
* Diagnostics
* ============================================================================ */
/* Enable UDS support */
#define ENABLE_UDS 1
/* Enable OBD-II support */
#define ENABLE_OBD_II 1
/* Enable DTC management */
#define ENABLE_DTC_MANAGEMENT 1
/* Maximum number of DTCs */
#define MAX_DTC_COUNT 100
/* ============================================================================
* Configuration Validation
* ============================================================================ */
#if MAX_TASKS > 255
#error "MAX_TASKS must be less than 256"
#endif
#if MAX_PRIORITY_LEVELS > 32
#error "MAX_PRIORITY_LEVELS must be less than 33"
#endif
#if TICK_RATE_HZ < 100 || TICK_RATE_HZ > 10000
#error "TICK_RATE_HZ must be between 100 and 10000"
#endif
#endif /* KERNEL_CONFIG_H */
+220
View File
@@ -0,0 +1,220 @@
/**
* @file mcu_config.h
* @brief MCU-specific configuration
*/
#ifndef MCU_CONFIG_H
#define MCU_CONFIG_H
/* ============================================================================
* MCU Selection
* ============================================================================ */
/* Select target MCU */
#define MCU_STM32F407VG 1
#define MCU_NXP_S32K144 0
#define MCU_INFINEON_TC397 0
#if (MCU_STM32F407VG + MCU_NXP_S32K144 + MCU_INFINEON_TC397) != 1
#error "Exactly one MCU must be selected"
#endif
/* ============================================================================
* Clock Configuration
* ============================================================================ */
#if MCU_STM32F407VG
/* STM32F407VG clock configuration */
#define HSE_VALUE 8000000U /* External crystal */
#define HSI_VALUE 16000000U /* Internal oscillator */
#define LSE_VALUE 32768U /* Low speed external */
#define LSI_VALUE 32000U /* Low speed internal */
#define SYSTEM_CLOCK 168000000U /* 168 MHz */
#define AHB_CLOCK 168000000U /* 168 MHz */
#define APB1_CLOCK 42000000U /* 42 MHz */
#define APB2_CLOCK 84000000U /* 84 MHz */
/* PLL configuration */
#define PLL_M 8
#define PLL_N 336
#define PLL_P 2
#define PLL_Q 7
#elif MCU_NXP_S32K144
/* NXP S32K144 clock configuration */
#define SOSC_FREQUENCY 8000000U /* System oscillator */
#define SPLL_FREQUENCY 160000000U /* System PLL */
#define FIRC_FREQUENCY 48000000U /* Fast IRC */
#define SIRC_FREQUENCY 8000000U /* Slow IRC */
#define SYSTEM_CLOCK 160000000U /* 160 MHz */
#define BUS_CLOCK 40000000U /* 40 MHz */
#define FLASH_CLOCK 20000000U /* 20 MHz */
/* PLL configuration */
#define PLL_MULT 20
#define PLL_DIV 1
#elif MCU_INFINEON_TC397
/* Infineon TC397 clock configuration */
#define F_OSC 20000000U /* External oscillator */
#define F_PLL 300000000U /* PLL frequency */
#define SYSTEM_CLOCK 300000000U /* 300 MHz */
#define PERIPHERAL_CLOCK 150000000U /* 150 MHz */
#define STM_CLOCK 100000000U /* 100 MHz */
/* PLL configuration */
#define PLL_N 30
#define PLL_P 2
#define PLL_K2 1
#endif
/* ============================================================================
* Peripheral Configuration
* ============================================================================ */
#if MCU_STM32F407VG
/* STM32F407VG peripherals */
#define GPIO_PORT_COUNT 6
#define UART_COUNT 6
#define SPI_COUNT 3
#define I2C_COUNT 3
#define CAN_COUNT 2
#define ADC_COUNT 3
#define TIMER_COUNT 14
#define DMA_STREAM_COUNT 16
/* GPIO ports */
#define GPIOA_ENABLE 1
#define GPIOB_ENABLE 1
#define GPIOC_ENABLE 1
#define GPIOD_ENABLE 1
#define GPIOE_ENABLE 1
#define GPIOF_ENABLE 0
#define GPIOG_ENABLE 0
/* UART configuration */
#define UART1_ENABLE 1
#define UART2_ENABLE 1
#define UART3_ENABLE 0
#define UART4_ENABLE 0
#define UART5_ENABLE 0
#define UART6_ENABLE 0
/* SPI configuration */
#define SPI1_ENABLE 1
#define SPI2_ENABLE 1
#define SPI3_ENABLE 0
/* I2C configuration */
#define I2C1_ENABLE 1
#define I2C2_ENABLE 0
#define I2C3_ENABLE 0
/* CAN configuration */
#define CAN1_ENABLE 1
#define CAN2_ENABLE 1
/* ADC configuration */
#define ADC1_ENABLE 1
#define ADC2_ENABLE 0
#define ADC3_ENABLE 0
#elif MCU_NXP_S32K144
/* NXP S32K144 peripherals */
#define GPIO_PORT_COUNT 5
#define UART_COUNT 3
#define SPI_COUNT 3
#define I2C_COUNT 2
#define CAN_COUNT 3
#define ADC_COUNT 2
#define TIMER_COUNT 5
/* GPIO ports */
#define GPIOA_ENABLE 1
#define GPIOB_ENABLE 1
#define GPIOC_ENABLE 1
#define GPIOD_ENABLE 1
#define GPIOE_ENABLE 1
/* UART configuration */
#define UART0_ENABLE 1
#define UART1_ENABLE 1
#define UART2_ENABLE 0
/* SPI configuration */
#define SPI0_ENABLE 1
#define SPI1_ENABLE 1
#define SPI2_ENABLE 0
/* I2C configuration */
#define I2C0_ENABLE 1
#define I2C1_ENABLE 0
/* CAN configuration */
#define CAN0_ENABLE 1
#define CAN1_ENABLE 1
#define CAN2_ENABLE 0
/* ADC configuration */
#define ADC0_ENABLE 1
#define ADC1_ENABLE 1
#elif MCU_INFINEON_TC397
/* Infineon TC397 peripherals */
#define GPIO_PORT_COUNT 16
#define UART_COUNT 4
#define SPI_COUNT 4
#define I2C_COUNT 2
#define CAN_COUNT 4
#define ADC_COUNT 8
#define TIMER_COUNT 20
#endif
/* ============================================================================
* Interrupt Configuration
* ============================================================================ */
/* NVIC priority grouping */
#define NVIC_PRIORITY_GROUPING 4 /* 4 bits preemption, 0 bits sub-priority */
/* Maximum interrupt priority */
#define MAX_INTERRUPT_PRIORITY 15
/* ============================================================================
* Power Configuration
* ============================================================================ */
/* Voltage monitoring */
#define ENABLE_VOLTAGE_MONITORING 1
#define VOLTAGE_MONITOR_THRESHOLD 2.7f /* Volts */
/* Temperature monitoring */
#define ENABLE_TEMP_MONITORING 1
#define TEMP_MONITOR_THRESHOLD 125 /* °C */
/* Brown-out reset */
#define ENABLE_BROWN_OUT_RESET 1
#define BROWN_OUT_THRESHOLD 2.7f /* Volts */
/* ============================================================================
* Safety Configuration
* ============================================================================ */
/* Watchdog */
#define WATCHDOG_ENABLED 1
#define WATCHDOG_TIMEOUT 100 /* ms */
#define WATCHDOG_WINDOW 50 /* ms */
/* Clock security system */
#define ENABLE_CLOCK_SECURITY 1
/* Memory protection */
#define ENABLE_MPU 1
/* ECC */
#define ENABLE_ECC 1
#endif /* MCU_CONFIG_H */
+211
View File
@@ -0,0 +1,211 @@
/**
* @file memory_config.h
* @brief Memory configuration for automotive RTOS
*/
#ifndef MEMORY_CONFIG_H
#define MEMORY_CONFIG_H
#include <stdint.h>
/* ============================================================================
* Memory Map Configuration
* ============================================================================ */
/* Flash memory configuration */
#define FLASH_BASE_ADDRESS 0x08000000U
#define FLASH_SIZE 0x00100000U /* 1 MB */
#define FLASH_PAGE_SIZE 0x00002000U /* 8 KB */
#define FLASH_SECTOR_SIZE 0x00010000U /* 64 KB */
/* RAM memory configuration */
#define RAM_BASE_ADDRESS 0x20000000U
#define RAM_SIZE 0x00020000U /* 128 KB */
/* CCM RAM (Core Coupled Memory) */
#define CCM_RAM_BASE_ADDRESS 0x10000000U
#define CCM_RAM_SIZE 0x00010000U /* 64 KB */
/* External RAM configuration */
#define EXT_RAM_BASE_ADDRESS 0x60000000U
#define EXT_RAM_SIZE 0x00800000U /* 8 MB */
/* ============================================================================
* Memory Regions
* ============================================================================ */
/* Kernel memory region */
#define KERNEL_MEMORY_START FLASH_BASE_ADDRESS
#define KERNEL_MEMORY_SIZE 0x00040000U /* 256 KB */
/* Application memory region */
#define APP_MEMORY_START (KERNEL_MEMORY_START + KERNEL_MEMORY_SIZE)
#define APP_MEMORY_SIZE 0x00080000U /* 512 KB */
/* Calibration data region */
#define CALIBRATION_MEMORY_START (APP_MEMORY_START + APP_MEMORY_SIZE)
#define CALIBRATION_MEMORY_SIZE 0x00020000U /* 128 KB */
/* Bootloader region */
#define BOOTLOADER_MEMORY_START FLASH_BASE_ADDRESS
#define BOOTLOADER_MEMORY_SIZE 0x00010000U /* 64 KB */
/* ============================================================================
* Stack Configuration
* ============================================================================ */
/* Main stack (MSP) */
#define MAIN_STACK_SIZE 0x00001000U /* 4 KB */
/* Process stack (PSP) */
#define PROCESS_STACK_SIZE 0x00000800U /* 2 KB */
/* ISR stack */
#define ISR_STACK_SIZE 0x00000800U /* 2 KB */
/* Exception stack */
#define EXCEPTION_STACK_SIZE 0x00000400U /* 1 KB */
/* ============================================================================
* Heap Configuration
* ============================================================================ */
/* Heap region */
#define HEAP_START (RAM_BASE_ADDRESS + 0x00010000U)
#define HEAP_SIZE 0x00010000U /* 64 KB */
/* Heap alignment */
#define HEAP_ALIGNMENT 8
/* Minimum heap block size */
#define HEAP_MIN_BLOCK_SIZE 16
/* Enable heap poisoning */
#define ENABLE_HEAP_POISONING 1
/* Heap poison value */
#define HEAP_POISON_VALUE 0xDEADBEEF
/* ============================================================================
* Memory Protection Units (MPU)
* ============================================================================ */
/* Number of MPU regions */
#define MPU_REGION_COUNT 8
/* MPU region definitions */
typedef struct {
uint32_t base_address;
uint32_t size;
uint8_t permissions;
bool executable;
bool cacheable;
bool bufferable;
} MpuRegionConfig_t;
/* Default MPU configuration */
static const MpuRegionConfig_t mpu_regions[] = {
/* Kernel code region (read-only, executable) */
{
.base_address = KERNEL_MEMORY_START,
.size = KERNEL_MEMORY_SIZE,
.permissions = 0x05, /* Read-only */
.executable = true,
.cacheable = true,
.bufferable = false
},
/* Application code region (read-only, executable) */
{
.base_address = APP_MEMORY_START,
.size = APP_MEMORY_SIZE,
.permissions = 0x05, /* Read-only */
.executable = true,
.cacheable = true,
.bufferable = false
},
/* RAM region (read-write, non-executable) */
{
.base_address = RAM_BASE_ADDRESS,
.size = RAM_SIZE,
.permissions = 0x03, /* Read-write */
.executable = false,
.cacheable = true,
.bufferable = true
},
/* Peripheral region (read-write, non-executable) */
{
.base_address = 0x40000000U,
.size = 0x10000000U, /* 256 MB */
.permissions = 0x03, /* Read-write */
.executable = false,
.cacheable = false,
.bufferable = true
},
/* External memory region */
{
.base_address = 0x60000000U,
.size = 0x10000000U, /* 256 MB */
.permissions = 0x03, /* Read-write */
.executable = false,
.cacheable = true,
.bufferable = true
}
};
#define MPU_REGION_COUNT_CONFIGURED (sizeof(mpu_regions) / sizeof(MpuRegionConfig_t))
/* ============================================================================
* Memory Pools
* ============================================================================ */
/* Memory pool configurations */
#define MEMORY_POOL_COUNT 4
typedef struct {
uint32_t block_size;
uint32_t block_count;
uint32_t total_size;
} MemoryPoolConfig_t;
static const MemoryPoolConfig_t memory_pools[MEMORY_POOL_COUNT] = {
{.block_size = 32, .block_count = 64, .total_size = 2048},
{.block_size = 64, .block_count = 64, .total_size = 4096},
{.block_size = 128, .block_count = 32, .total_size = 4096},
{.block_size = 256, .block_count = 16, .total_size = 4096}
};
/* ============================================================================
* DMA Configuration
* ============================================================================ */
/* DMA channels */
#define DMA_CHANNEL_COUNT 8
/* DMA buffer sizes */
#define DMA_BUFFER_SIZE_CAN 512
#define DMA_BUFFER_SIZE_UART 256
#define DMA_BUFFER_SIZE_SPI 1024
#define DMA_BUFFER_SIZE_ADC 512
/* DMA priorities */
#define DMA_PRIORITY_LOW 0
#define DMA_PRIORITY_MEDIUM 1
#define DMA_PRIORITY_HIGH 2
#define DMA_PRIORITY_VERY_HIGH 3
/* ============================================================================
* ECC Configuration
* ============================================================================ */
/* Enable ECC */
#define ENABLE_ECC 1
/* ECC protected regions */
#define ECC_FLASH_ENABLED 1
#define ECC_RAM_ENABLED 1
/* ECC error handling */
#define ECC_SINGLE_ERROR_CORRECT 1
#define ECC_DOUBLE_ERROR_DETECT 1
#endif /* MEMORY_CONFIG_H */
+191
View File
@@ -0,0 +1,191 @@
/**
* @file task_config.h
* @brief Task configuration for automotive applications
*/
#ifndef TASK_CONFIG_H
#define TASK_CONFIG_H
#include "kernel_config.h"
/* ============================================================================
* Task Priority Definitions
* ============================================================================ */
/* Critical safety tasks (highest priority) */
#define TASK_PRIORITY_SAFETY_CRITICAL 0
#define TASK_PRIORITY_ENGINE_CONTROL 1
#define TASK_PRIORITY_BRAKE_CONTROL 1
#define TASK_PRIORITY_ABS_CONTROL 2
#define TASK_PRIORITY_AIRBAG_CONTROL 2
/* Real-time control tasks */
#define TASK_PRIORITY_FUEL_INJECTION 3
#define TASK_PRIORITY_IGNITION_CONTROL 3
#define TASK_PRIORITY_TRANSMISSION 4
#define TASK_PRIORITY_STEERING_CONTROL 4
/* Communication tasks */
#define TASK_PRIORITY_CAN_COMM 5
#define TASK_PRIORITY_LIN_COMM 6
#define TASK_PRIORITY_DIAGNOSTICS 6
/* Sensor processing tasks */
#define TASK_PRIORITY_SENSOR_READING 7
#define TASK_PRIORITY_SENSOR_FUSION 7
#define TASK_PRIORITY_DATA_LOGGING 8
/* Body control tasks */
#define TASK_PRIORITY_BODY_CONTROL 8
#define TASK_PRIORITY_DOOR_CONTROL 9
#define TASK_PRIORITY_LIGHTING_CONTROL 9
/* User interface tasks */
#define TASK_PRIORITY_DISPLAY 10
#define TASK_PRIORITY_GAUGE_CONTROL 10
#define TASK_PRIORITY_INFOTAINMENT 11
/* Background tasks (lowest priority) */
#define TASK_PRIORITY_DIAGNOSTIC_MONITOR 12
#define TASK_PRIORITY_MAINTENANCE 13
#define TASK_PRIORITY_IDLE IDLE_TASK_PRIORITY
/* ============================================================================
* Task Period Definitions (in milliseconds)
* ============================================================================ */
/* Safety-critical periods */
#define TASK_PERIOD_AIRBAG_CONTROL 1
#define TASK_PERIOD_ABS_CONTROL 1
#define TASK_PERIOD_ENGINE_CONTROL 1
/* Control loop periods */
#define TASK_PERIOD_FUEL_INJECTION 5
#define TASK_PERIOD_IGNITION_CONTROL 5
#define TASK_PERIOD_BRAKE_CONTROL 5
#define TASK_PERIOD_STEERING_CONTROL 5
/* Communication periods */
#define TASK_PERIOD_CAN_COMM 10
#define TASK_PERIOD_LIN_COMM 20
#define TASK_PERIOD_DIAGNOSTICS 50
/* Sensor periods */
#define TASK_PERIOD_SENSOR_READING 2
#define TASK_PERIOD_SENSOR_FUSION 10
#define TASK_PERIOD_DATA_LOGGING 100
/* Body control periods */
#define TASK_PERIOD_BODY_CONTROL 50
#define TASK_PERIOD_DOOR_CONTROL 100
#define TASK_PERIOD_LIGHTING_CONTROL 100
/* Display periods */
#define TASK_PERIOD_DISPLAY 50
#define TASK_PERIOD_GAUGE_CONTROL 10
#define TASK_PERIOD_INFOTAINMENT 100
/* Background periods */
#define TASK_PERIOD_DIAGNOSTIC_MONITOR 500
#define TASK_PERIOD_MAINTENANCE 1000
/* ============================================================================
* Task Stack Sizes (in bytes)
* ============================================================================ */
/* Safety-critical task stacks */
#define TASK_STACK_AIRBAG_CONTROL 2048
#define TASK_STACK_ABS_CONTROL 2048
#define TASK_STACK_ENGINE_CONTROL 2048
/* Control task stacks */
#define TASK_STACK_FUEL_INJECTION 1024
#define TASK_STACK_IGNITION_CONTROL 1024
#define TASK_STACK_BRAKE_CONTROL 1024
#define TASK_STACK_STEERING_CONTROL 1024
/* Communication task stacks */
#define TASK_STACK_CAN_COMM 2048
#define TASK_STACK_LIN_COMM 1024
#define TASK_STACK_DIAGNOSTICS 2048
/* Sensor task stacks */
#define TASK_STACK_SENSOR_READING 1024
#define TASK_STACK_SENSOR_FUSION 2048
#define TASK_STACK_DATA_LOGGING 4096
/* Body control task stacks */
#define TASK_STACK_BODY_CONTROL 1024
#define TASK_STACK_DOOR_CONTROL 1024
#define TASK_STACK_LIGHTING_CONTROL 1024
/* Display task stacks */
#define TASK_STACK_DISPLAY 4096
#define TASK_STACK_GAUGE_CONTROL 1024
#define TASK_STACK_INFOTAINMENT 8192
/* Background task stacks */
#define TASK_STACK_DIAGNOSTIC_MONITOR 2048
#define TASK_STACK_MAINTENANCE 1024
/* ============================================================================
* Task Configuration Table
* ============================================================================ */
typedef struct {
const char* name;
uint8_t priority;
uint16_t period_ms;
uint32_t stack_size;
uint32_t deadline_ms;
bool is_periodic;
bool is_critical;
} TaskConfigEntry_t;
/* Task configuration table */
static const TaskConfigEntry_t task_config_table[] = {
/* Name Priority Period Stack Deadline Periodic Critical */
{"Airbag Control", 0, 1, 2048, 2, true, true},
{"ABS Control", 2, 1, 2048, 2, true, true},
{"Engine Control", 1, 1, 2048, 2, true, true},
{"Brake Control", 1, 5, 1024, 10, true, true},
{"Fuel Injection", 3, 5, 1024, 10, true, false},
{"Ignition Control", 3, 5, 1024, 10, true, false},
{"Steering Control", 4, 5, 1024, 10, true, false},
{"Transmission Control", 4, 10, 2048, 20, true, false},
{"CAN Communication", 5, 10, 2048, 20, true, false},
{"LIN Communication", 6, 20, 1024, 40, true, false},
{"Diagnostics", 6, 50, 2048, 100, true, false},
{"Sensor Reading", 7, 2, 1024, 4, true, false},
{"Sensor Fusion", 7, 10, 2048, 20, true, false},
{"Data Logging", 8, 100, 4096, 200, true, false},
{"Body Control", 8, 50, 1024, 100, true, false},
{"Door Control", 9, 100, 1024, 200, true, false},
{"Lighting Control", 9, 100, 1024, 200, true, false},
{"Display", 10, 50, 4096, 100, true, false},
{"Gauge Control", 10, 10, 1024, 20, true, false},
{"Infotainment", 11, 100, 8192, 200, true, false},
{"Diagnostic Monitor", 12, 500, 2048, 1000, true, false},
{"Maintenance", 13, 1000, 1024, 2000, true, false},
};
/* Number of tasks in configuration table */
#define TASK_CONFIG_COUNT (sizeof(task_config_table) / sizeof(TaskConfigEntry_t))
/* ============================================================================
* Task Supervision Configuration
* ============================================================================ */
/* Enable task supervision */
#define TASK_SUPERVISION_ENABLED 1
/* Default task timeout in milliseconds */
#define TASK_DEFAULT_TIMEOUT_MS 1000
/* Maximum alive counter before reset */
#define TASK_MAX_ALIVE_COUNT 5
/* Task supervision check period */
#define TASK_SUPERVISION_PERIOD_MS 100
#endif /* TASK_CONFIG_H */
+243
View File
@@ -0,0 +1,243 @@
automotive_rtos/
├── README.md
├── LICENSE
├── Makefile
├── CMakeLists.txt
├── docs/
│ ├── architecture/
│ │ ├── system_architecture.md
│ │ ├── task_model.md
│ │ └── memory_map.md
│ ├── api/
│ │ ├── kernel_api.md
│ │ └── driver_api.md
│ ├── safety/
│ │ ├── safety_manual.md
│ │ ├── hazard_analysis.md
│ │ └── iso26262_compliance.md
│ └── user_guide/
│ ├── getting_started.md
│ └── configuration_guide.md
├── kernel/
│ ├── include/
│ │ ├── kernel.h
│ │ ├── task.h
│ │ ├── scheduler.h
│ │ ├── semaphore.h
│ │ ├── mutex.h
│ │ ├── queue.h
│ │ ├── timer.h
│ │ └── isr.h
│ │
│ ├── src/
│ │ ├── kernel_init.c
│ │ ├── scheduler.c
│ │ ├── task.c
│ │ ├── semaphore.c
│ │ ├── mutex.c
│ │ ├── queue.c
│ │ ├── timer.c
│ │ └── fault_handler.c
│ │
│ └── arch/
│ ├── arm/
│ │ ├── cortex-m0/
│ │ │ ├── port.c
│ │ │ ├── port_asm.s
│ │ │ └── portmacro.h
│ │ ├── cortex-m3/
│ │ │ ├── port.c
│ │ │ ├── port_asm.s
│ │ │ └── portmacro.h
│ │ └── cortex-m4/
│ │ ├── port.c
│ │ ├── port_asm.s
│ │ └── portmacro.h
│ │
│ └── riscv/
│ └── rv32/
│ ├── port.c
│ └── portmacro.h
├── drivers/
│ ├── include/
│ │ ├── can_driver.h
│ │ ├── uart_driver.h
│ │ ├── spi_driver.h
│ │ ├── i2c_driver.h
│ │ ├── gpio_driver.h
│ │ ├── adc_driver.h
│ │ └── pwm_driver.h
│ │
│ ├── src/
│ │ ├── can_driver.c
│ │ ├── uart_driver.c
│ │ ├── spi_driver.c
│ │ ├── i2c_driver.c
│ │ ├── gpio_driver.c
│ │ ├── adc_driver.c
│ │ └── pwm_driver.c
│ │
│ └── mcu_specific/
│ ├── stm32f4/
│ │ ├── stm32f4xx_hal.c
│ │ └── stm32f4xx_config.h
│ ├── nxp_s32k/
│ │ ├── s32k14x_hal.c
│ │ └── s32k14x_config.h
│ └── infineon_tricore/
│ ├── tc3xx_hal.c
│ └── tc3xx_config.h
├── middleware/
│ ├── can_stack/
│ │ ├── include/
│ │ │ ├── can_tp.h
│ │ │ ├── can_nm.h
│ │ │ └── uds.h
│ │ └── src/
│ │ ├── can_tp.c
│ │ ├── can_nm.c
│ │ └── uds.c
│ │
│ ├── diagnostics/
│ │ ├── include/
│ │ │ ├── dtc_manager.h
│ │ │ └── obd_ii.h
│ │ └── src/
│ │ ├── dtc_manager.c
│ │ └── obd_ii.c
│ │
│ └── safety/
│ ├── watchdog_manager.c
│ ├── memory_protection.c
│ └── e2e_protection.c
├── applications/
│ ├── engine_control/
│ │ ├── include/
│ │ │ ├── engine_control.h
│ │ │ └── engine_parameters.h
│ │ └── src/
│ │ ├── engine_control_task.c
│ │ ├── fuel_injection.c
│ │ └── ignition_control.c
│ │
│ ├── brake_control/
│ │ ├── include/
│ │ │ └── brake_control.h
│ │ └── src/
│ │ ├── brake_task.c
│ │ └── abs_control.c
│ │
│ ├── body_control/
│ │ ├── include/
│ │ └── src/
│ │ ├── body_control_task.c
│ │ ├── door_control.c
│ │ └── lighting_control.c
│ │
│ └── dashboard/
│ ├── include/
│ └── src/
│ ├── display_task.c
│ └── gauge_control.c
├── config/
│ ├── kernel_config.h
│ ├── task_config.h
│ ├── memory_config.h
│ ├── can_config.h
│ ├── mcu_config.h
│ └── board_config.h
├── board/
│ ├── stm32f407_discovery/
│ │ ├── board_init.c
│ │ ├── board.h
│ │ └── linker_script.ld
│ │
│ ├── nxp_s32k144_evb/
│ │ ├── board_init.c
│ │ ├── board.h
│ │ └── linker_script.ld
│ │
│ └── custom_ecu/
│ ├── board_init.c
│ ├── board.h
│ └── linker_script.ld
├── tests/
│ ├── unit/
│ │ ├── test_scheduler.c
│ │ ├── test_task.c
│ │ ├── test_semaphore.c
│ │ ├── test_mutex.c
│ │ └── test_queue.c
│ │
│ ├── integration/
│ │ ├── test_can_communication.c
│ │ ├── test_timing.c
│ │ └── test_fault_handling.c
│ │
│ ├── system/
│ │ ├── test_full_system.c
│ │ └── test_stress.c
│ │
│ └── hardware/
│ ├── test_gpio.c
│ ├── test_adc.c
│ └── test_pwm.c
├── tools/
│ ├── build_scripts/
│ │ ├── build_all.sh
│ │ ├── build_target.sh
│ │ └── flash_target.sh
│ │
│ ├── analysis/
│ │ ├── stack_usage_analyzer.py
│ │ ├── timing_analyzer.py
│ │ └── misra_checker.sh
│ │
│ ├── debugging/
│ │ ├── gdb_init.gdb
│ │ └── trace_analyzer.py
│ │
│ └── configuration/
│ ├── config_generator.py
│ └── task_priority_calculator.py
├── third_party/
│ ├── unity/ # Unit testing framework
│ ├── cmock/ # Mock objects for testing
│ └── cmsis/ # ARM CMSIS headers
├── scripts/
│ ├── setup_environment.sh
│ ├── generate_docs.sh
│ ├── run_tests.sh
│ └── static_analysis.sh
├── .github/
│ ├── workflows/
│ │ ├── build.yml
│ │ ├── test.yml
│ │ └── static-analysis.yml
│ └── ISSUE_TEMPLATE/
│ ├── bug_report.md
│ └── feature_request.md
├── .vscode/
│ ├── launch.json
│ ├── tasks.json
│ └── settings.json
├── .gitignore
├── .gitattributes
├── CHANGELOG.md
├── CONTRIBUTING.md
└── SECURITY.md
+3
View File
@@ -0,0 +1,3 @@
# driver api
Placeholder documentation.
+3
View File
@@ -0,0 +1,3 @@
# kernel api
Placeholder documentation.
+3
View File
@@ -0,0 +1,3 @@
# memory map
Placeholder documentation.
+3
View File
@@ -0,0 +1,3 @@
# system architecture
Placeholder documentation.
+3
View File
@@ -0,0 +1,3 @@
# task model
Placeholder documentation.
+3
View File
@@ -0,0 +1,3 @@
# hazard analysis
Placeholder documentation.
+3
View File
@@ -0,0 +1,3 @@
# iso26262 compliance
Placeholder documentation.
+3
View File
@@ -0,0 +1,3 @@
# safety manual
Placeholder documentation.
+3
View File
@@ -0,0 +1,3 @@
# configuration guide
Placeholder documentation.
+3
View File
@@ -0,0 +1,3 @@
# getting started
Placeholder documentation.
+114
View File
@@ -0,0 +1,114 @@
/**
* @file adc_driver.h
* @brief ADC driver interface
*/
#ifndef ADC_DRIVER_H
#define ADC_DRIVER_H
#include <stdint.h>
#include <stdbool.h>
#include "kernel.h"
/* ADC Configuration Constants */
#define ADC_MAX_INSTANCES 3
#define ADC_MAX_CHANNELS 16
#define ADC_MAX_SEQUENCES 8
/* ADC Resolution */
typedef enum {
ADC_RESOLUTION_6BIT = 6,
ADC_RESOLUTION_8BIT = 8,
ADC_RESOLUTION_10BIT = 10,
ADC_RESOLUTION_12BIT = 12,
ADC_RESOLUTION_14BIT = 14,
ADC_RESOLUTION_16BIT = 16
} AdcResolution_t;
/* ADC Conversion Modes */
typedef enum {
ADC_MODE_SINGLE = 0,
ADC_MODE_CONTINUOUS = 1,
ADC_MODE_SCAN = 2,
ADC_MODE_DISCONTINUOUS = 3
} AdcConversionMode_t;
/* ADC Trigger Sources */
typedef enum {
ADC_TRIGGER_SOFTWARE = 0,
ADC_TRIGGER_TIMER = 1,
ADC_TRIGGER_EXTERNAL = 2
} AdcTriggerSource_t;
/* ADC Reference Voltage */
typedef enum {
ADC_REFERENCE_INTERNAL = 0,
ADC_REFERENCE_EXTERNAL = 1,
ADC_REFERENCE_VDD = 2
} AdcReference_t;
/* ADC Sampling Time */
typedef enum {
ADC_SAMPLING_1_5_CYCLES = 0,
ADC_SAMPLING_7_5_CYCLES = 1,
ADC_SAMPLING_13_5_CYCLES = 2,
ADC_SAMPLING_28_5_CYCLES = 3,
ADC_SAMPLING_41_5_CYCLES = 4,
ADC_SAMPLING_55_5_CYCLES = 5,
ADC_SAMPLING_71_5_CYCLES = 6,
ADC_SAMPLING_239_5_CYCLES = 7
} AdcSamplingTime_t;
/* ADC Callbacks */
typedef void (*AdcConversionCompleteCallback_t)(uint16_t* values, uint8_t count);
/* ADC Channel Configuration */
typedef struct {
uint8_t channel;
AdcSamplingTime_t sampling_time;
bool enable_watchdog;
uint16_t watchdog_high_threshold;
uint16_t watchdog_low_threshold;
} AdcChannelConfig_t;
/* ADC Configuration */
typedef struct {
AdcResolution_t resolution;
AdcConversionMode_t mode;
AdcTriggerSource_t trigger_source;
AdcReference_t reference;
bool enable_dma;
uint32_t conversion_frequency;
AdcChannelConfig_t channels[ADC_MAX_CHANNELS];
uint8_t channel_count;
AdcConversionCompleteCallback_t conversion_complete_callback;
} AdcConfig_t;
/* ADC Statistics */
typedef struct {
uint32_t conversions_completed;
uint32_t conversions_failed;
uint32_t watchdog_events;
uint32_t overrun_errors;
uint32_t dma_transfers;
uint32_t average_conversion_time_us;
} AdcStatistics_t;
/* ADC Driver Interface */
KernelStatus_t adc_init(uint8_t instance, AdcConfig_t* config);
KernelStatus_t adc_deinit(uint8_t instance);
KernelStatus_t adc_start_conversion(uint8_t instance);
KernelStatus_t adc_stop_conversion(uint8_t instance);
KernelStatus_t adc_read_channel(uint8_t instance, uint8_t channel, uint16_t* value,
uint32_t timeout_ms);
KernelStatus_t adc_read_channels(uint8_t instance, uint16_t* values, uint8_t count,
uint32_t timeout_ms);
KernelStatus_t adc_start_dma(uint8_t instance, uint16_t* buffer, uint16_t length);
KernelStatus_t adc_stop_dma(uint8_t instance);
KernelStatus_t adc_calibrate(uint8_t instance);
KernelStatus_t adc_get_statistics(uint8_t instance, AdcStatistics_t* stats);
float adc_convert_to_voltage(uint16_t adc_value, AdcResolution_t resolution,
float reference_voltage);
void adc_process_interrupt(uint8_t instance);
#endif /* ADC_DRIVER_H */
+120
View File
@@ -0,0 +1,120 @@
/**
* @file can_driver.h
* @brief CAN (Controller Area Network) driver interface
* @note Supports classical CAN and CAN FD
*/
#ifndef CAN_DRIVER_H
#define CAN_DRIVER_H
#include <stdint.h>
#include <stdbool.h>
#include "kernel.h"
/* CAN Configuration Constants */
#define CAN_MAX_MESSAGE_LENGTH 8 /* Classical CAN */
#define CAN_FD_MAX_MESSAGE_LENGTH 64 /* CAN FD */
#define CAN_MAX_FILTERS 32
#define CAN_MAX_TX_MAILBOXES 3
#define CAN_MAX_RX_FIFO_DEPTH 16
/* CAN Baudrates */
typedef enum {
CAN_BAUD_125K = 125000,
CAN_BAUD_250K = 250000,
CAN_BAUD_500K = 500000,
CAN_BAUD_1M = 1000000,
CAN_FD_BAUD_2M = 2000000,
CAN_FD_BAUD_5M = 5000000
} CanBaudrate_t;
/* CAN Message Types */
typedef enum {
CAN_FRAME_CLASSIC = 0,
CAN_FRAME_FD = 1,
CAN_FRAME_FD_BRS = 2 /* FD with Bit Rate Switch */
} CanFrameType_t;
/* CAN Frame Format */
typedef enum {
CAN_FORMAT_STANDARD = 0, /* 11-bit identifier */
CAN_FORMAT_EXTENDED = 1 /* 29-bit identifier */
} CanFrameFormat_t;
/* CAN Message ID */
typedef struct {
uint32_t id : 29;
CanFrameFormat_t format : 1;
bool is_remote : 1;
bool is_extended : 1;
} CanMessageId_t;
/* CAN Message Structure */
typedef struct {
CanMessageId_t id;
CanFrameType_t type;
uint8_t data[CAN_FD_MAX_MESSAGE_LENGTH];
uint8_t length;
uint32_t timestamp;
bool is_rx;
} CanMessage_t;
/* CAN Filter Configuration */
typedef struct {
uint32_t filter_id;
uint32_t filter_mask;
CanFrameFormat_t format;
bool enable;
} CanFilterConfig_t;
/* CAN Statistics */
typedef struct {
uint32_t tx_messages;
uint32_t rx_messages;
uint32_t tx_errors;
uint32_t rx_errors;
uint32_t bus_off_count;
uint32_t error_warning_count;
uint32_t error_passive_count;
uint32_t tx_overflow;
uint32_t rx_overflow;
} CanStatistics_t;
/* CAN Callbacks */
typedef void (*CanRxCallback_t)(const CanMessage_t* message);
typedef void (*CanTxCallback_t)(uint32_t mailbox, bool success);
typedef void (*CanErrorCallback_t)(uint32_t error_code);
/* CAN Configuration Structure */
typedef struct {
CanBaudrate_t nominal_baudrate;
CanBaudrate_t data_baudrate; /* For CAN FD */
CanFrameType_t frame_type;
bool enable_fd;
bool enable_automatic_retransmission;
CanFilterConfig_t filters[CAN_MAX_FILTERS];
uint8_t filter_count;
CanRxCallback_t rx_callback;
CanTxCallback_t tx_callback;
CanErrorCallback_t error_callback;
} CanConfig_t;
/* CAN Driver Interface */
KernelStatus_t can_init(CanConfig_t* config);
KernelStatus_t can_deinit(void);
KernelStatus_t can_send_message(const CanMessage_t* message, uint32_t timeout_ms);
KernelStatus_t can_receive_message(CanMessage_t* message, uint32_t timeout_ms);
KernelStatus_t can_configure_filter(const CanFilterConfig_t* filter);
KernelStatus_t can_set_baudrate(CanBaudrate_t baudrate);
KernelStatus_t can_get_statistics(CanStatistics_t* stats);
KernelStatus_t can_clear_statistics(void);
bool can_is_bus_off(void);
KernelStatus_t can_recover_bus_off(void);
void can_process_interrupt(void);
/* CAN FD Specific Functions */
KernelStatus_t can_fd_set_data_baudrate(CanBaudrate_t baudrate);
KernelStatus_t can_fd_set_transmit_delay(uint16_t delay_us);
bool can_fd_is_enabled(void);
#endif /* CAN_DRIVER_H */
+113
View File
@@ -0,0 +1,113 @@
/**
* @file gpio_driver.h
* @brief GPIO driver interface
*/
#ifndef GPIO_DRIVER_H
#define GPIO_DRIVER_H
#include <stdint.h>
#include <stdbool.h>
#include "kernel.h"
/* GPIO Configuration Constants */
#define GPIO_MAX_PORTS 8
#define GPIO_MAX_PINS_PER_PORT 16
#define GPIO_MAX_INTERRUPTS 32
/* GPIO Modes */
typedef enum {
GPIO_MODE_INPUT = 0,
GPIO_MODE_OUTPUT = 1,
GPIO_MODE_ALTERNATE = 2,
GPIO_MODE_ANALOG = 3
} GpioMode_t;
/* GPIO Output Types */
typedef enum {
GPIO_OUTPUT_PUSH_PULL = 0,
GPIO_OUTPUT_OPEN_DRAIN = 1
} GpioOutputType_t;
/* GPIO Pull Configuration */
typedef enum {
GPIO_PULL_NONE = 0,
GPIO_PULL_UP = 1,
GPIO_PULL_DOWN = 2
} GpioPull_t;
/* GPIO Speed */
typedef enum {
GPIO_SPEED_LOW = 0,
GPIO_SPEED_MEDIUM = 1,
GPIO_SPEED_HIGH = 2,
GPIO_SPEED_VERY_HIGH = 3
} GpioSpeed_t;
/* GPIO Alternate Functions */
typedef enum {
GPIO_AF0 = 0,
GPIO_AF1 = 1,
GPIO_AF2 = 2,
GPIO_AF3 = 3,
GPIO_AF4 = 4,
GPIO_AF5 = 5,
GPIO_AF6 = 6,
GPIO_AF7 = 7,
GPIO_AF8 = 8,
GPIO_AF9 = 9,
GPIO_AF10 = 10,
GPIO_AF11 = 11,
GPIO_AF12 = 12,
GPIO_AF13 = 13,
GPIO_AF14 = 14,
GPIO_AF15 = 15
} GpioAlternateFunction_t;
/* GPIO Interrupt Triggers */
typedef enum {
GPIO_INTERRUPT_NONE = 0,
GPIO_INTERRUPT_RISING = 1,
GPIO_INTERRUPT_FALLING = 2,
GPIO_INTERRUPT_BOTH = 3
} GpioInterruptTrigger_t;
/* GPIO Pin Configuration */
typedef struct {
uint8_t port;
uint8_t pin;
GpioMode_t mode;
GpioOutputType_t output_type;
GpioPull_t pull;
GpioSpeed_t speed;
GpioAlternateFunction_t alternate_function;
} GpioPinConfig_t;
/* GPIO Interrupt Configuration */
typedef struct {
uint8_t port;
uint8_t pin;
GpioInterruptTrigger_t trigger;
void (*callback)(uint8_t port, uint8_t pin);
} GpioInterruptConfig_t;
/* GPIO Driver Interface */
KernelStatus_t gpio_init(const GpioPinConfig_t* config);
KernelStatus_t gpio_deinit(uint8_t port, uint8_t pin);
KernelStatus_t gpio_set_mode(uint8_t port, uint8_t pin, GpioMode_t mode);
KernelStatus_t gpio_set_output_type(uint8_t port, uint8_t pin, GpioOutputType_t type);
KernelStatus_t gpio_set_pull(uint8_t port, uint8_t pin, GpioPull_t pull);
KernelStatus_t gpio_set_speed(uint8_t port, uint8_t pin, GpioSpeed_t speed);
KernelStatus_t gpio_set_alternate_function(uint8_t port, uint8_t pin,
GpioAlternateFunction_t af);
KernelStatus_t gpio_write(uint8_t port, uint8_t pin, bool value);
KernelStatus_t gpio_write_port(uint8_t port, uint16_t value);
bool gpio_read(uint8_t port, uint8_t pin);
uint16_t gpio_read_port(uint8_t port);
KernelStatus_t gpio_toggle(uint8_t port, uint8_t pin);
KernelStatus_t gpio_configure_interrupt(const GpioInterruptConfig_t* config);
KernelStatus_t gpio_enable_interrupt(uint8_t port, uint8_t pin);
KernelStatus_t gpio_disable_interrupt(uint8_t port, uint8_t pin);
void gpio_process_interrupt(uint8_t port);
#endif /* GPIO_DRIVER_H */
+101
View File
@@ -0,0 +1,101 @@
/**
* @file i2c_driver.h
* @brief I2C driver interface
*/
#ifndef I2C_DRIVER_H
#define I2C_DRIVER_H
#include <stdint.h>
#include <stdbool.h>
#include "kernel.h"
/* I2C Configuration Constants */
#define I2C_MAX_INSTANCES 4
#define I2C_MAX_BUFFER_SIZE 1024
#define I2C_MAX_TRANSFER_SIZE 255
/* I2C Speeds */
typedef enum {
I2C_SPEED_STANDARD = 100000, /* 100 kHz */
I2C_SPEED_FAST = 400000, /* 400 kHz */
I2C_SPEED_FAST_PLUS = 1000000, /* 1 MHz */
I2C_SPEED_HIGH = 3400000 /* 3.4 MHz */
} I2cSpeed_t;
/* I2C Addressing Mode */
typedef enum {
I2C_ADDRESSING_7BIT = 0,
I2C_ADDRESSING_10BIT = 1
} I2cAddressingMode_t;
/* I2C Transfer Direction */
typedef enum {
I2C_DIRECTION_WRITE = 0,
I2C_DIRECTION_READ = 1
} I2cDirection_t;
/* I2C Transfer Status */
typedef enum {
I2C_TRANSFER_COMPLETE = 0,
I2C_TRANSFER_ERROR = 1,
I2C_TRANSFER_NACK = 2,
I2C_TRANSFER_TIMEOUT = 3,
I2C_TRANSFER_ARBITRATION_LOST = 4,
I2C_TRANSFER_BUS_ERROR = 5
} I2cTransferStatus_t;
/* I2C Callbacks */
typedef void (*I2cTransferCompleteCallback_t)(I2cTransferStatus_t status, void* user_data);
/* I2C Configuration */
typedef struct {
I2cSpeed_t speed;
I2cAddressingMode_t addressing_mode;
uint16_t own_address;
bool enable_general_call;
bool enable_clock_stretching;
bool use_dma;
I2cTransferCompleteCallback_t transfer_complete_callback;
} I2cConfig_t;
/* I2C Message */
typedef struct {
uint16_t slave_address;
I2cDirection_t direction;
uint8_t* data;
uint16_t length;
bool generate_stop;
bool generate_restart;
} I2cMessage_t;
/* I2C Statistics */
typedef struct {
uint32_t transfers_completed;
uint32_t transfers_failed;
uint32_t nack_errors;
uint32_t arbitration_lost;
uint32_t bus_errors;
uint32_t timeout_errors;
uint32_t bytes_transferred;
} I2cStatistics_t;
/* I2C Driver Interface */
KernelStatus_t i2c_init(uint8_t instance, I2cConfig_t* config);
KernelStatus_t i2c_deinit(uint8_t instance);
KernelStatus_t i2c_transfer(uint8_t instance, const I2cMessage_t* message,
uint32_t timeout_ms);
KernelStatus_t i2c_transfer_async(uint8_t instance, const I2cMessage_t* message);
KernelStatus_t i2c_write(uint8_t instance, uint16_t slave_address,
const uint8_t* data, uint16_t length, uint32_t timeout_ms);
KernelStatus_t i2c_read(uint8_t instance, uint16_t slave_address,
uint8_t* data, uint16_t length, uint32_t timeout_ms);
KernelStatus_t i2c_write_read(uint8_t instance, uint16_t slave_address,
const uint8_t* tx_data, uint16_t tx_length,
uint8_t* rx_data, uint16_t rx_length,
uint32_t timeout_ms);
KernelStatus_t i2c_get_statistics(uint8_t instance, I2cStatistics_t* stats);
bool i2c_is_device_ready(uint8_t instance, uint16_t slave_address);
void i2c_process_interrupt(uint8_t instance);
#endif /* I2C_DRIVER_H */
+105
View File
@@ -0,0 +1,105 @@
/**
* @file pwm_driver.h
* @brief PWM driver interface
*/
#ifndef PWM_DRIVER_H
#define PWM_DRIVER_H
#include <stdint.h>
#include <stdbool.h>
#include "kernel.h"
/* PWM Configuration Constants */
#define PWM_MAX_INSTANCES 8
#define PWM_MAX_CHANNELS 4
#define PWM_MAX_DUTY_CYCLE 10000 /* 100.00% in 0.01% steps */
/* PWM Alignment Modes */
typedef enum {
PWM_ALIGNMENT_EDGE = 0,
PWM_ALIGNMENT_CENTER = 1
} PwmAlignment_t;
/* PWM Polarity */
typedef enum {
PWM_POLARITY_ACTIVE_HIGH = 0,
PWM_POLARITY_ACTIVE_LOW = 1
} PwmPolarity_t;
/* PWM Modes */
typedef enum {
PWM_MODE_NORMAL = 0,
PWM_MODE_COMPLEMENTARY = 1,
PWM_MODE_COMBINED = 2
} PwmMode_t;
/* PWM Dead Time */
typedef struct {
uint16_t rising_edge_delay_ns;
uint16_t falling_edge_delay_ns;
} PwmDeadTime_t;
/* PWM Fault Actions */
typedef enum {
PWM_FAULT_DISABLE = 0,
PWM_FAULT_ENABLE = 1,
PWM_FAULT_HIGH_Z = 2
} PwmFaultAction_t;
/* PWM Callbacks */
typedef void (*PwmPeriodElapsedCallback_t)(uint8_t instance);
typedef void (*PwmFaultCallback_t)(uint8_t instance, uint32_t fault_flags);
/* PWM Channel Configuration */
typedef struct {
uint8_t channel;
uint32_t duty_cycle; /* 0 to PWM_MAX_DUTY_CYCLE */
PwmPolarity_t polarity;
PwmMode_t mode;
PwmDeadTime_t dead_time;
} PwmChannelConfig_t;
/* PWM Configuration */
typedef struct {
uint32_t frequency_hz;
PwmAlignment_t alignment;
uint32_t period_ticks;
uint8_t prescaler;
PwmChannelConfig_t channels[PWM_MAX_CHANNELS];
uint8_t channel_count;
bool enable_fault_protection;
PwmFaultAction_t fault_action;
PwmPeriodElapsedCallback_t period_elapsed_callback;
PwmFaultCallback_t fault_callback;
} PwmConfig_t;
/* PWM Statistics */
typedef struct {
uint32_t period_elapsed_count;
uint32_t fault_events;
uint32_t duty_cycle_updates;
uint32_t overcurrent_events;
uint32_t overvoltage_events;
} PwmStatistics_t;
/* PWM Driver Interface */
KernelStatus_t pwm_init(uint8_t instance, PwmConfig_t* config);
KernelStatus_t pwm_deinit(uint8_t instance);
KernelStatus_t pwm_start(uint8_t instance);
KernelStatus_t pwm_stop(uint8_t instance);
KernelStatus_t pwm_set_duty_cycle(uint8_t instance, uint8_t channel, uint32_t duty_cycle);
KernelStatus_t pwm_set_frequency(uint8_t instance, uint32_t frequency_hz);
KernelStatus_t pwm_set_period(uint8_t instance, uint32_t period_ticks);
KernelStatus_t pwm_set_dead_time(uint8_t instance, uint8_t channel,
const PwmDeadTime_t* dead_time);
KernelStatus_t pwm_enable_channel(uint8_t instance, uint8_t channel);
KernelStatus_t pwm_disable_channel(uint8_t instance, uint8_t channel);
KernelStatus_t pwm_configure_fault(uint8_t instance, PwmFaultAction_t action);
KernelStatus_t pwm_clear_fault(uint8_t instance);
KernelStatus_t pwm_get_statistics(uint8_t instance, PwmStatistics_t* stats);
uint32_t pwm_get_duty_cycle(uint8_t instance, uint8_t channel);
uint32_t pwm_get_frequency(uint8_t instance);
void pwm_process_interrupt(uint8_t instance);
#endif /* PWM_DRIVER_H */
+109
View File
@@ -0,0 +1,109 @@
/**
* @file spi_driver.h
* @brief SPI driver interface
*/
#ifndef SPI_DRIVER_H
#define SPI_DRIVER_H
#include <stdint.h>
#include <stdbool.h>
#include "kernel.h"
/* SPI Configuration Constants */
#define SPI_MAX_INSTANCES 4
#define SPI_MAX_BUFFER_SIZE 4096
#define SPI_MAX_TRANSFER_SIZE 65535
/* SPI Modes */
typedef enum {
SPI_MODE_0 = 0, /* CPOL=0, CPHA=0 */
SPI_MODE_1 = 1, /* CPOL=0, CPHA=1 */
SPI_MODE_2 = 2, /* CPOL=1, CPHA=0 */
SPI_MODE_3 = 3 /* CPOL=1, CPHA=1 */
} SpiMode_t;
/* SPI Clock Speeds */
typedef enum {
SPI_CLOCK_1MHZ = 1000000,
SPI_CLOCK_2MHZ = 2000000,
SPI_CLOCK_4MHZ = 4000000,
SPI_CLOCK_8MHZ = 8000000,
SPI_CLOCK_16MHZ = 16000000,
SPI_CLOCK_32MHZ = 32000000
} SpiClockSpeed_t;
/* SPI Data Order */
typedef enum {
SPI_DATA_ORDER_MSB_FIRST = 0,
SPI_DATA_ORDER_LSB_FIRST = 1
} SpiDataOrder_t;
/* SPI Chip Select */
typedef enum {
SPI_CS_ACTIVE_LOW = 0,
SPI_CS_ACTIVE_HIGH = 1
} SpiChipSelectPolarity_t;
/* SPI Transfer Status */
typedef enum {
SPI_TRANSFER_COMPLETE = 0,
SPI_TRANSFER_ERROR = 1,
SPI_TRANSFER_TIMEOUT = 2,
SPI_TRANSFER_DMA_COMPLETE = 3
} SpiTransferStatus_t;
/* SPI Callbacks */
typedef void (*SpiTransferCompleteCallback_t)(SpiTransferStatus_t status, void* user_data);
/* SPI Configuration */
typedef struct {
SpiMode_t mode;
SpiClockSpeed_t clock_speed;
SpiDataOrder_t data_order;
uint8_t data_size; /* 8 or 16 bits */
bool use_dma;
bool enable_hardware_cs;
SpiChipSelectPolarity_t cs_polarity;
uint8_t cs_port;
uint8_t cs_pin;
SpiTransferCompleteCallback_t transfer_complete_callback;
} SpiConfig_t;
/* SPI Statistics */
typedef struct {
uint32_t transfers_completed;
uint32_t transfers_failed;
uint32_t bytes_transferred;
uint32_t dma_transfers;
uint32_t overrun_errors;
uint32_t underrun_errors;
uint32_t timeout_errors;
} SpiStatistics_t;
/* SPI Transaction */
typedef struct {
const uint8_t* tx_data;
uint8_t* rx_data;
uint16_t length;
bool keep_cs_active;
void* user_data;
} SpiTransaction_t;
/* SPI Driver Interface */
KernelStatus_t spi_init(uint8_t instance, SpiConfig_t* config);
KernelStatus_t spi_deinit(uint8_t instance);
KernelStatus_t spi_transfer(uint8_t instance, const SpiTransaction_t* transaction,
uint32_t timeout_ms);
KernelStatus_t spi_transfer_async(uint8_t instance, const SpiTransaction_t* transaction);
KernelStatus_t spi_read(uint8_t instance, uint8_t* data, uint16_t length,
uint32_t timeout_ms);
KernelStatus_t spi_write(uint8_t instance, const uint8_t* data, uint16_t length,
uint32_t timeout_ms);
KernelStatus_t spi_read_write(uint8_t instance, const uint8_t* tx_data,
uint8_t* rx_data, uint16_t length, uint32_t timeout_ms);
KernelStatus_t spi_get_statistics(uint8_t instance, SpiStatistics_t* stats);
void spi_set_chip_select(uint8_t instance, bool active);
void spi_process_interrupt(uint8_t instance);
#endif /* SPI_DRIVER_H */
+107
View File
@@ -0,0 +1,107 @@
/**
* @file uart_driver.h
* @brief UART driver interface
*/
#ifndef UART_DRIVER_H
#define UART_DRIVER_H
#include <stdint.h>
#include <stdbool.h>
#include "kernel.h"
/* UART Configuration Constants */
#define UART_MAX_INSTANCES 6
#define UART_MAX_BUFFER_SIZE 2048
#define UART_DEFAULT_BAUDRATE 115200
/* UART Baudrates */
typedef enum {
UART_BAUD_9600 = 9600,
UART_BAUD_19200 = 19200,
UART_BAUD_38400 = 38400,
UART_BAUD_57600 = 57600,
UART_BAUD_115200 = 115200,
UART_BAUD_230400 = 230400,
UART_BAUD_460800 = 460800,
UART_BAUD_921600 = 921600
} UartBaudrate_t;
/* UART Data Bits */
typedef enum {
UART_DATA_BITS_5 = 5,
UART_DATA_BITS_6 = 6,
UART_DATA_BITS_7 = 7,
UART_DATA_BITS_8 = 8,
UART_DATA_BITS_9 = 9
} UartDataBits_t;
/* UART Stop Bits */
typedef enum {
UART_STOP_BITS_1 = 0,
UART_STOP_BITS_1_5 = 1,
UART_STOP_BITS_2 = 2
} UartStopBits_t;
/* UART Parity */
typedef enum {
UART_PARITY_NONE = 0,
UART_PARITY_EVEN = 1,
UART_PARITY_ODD = 2
} UartParity_t;
/* UART Flow Control */
typedef enum {
UART_FLOW_CONTROL_NONE = 0,
UART_FLOW_CONTROL_RTS_CTS = 1,
UART_FLOW_CONTROL_XON_XOFF = 2
} UartFlowControl_t;
/* UART Callbacks */
typedef void (*UartRxCallback_t)(uint8_t* data, uint16_t length);
typedef void (*UartTxCallback_t)(void);
typedef void (*UartErrorCallback_t)(uint32_t error);
/* UART Configuration */
typedef struct {
UartBaudrate_t baudrate;
UartDataBits_t data_bits;
UartStopBits_t stop_bits;
UartParity_t parity;
UartFlowControl_t flow_control;
bool enable_rx;
bool enable_tx;
bool use_dma;
UartRxCallback_t rx_callback;
UartTxCallback_t tx_callback;
UartErrorCallback_t error_callback;
} UartConfig_t;
/* UART Statistics */
typedef struct {
uint32_t tx_bytes;
uint32_t rx_bytes;
uint32_t tx_errors;
uint32_t rx_errors;
uint32_t parity_errors;
uint32_t framing_errors;
uint32_t overrun_errors;
uint32_t dma_transfers;
} UartStatistics_t;
/* UART Driver Interface */
KernelStatus_t uart_init(uint8_t instance, UartConfig_t* config);
KernelStatus_t uart_deinit(uint8_t instance);
KernelStatus_t uart_send(uint8_t instance, const uint8_t* data, uint16_t length,
uint32_t timeout_ms);
KernelStatus_t uart_receive(uint8_t instance, uint8_t* data, uint16_t length,
uint32_t timeout_ms);
KernelStatus_t uart_send_async(uint8_t instance, const uint8_t* data, uint16_t length);
KernelStatus_t uart_receive_async(uint8_t instance, uint8_t* data, uint16_t length);
KernelStatus_t uart_flush(uint8_t instance);
KernelStatus_t uart_get_statistics(uint8_t instance, UartStatistics_t* stats);
uint16_t uart_get_rx_count(uint8_t instance);
uint16_t uart_get_tx_count(uint8_t instance);
void uart_process_interrupt(uint8_t instance);
#endif /* UART_DRIVER_H */
@@ -0,0 +1,72 @@
/**
* @file tc3xx_config.h
* @brief Infineon TriCore TC3xx specific configuration
*/
#ifndef TC3XX_CONFIG_H
#define TC3XX_CONFIG_H
/* MCU Specific Definitions */
#define TC397
#define CPU_FREQUENCY 300000000U /* 300 MHz */
#define PERIPHERAL_FREQUENCY 150000000U /* 150 MHz */
#define STM_FREQUENCY 100000000U /* 100 MHz */
/* Peripheral Base Addresses */
#define CAN0_BASE 0xF0200000U
#define CAN1_BASE 0xF0210000U
#define CAN2_BASE 0xF0220000U
#define CAN3_BASE 0xF0230000U
#define ASCLIN0_BASE 0xF0000000U
#define ASCLIN1_BASE 0xF0000100U
#define ASCLIN2_BASE 0xF0000200U
#define ASCLIN3_BASE 0xF0000300U
#define QSPI0_BASE 0xF0001000U
#define QSPI1_BASE 0xF0001100U
#define QSPI2_BASE 0xF0001200U
#define QSPI3_BASE 0xF0001300U
#define I2C0_BASE 0xF0002000U
#define I2C1_BASE 0xF0002100U
#define VADC0_BASE 0xF0020000U
#define VADC1_BASE 0xF0020100U
#define GTM_BASE 0xF0100000U
#define GPT12_BASE 0xF0003000U
/* Interrupt Priorities */
#define CAN0_IRQ_PRIORITY 5
#define CAN1_IRQ_PRIORITY 5
#define ASCLIN0_IRQ_PRIORITY 6
#define QSPI0_IRQ_PRIORITY 7
#define I2C0_IRQ_PRIORITY 7
#define VADC0_IRQ_PRIORITY 8
#define GTM_IRQ_PRIORITY 8
/* DMA Configuration */
#define DMA_CHANNEL_COUNT 128
#define DMA_PRIORITY_HIGH 0
#define DMA_PRIORITY_MEDIUM 1
#define DMA_PRIORITY_LOW 2
/* Safety Features */
#define ENABLE_SAFETY_WATCHDOG 1
#define WATCHDOG_TIMEOUT_MS 100
#define ENABLE_ECC 1
#define ENABLE_MEMORY_PROTECTION 1
/* Memory Configuration */
#define FLASH_SIZE 0x800000U /* 8 MB */
#define RAM_SIZE 0x280000U /* 2.5 MB */
#define DSPR_SIZE 0x20000U /* 128 KB per CPU */
/* CAN FD Configuration */
#define CAN_FD_ENABLED 1
#define CAN_FD_MAX_PAYLOAD 64
#define CAN_TX_FIFO_SIZE 32
#define CAN_RX_FIFO_SIZE 64
#endif /* TC3XX_CONFIG_H */
@@ -0,0 +1,132 @@
/**
* @file tc3xx_hal.c
* @brief Infineon TriCore TC3xx Hardware Abstraction Layer
*/
#include "tc3xx_config.h"
#include "can_driver.h"
#include "uart_driver.h"
#include "spi_driver.h"
#include "i2c_driver.h"
#include "gpio_driver.h"
#include "adc_driver.h"
#include "pwm_driver.h"
#include "Ifx_Types.h"
#include "IfxCan_Can.h"
#include "IfxAsclin_Asc.h"
#include "IfxQspi_SpiMaster.h"
#include "IfxI2c_I2c.h"
#include "IfxPort.h"
#include "IfxVadc_Adc.h"
#include "IfxGtm_Tom_PwmHl.h"
/* CAN HAL Implementation */
int hal_can_init(uint32_t baudrate, uint8_t frame_type, bool enable_fd) {
/* Create CAN module configuration */
IfxCan_Can_Config canConfig;
IfxCan_Can_initModuleConfig(&canConfig, &MODULE_CAN0);
/* Configure node */
canConfig.nodeConfig[0].baudRate.baudrate = baudrate;
canConfig.nodeConfig[0].frame.type = IfxCan_FrameType_receive;
if (enable_fd) {
canConfig.nodeConfig[0].frame.mode = IfxCan_FrameMode_fd;
}
/* Initialize CAN module */
IfxCan_Can_initModule(&g_canDriver, &canConfig);
/* Configure TX FIFO */
IfxCan_Can_initTxFifo(&g_canDriver, &g_canTxFifo);
/* Configure RX FIFO */
IfxCan_Can_initRxFifo(&g_canDriver, &g_canRxFifo);
/* Enable interrupts */
IfxCan_Can_enableInterrupt(&g_canDriver, IfxCan_Interrupt_messageStoredToDedicatedRxFifo);
return 0;
}
int hal_can_send_message(const CanMessage_t* message, uint32_t* mailbox) {
/* Create TX message */
IfxCan_Can_Message txMessage;
/* Set message ID */
txMessage.messageId = message->id.id;
txMessage.extendedFrame = message->id.is_extended;
/* Set data */
txMessage.dataLengthCode = message->length;
for (int i = 0; i < message->length; i++) {
txMessage.data[i] = message->data[i];
}
/* Send message */
if (IfxCan_Can_sendMessage(&g_canDriver, &txMessage, &txMessage.messageId)
!= IfxCan_Status_ok) {
return -1;
}
*mailbox = 0;
return 0;
}
int hal_can_receive_message(CanMessage_t* message) {
/* Create RX message */
IfxCan_Can_Message rxMessage;
/* Receive message */
if (IfxCan_Can_readMessage(&g_canDriver, &rxMessage, &rxMessage.messageId)
!= IfxCan_Status_ok) {
return -1;
}
/* Copy message data */
message->id.id = rxMessage.messageId;
message->id.is_extended = rxMessage.extendedFrame;
message->length = rxMessage.dataLengthCode;
for (int i = 0; i < message->length; i++) {
message->data[i] = rxMessage.data[i];
}
return 0;
}
/* GPIO HAL Implementation */
void hal_gpio_init(uint8_t port, uint8_t pin, GpioMode_t mode) {
/* Configure port pin */
IfxPort_setPinMode(&MODULE_P00, pin, IfxPort_Mode_outputPushPullGeneral);
}
void hal_gpio_write(uint8_t port, uint8_t pin, bool value) {
if (value) {
IfxPort_setPinHigh(&MODULE_P00, pin);
} else {
IfxPort_setPinLow(&MODULE_P00, pin);
}
}
bool hal_gpio_read(uint8_t port, uint8_t pin) {
return IfxPort_getPinState(&MODULE_P00, pin);
}
/* UART HAL Implementation */
int hal_uart_init(uint8_t instance, UartConfig_t* config) {
/* Create ASCLIN configuration */
IfxAsclin_Asc_Config ascConfig;
IfxAsclin_Asc_initModuleConfig(&ascConfig, &MODULE_ASCLIN0);
/* Configure baudrate */
ascConfig.baudrate.baudrate = config->baudrate;
/* Configure pins */
ascConfig.pins = &g_ascPins;
/* Initialize module */
IfxAsclin_Asc_initModule(&g_ascDriver, &ascConfig);
return 0;
}
@@ -0,0 +1,89 @@
/**
* @file s32k14x_config.h
* @brief NXP S32K14x specific configuration
*/
#ifndef S32K14X_CONFIG_H
#define S32K14X_CONFIG_H
/* MCU Specific Definitions */
#define S32K144
#define CPU_FREQUENCY 160000000U /* 160 MHz */
#define BUS_FREQUENCY 40000000U /* 40 MHz */
#define SLOW_FREQUENCY 10000000U /* 10 MHz */
/* Peripheral Base Addresses */
#define GPIOA_BASE 0x400FF000U
#define GPIOB_BASE 0x400FF040U
#define GPIOC_BASE 0x400FF080U
#define GPIOD_BASE 0x400FF0C0U
#define GPIOE_BASE 0x400FF100U
#define LPUART0_BASE 0x4006A000U
#define LPUART1_BASE 0x4006B000U
#define LPUART2_BASE 0x4006C000U
#define LPSPI0_BASE 0x4002C000U
#define LPSPI1_BASE 0x4002D000U
#define LPSPI2_BASE 0x4002E000U
#define LPI2C0_BASE 0x40066000U
#define LPI2C1_BASE 0x40067000U
#define ADC0_BASE 0x4003B000U
#define ADC1_BASE 0x4003C000U
#define FTM0_BASE 0x40038000U
#define FTM1_BASE 0x40039000U
#define FTM2_BASE 0x4003A000U
#define FTM3_BASE 0x40026000U
#define FTM4_BASE 0x40027000U
#define FLEXCAN0_BASE 0x40024000U
#define FLEXCAN1_BASE 0x40025000U
#define FLEXCAN2_BASE 0x4002B000U
/* Clock Configuration */
#define SOSC_FREQUENCY 8000000U /* System oscillator */
#define SPLL_FREQUENCY 160000000U /* System PLL */
#define FIRC_FREQUENCY 48000000U /* Fast IRC */
#define SIRC_FREQUENCY 8000000U /* Slow IRC */
/* Peripheral Clock Configuration */
#define FLEXCAN0_CLOCK 40000000U /* 40 MHz */
#define FLEXCAN1_CLOCK 40000000U
#define LPUART0_CLOCK 40000000U
#define LPSPI0_CLOCK 40000000U
#define LPI2C0_CLOCK 40000000U
#define ADC0_CLOCK 40000000U
#define FTM0_CLOCK 40000000U
/* NVIC Priority Configuration */
#define FLEXCAN0_IRQ_PRIORITY 5
#define FLEXCAN1_IRQ_PRIORITY 5
#define LPUART0_IRQ_PRIORITY 6
#define LPUART1_IRQ_PRIORITY 6
#define LPSPI0_IRQ_PRIORITY 7
#define LPI2C0_IRQ_PRIORITY 7
#define ADC0_IRQ_PRIORITY 8
#define FTM0_IRQ_PRIORITY 8
/* DMA Configuration */
#define DMA_CHANNEL_COUNT 16
#define DMA_MUX_CHANNEL_COUNT 16
/* Safety Features */
#define ENABLE_CLOCK_MONITORING 1
#define ENABLE_MEMORY_PROTECTION 1
#define WATCHDOG_TIMEOUT_MS 100
/* Memory Configuration */
#define FLASH_SIZE 0x100000U /* 1 MB */
#define RAM_SIZE 0x20000U /* 128 KB */
#define EEPROM_SIZE 0x1000U /* 4 KB */
/* CAN FD Configuration */
#define CAN_FD_ENABLED 1
#define CAN_FD_MAX_PAYLOAD 64
#endif /* S32K14X_CONFIG_H */
+224
View File
@@ -0,0 +1,224 @@
/**
* @file s32k14x_hal.c
* @brief NXP S32K14x Hardware Abstraction Layer
*/
#include "s32k14x_config.h"
#include "can_driver.h"
#include "uart_driver.h"
#include "spi_driver.h"
#include "i2c_driver.h"
#include "gpio_driver.h"
#include "adc_driver.h"
#include "pwm_driver.h"
#include "S32K144.h"
/* CAN HAL Implementation */
int hal_can_init(uint32_t baudrate, uint8_t frame_type, bool enable_fd) {
/* Enable FLEXCAN0 clock */
PCC->PCCn[PCC_FlexCAN0_INDEX] |= PCC_PCCn_CGC_MASK;
/* Configure CAN pins */
// PTE4 - CAN0_RX, PTE5 - CAN0_TX
PCC->PCCn[PCC_PORTE_INDEX] |= PCC_PCCn_CGC_MASK;
PORTE->PCR[4] = PORT_PCR_MUX(5); /* CAN0_RX */
PORTE->PCR[5] = PORT_PCR_MUX(5); /* CAN0_TX */
/* Reset FLEXCAN */
CAN0->MCR |= CAN_MCR_SOFTRST_MASK;
while (CAN0->MCR & CAN_MCR_SOFTRST_MASK);
/* Configure for CAN FD if enabled */
if (enable_fd) {
CAN0->MCR |= CAN_MCR_FDEN_MASK; /* Enable FD */
}
/* Set baudrate */
uint32_t prescaler = BUS_FREQUENCY / (baudrate * 10); /* 10 time quanta */
CAN0->CTRL1 = CAN_CTRL1_PRESDIV(prescaler - 1) |
CAN_CTRL1_PSEG1(3) |
CAN_CTRL1_PSEG2(2) |
CAN_CTRL1_PROPSEG(4);
/* Configure message buffers */
CAN0->RXMGMASK = 0x1FFFFFFF; /* Accept all IDs */
CAN0->RX14MASK = 0x1FFFFFFF;
CAN0->RX15MASK = 0x1FFFFFFF;
/* Enable interrupts */
CAN0->IMASK1 |= CAN_IMASK1_BUF31TO0M_MASK;
CAN0->MCR |= CAN_MCR_IRMQ_MASK; /* Individual RX masking */
/* Normal mode */
CAN0->MCR &= ~CAN_MCR_HALT_MASK;
while (CAN0->MCR & CAN_MCR_FRZACK_MASK);
return 0;
}
int hal_can_send_message(const CanMessage_t* message, uint32_t* mailbox) {
/* Find free message buffer */
*mailbox = 0;
while (*mailbox < 32) {
if ((CAN0->IFLAG1 & (1 << *mailbox)) != 0) {
break;
}
(*mailbox)++;
}
if (*mailbox >= 32) {
return -1;
}
/* Configure message buffer */
CAN0->RAMn[*mailbox * 4 + 1] = (message->id.id << 18) |
(message->id.is_extended ? 1 << 29 : 0) |
(message->length << 16);
/* Copy data */
for (int i = 0; i < message->length; i += 4) {
uint32_t data = 0;
for (int j = 0; j < 4 && (i + j) < message->length; j++) {
data |= (message->data[i + j] << (j * 8));
}
CAN0->RAMn[*mailbox * 4 + 2 + (i / 4)] = data;
}
/* Enable transmission */
CAN0->RAMn[*mailbox * 4] = CAN_WORD0_IDE_MASK |
CAN_WORD0_SRR_MASK |
CAN_WORD0_ESI_MASK |
CAN_WORD0_CODE(0xC); /* TX data */
return 0;
}
int hal_can_receive_message(CanMessage_t* message) {
/* Check for received messages */
uint32_t iflag = CAN0->IFLAG1;
if (iflag == 0) {
return -1;
}
/* Find received message buffer */
uint32_t mailbox = 0;
while (mailbox < 32) {
if (iflag & (1 << mailbox)) {
break;
}
mailbox++;
}
if (mailbox >= 32) {
return -1;
}
/* Read message */
uint32_t word0 = CAN0->RAMn[mailbox * 4];
uint32_t word1 = CAN0->RAMn[mailbox * 4 + 1];
/* Check if RX buffer */
if ((word0 & CAN_WORD0_CODE_MASK) != CAN_WORD0_CODE(0x4)) {
CAN0->IFLAG1 = (1 << mailbox); /* Clear flag */
return -1;
}
/* Get ID */
message->id.is_extended = (word0 & CAN_WORD0_IDE_MASK) != 0;
if (message->id.is_extended) {
message->id.id = (word0 & CAN_WORD0_ID_MASK) >> 0;
} else {
message->id.id = (word0 & CAN_WORD0_ID_MASK) >> 18;
}
/* Get data length */
message->length = (word1 & CAN_WORD1_DLC_MASK) >> 16;
/* Get data */
for (int i = 0; i < message->length; i += 4) {
uint32_t data = CAN0->RAMn[mailbox * 4 + 2 + (i / 4)];
for (int j = 0; j < 4 && (i + j) < message->length; j++) {
message->data[i + j] = (data >> (j * 8)) & 0xFF;
}
}
/* Clear flag */
CAN0->IFLAG1 = (1 << mailbox);
return 0;
}
/* GPIO HAL Implementation */
void hal_gpio_init(uint8_t port, uint8_t pin, GpioMode_t mode) {
GPIO_Type* gpio_port = get_gpio_port(port);
PORT_Type* port_config = get_port_config(port);
if (gpio_port == NULL || port_config == NULL) {
return;
}
/* Enable clock */
PCC->PCCn[PCC_PORTA_INDEX + port] |= PCC_PCCn_CGC_MASK;
PCC->PCCn[PCC_GPIOA_INDEX + port] |= PCC_PCCn_CGC_MASK;
/* Configure pin mux */
switch (mode) {
case GPIO_MODE_INPUT:
port_config->PCR[pin] = PORT_PCR_MUX(1);
gpio_port->PDDR &= ~(1 << pin);
break;
case GPIO_MODE_OUTPUT:
port_config->PCR[pin] = PORT_PCR_MUX(1);
gpio_port->PDDR |= (1 << pin);
break;
default:
break;
}
}
void hal_gpio_write(uint8_t port, uint8_t pin, bool value) {
GPIO_Type* gpio_port = get_gpio_port(port);
if (gpio_port == NULL) {
return;
}
if (value) {
gpio_port->PSOR = (1 << pin);
} else {
gpio_port->PCOR = (1 << pin);
}
}
bool hal_gpio_read(uint8_t port, uint8_t pin) {
GPIO_Type* gpio_port = get_gpio_port(port);
if (gpio_port == NULL) {
return false;
}
return (gpio_port->PDIR & (1 << pin)) != 0;
}
/* Helper functions */
static GPIO_Type* get_gpio_port(uint8_t port) {
switch (port) {
case 0: return PTA;
case 1: return PTB;
case 2: return PTC;
case 3: return PTD;
case 4: return PTE;
default: return NULL;
}
}
static PORT_Type* get_port_config(uint8_t port) {
switch (port) {
case 0: return PORTA;
case 1: return PORTB;
case 2: return PORTC;
case 3: return PORTD;
case 4: return PORTE;
default: return NULL;
}
}
@@ -0,0 +1,126 @@
/**
* @file stm32f4xx_config.h
* @brief STM32F4 specific configuration
*/
#ifndef STM32F4XX_CONFIG_H
#define STM32F4XX_CONFIG_H
/* MCU Specific Definitions */
#define STM32F407xx
#define HSE_VALUE 8000000U /* External crystal */
#define HSI_VALUE 16000000U /* Internal oscillator */
#define LSE_VALUE 32768U /* Low speed external */
#define LSI_VALUE 32000U /* Low speed internal */
/* Clock Configuration */
#define SYSTEM_CLOCK 168000000U /* 168 MHz */
#define AHB_CLOCK 168000000U
#define APB1_CLOCK 42000000U /* 42 MHz */
#define APB2_CLOCK 84000000U /* 84 MHz */
/* Peripheral Base Addresses */
#define GPIOA_BASE 0x40020000U
#define GPIOB_BASE 0x40020400U
#define GPIOC_BASE 0x40020800U
#define GPIOD_BASE 0x40020C00U
#define GPIOE_BASE 0x40021000U
#define GPIOF_BASE 0x40021400U
#define GPIOG_BASE 0x40021800U
#define GPIOH_BASE 0x40021C00U
#define USART1_BASE 0x40011000U
#define USART2_BASE 0x40004400U
#define USART3_BASE 0x40004800U
#define UART4_BASE 0x40004C00U
#define UART5_BASE 0x40005000U
#define USART6_BASE 0x40011400U
#define SPI1_BASE 0x40013000U
#define SPI2_BASE 0x40003800U
#define SPI3_BASE 0x40003C00U
#define I2C1_BASE 0x40005400U
#define I2C2_BASE 0x40005800U
#define I2C3_BASE 0x40005C00U
#define ADC1_BASE 0x40012000U
#define ADC2_BASE 0x40012100U
#define ADC3_BASE 0x40012200U
#define TIM1_BASE 0x40010000U
#define TIM2_BASE 0x40000000U
#define TIM3_BASE 0x40000400U
#define TIM4_BASE 0x40000800U
#define TIM5_BASE 0x40000C00U
#define TIM8_BASE 0x40010400U
#define TIM9_BASE 0x40014000U
#define TIM10_BASE 0x40014400U
#define TIM11_BASE 0x40014800U
#define TIM12_BASE 0x40001800U
#define TIM13_BASE 0x40001C00U
#define TIM14_BASE 0x40002000U
#define CAN1_BASE 0x40006400U
#define CAN2_BASE 0x40006800U
/* NVIC Priority Configuration */
#define CAN1_IRQ_PRIORITY 5
#define CAN2_IRQ_PRIORITY 5
#define USART1_IRQ_PRIORITY 6
#define USART2_IRQ_PRIORITY 6
#define USART3_IRQ_PRIORITY 6
#define SPI1_IRQ_PRIORITY 7
#define SPI2_IRQ_PRIORITY 7
#define I2C1_IRQ_PRIORITY 7
#define I2C2_IRQ_PRIORITY 7
#define ADC_IRQ_PRIORITY 8
#define TIM_IRQ_PRIORITY 8
/* DMA Configuration */
#define DMA1_STREAM0_CHANNEL 0
#define DMA1_STREAM1_CHANNEL 1
#define DMA1_STREAM2_CHANNEL 2
#define DMA1_STREAM3_CHANNEL 3
#define DMA1_STREAM4_CHANNEL 4
#define DMA1_STREAM5_CHANNEL 5
#define DMA1_STREAM6_CHANNEL 6
#define DMA1_STREAM7_CHANNEL 7
#define DMA2_STREAM0_CHANNEL 0
#define DMA2_STREAM1_CHANNEL 1
#define DMA2_STREAM2_CHANNEL 2
#define DMA2_STREAM3_CHANNEL 3
#define DMA2_STREAM4_CHANNEL 4
#define DMA2_STREAM5_CHANNEL 5
#define DMA2_STREAM6_CHANNEL 6
#define DMA2_STREAM7_CHANNEL 7
/* GPIO Alternate Function Mapping */
#define GPIO_AF_UART1_TX 7
#define GPIO_AF_UART1_RX 7
#define GPIO_AF_UART2_TX 7
#define GPIO_AF_UART2_RX 7
#define GPIO_AF_SPI1_SCK 5
#define GPIO_AF_SPI1_MOSI 5
#define GPIO_AF_SPI1_MISO 5
#define GPIO_AF_I2C1_SCL 4
#define GPIO_AF_I2C1_SDA 4
#define GPIO_AF_CAN1_TX 9
#define GPIO_AF_CAN1_RX 9
#define GPIO_AF_TIM1_CH1 1
#define GPIO_AF_TIM1_CH2 1
#define GPIO_AF_TIM1_CH3 1
#define GPIO_AF_TIM1_CH4 1
/* Memory Configuration */
#define FLASH_SIZE 0x100000U /* 1 MB */
#define RAM_SIZE 0x20000U /* 128 KB */
#define CCM_RAM_SIZE 0x10000U /* 64 KB */
/* Safety Features */
#define ENABLE_CLOCK_SECURITY_SYSTEM 1
#define ENABLE_BROWN_OUT_RESET 1
#define BROWNOUT_THRESHOLD 0x08 /* 2.7V */
#endif /* STM32F4XX_CONFIG_H */
@@ -0,0 +1,289 @@
/**
* @file stm32f4xx_hal.c
* @brief STM32F4 Hardware Abstraction Layer
*/
#include "stm32f4xx_config.h"
#include "can_driver.h"
#include "uart_driver.h"
#include "spi_driver.h"
#include "i2c_driver.h"
#include "gpio_driver.h"
#include "adc_driver.h"
#include "pwm_driver.h"
#include "stm32f4xx.h"
/* CAN HAL Implementation */
int hal_can_init(uint32_t baudrate, uint8_t frame_type, bool enable_fd) {
/* Enable CAN clock */
RCC->APB1ENR |= RCC_APB1ENR_CAN1EN;
/* Configure CAN GPIO */
// PB8 - CAN1_RX, PB9 - CAN1_TX
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN;
GPIOB->MODER |= (GPIO_MODER_MODER8_1 | GPIO_MODER_MODER9_1);
GPIOB->OTYPER &= ~(GPIO_OTYPER_OT_8 | GPIO_OTYPER_OT_9);
GPIOB->OSPEEDR |= (GPIO_OSPEEDER_OSPEEDR8 | GPIO_OSPEEDER_OSPEEDR9);
GPIOB->AFR[1] |= (9 << 0) | (9 << 4); /* AF9 for CAN */
/* Reset CAN */
CAN1->MCR |= CAN_MCR_RESET;
CAN1->MCR &= ~CAN_MCR_RESET;
/* Exit sleep mode */
CAN1->MCR &= ~CAN_MCR_SLEEP;
/* Set baudrate */
uint32_t prescaler = 0;
uint32_t time_quantum = 0;
switch (baudrate) {
case 125000:
prescaler = 21;
time_quantum = 16;
break;
case 250000:
prescaler = 11;
time_quantum = 15;
break;
case 500000:
prescaler = 5;
time_quantum = 16;
break;
case 1000000:
prescaler = 3;
time_quantum = 14;
break;
default:
return -1;
}
CAN1->BTR = ((prescaler - 1) << 20) |
((time_quantum - 1) << 16) |
(3 << 20) | /* SJW = 4 */
(7 << 16); /* BS1 = 8 */
/* Configure filters */
CAN1->FMR |= CAN_FMR_FINIT;
CAN1->FM1R &= ~CAN_FM1R_FBM0; /* Mask mode for filter 0 */
CAN1->FS1R |= CAN_FS1R_FSC0; /* 32-bit scale */
CAN1->FFA1R &= ~CAN_FFA1R_FFA0; /* FIFO 0 */
CAN1->FMR &= ~CAN_FMR_FINIT;
/* Enable interrupts */
CAN1->IER |= CAN_IER_FMPIE0 | /* FIFO 0 message pending */
CAN_IER_TMEIE | /* Transmit mailbox empty */
CAN_IER_BOFIE | /* Bus-off */
CAN_IER_ERRIE; /* Error */
/* Normal mode */
CAN1->MCR &= ~CAN_MCR_SLEEP;
return 0;
}
int hal_can_send_message(const CanMessage_t* message, uint32_t* mailbox) {
/* Check for free mailbox */
if ((CAN1->TSR & CAN_TSR_TME0) != 0) {
*mailbox = 0;
} else if ((CAN1->TSR & CAN_TSR_TME1) != 0) {
*mailbox = 1;
} else if ((CAN1->TSR & CAN_TSR_TME2) != 0) {
*mailbox = 2;
} else {
return -1;
}
/* Configure mailbox */
CAN_TxMailBox_TypeDef* tx_mailbox = &CAN1->sTxMailBox[*mailbox];
/* Set ID */
if (message->id.is_extended) {
tx_mailbox->TIR = (message->id.id << 3) | CAN_TI0R_IDE;
} else {
tx_mailbox->TIR = (message->id.id << 21);
}
/* Set data length and data */
tx_mailbox->TDTR = message->length;
/* Copy data */
uint32_t data[2] = {0, 0};
for (int i = 0; i < message->length; i++) {
if (i < 4) {
data[0] |= (message->data[i] << (i * 8));
} else {
data[1] |= (message->data[i] << ((i - 4) * 8));
}
}
tx_mailbox->TDLR = data[0];
tx_mailbox->TDHR = data[1];
/* Request transmission */
tx_mailbox->TIR |= CAN_TI0R_TXRQ;
return 0;
}
int hal_can_receive_message(CanMessage_t* message) {
/* Check if message available */
if ((CAN1->RF0R & CAN_RF0R_FMP0) == 0) {
return -1;
}
/* Get message */
CAN_FIFOMailBox_TypeDef* rx_mailbox = &CAN1->sFIFOMailBox[0];
/* Get ID */
if (rx_mailbox->RIR & CAN_RI0R_IDE) {
message->id.is_extended = true;
message->id.id = (rx_mailbox->RIR >> 3) & 0x1FFFFFFF;
} else {
message->id.is_extended = false;
message->id.id = (rx_mailbox->RIR >> 21) & 0x7FF;
}
/* Get data length */
message->length = rx_mailbox->RDTR & CAN_RDT0R_DLC;
/* Get data */
uint32_t data_low = rx_mailbox->RDLR;
uint32_t data_high = rx_mailbox->RDHR;
for (int i = 0; i < message->length; i++) {
if (i < 4) {
message->data[i] = (data_low >> (i * 8)) & 0xFF;
} else {
message->data[i] = (data_high >> ((i - 4) * 8)) & 0xFF;
}
}
/* Release FIFO */
CAN1->RF0R |= CAN_RF0R_RFOM0;
return 0;
}
/* GPIO HAL Implementation */
void hal_gpio_init(uint8_t port, uint8_t pin, GpioMode_t mode) {
GPIO_TypeDef* gpio_port = get_gpio_port(port);
if (gpio_port == NULL) {
return;
}
/* Enable GPIO clock */
RCC->AHB1ENR |= (1 << port);
/* Configure mode */
uint32_t moder_value = 0;
switch (mode) {
case GPIO_MODE_INPUT:
moder_value = 0x00;
break;
case GPIO_MODE_OUTPUT:
moder_value = 0x01;
break;
case GPIO_MODE_ALTERNATE:
moder_value = 0x02;
break;
case GPIO_MODE_ANALOG:
moder_value = 0x03;
break;
}
gpio_port->MODER &= ~(0x03 << (pin * 2));
gpio_port->MODER |= (moder_value << (pin * 2));
}
void hal_gpio_write(uint8_t port, uint8_t pin, bool value) {
GPIO_TypeDef* gpio_port = get_gpio_port(port);
if (gpio_port == NULL) {
return;
}
if (value) {
gpio_port->BSRR = (1 << pin);
} else {
gpio_port->BSRR = (1 << (pin + 16));
}
}
bool hal_gpio_read(uint8_t port, uint8_t pin) {
GPIO_TypeDef* gpio_port = get_gpio_port(port);
if (gpio_port == NULL) {
return false;
}
return (gpio_port->IDR & (1 << pin)) != 0;
}
/* UART HAL Implementation */
int hal_uart_init(uint8_t instance, UartConfig_t* config) {
USART_TypeDef* uart = get_uart_instance(instance);
if (uart == NULL) {
return -1;
}
/* Enable clock */
if (instance == 0) {
RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
} else {
RCC->APB1ENR |= (RCC_APB1ENR_USART2EN << (instance - 1));
}
/* Configure baudrate */
uint32_t clock = (instance == 0 || instance == 5) ? APB2_CLOCK : APB1_CLOCK;
uart->BRR = clock / config->baudrate;
/* Configure control registers */
uart->CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_UE;
if (config->data_bits == UART_DATA_BITS_9) {
uart->CR1 |= USART_CR1_M;
}
uart->CR2 = 0;
if (config->stop_bits == UART_STOP_BITS_2) {
uart->CR2 |= USART_CR2_STOP_1;
}
/* Enable interrupts */
if (config->enable_rx) {
uart->CR1 |= USART_CR1_RXNEIE;
}
return 0;
}
/* Helper functions */
static GPIO_TypeDef* get_gpio_port(uint8_t port) {
switch (port) {
case 0: return GPIOA;
case 1: return GPIOB;
case 2: return GPIOC;
case 3: return GPIOD;
case 4: return GPIOE;
case 5: return GPIOF;
case 6: return GPIOG;
case 7: return GPIOH;
default: return NULL;
}
}
static USART_TypeDef* get_uart_instance(uint8_t instance) {
switch (instance) {
case 0: return USART1;
case 1: return USART2;
case 2: return USART3;
case 3: return UART4;
case 4: return UART5;
case 5: return USART6;
default: return NULL;
}
}
+283
View File
@@ -0,0 +1,283 @@
/**
* @file adc_driver.c
* @brief ADC driver implementation
*/
#include "adc_driver.h"
#include "isr.h"
#include <string.h>
/* ADC Driver State */
typedef struct {
bool initialized;
AdcConfig_t config;
AdcStatistics_t statistics;
uint16_t conversion_buffer[ADC_MAX_CHANNELS];
uint8_t current_channel;
bool conversion_active;
bool dma_active;
uint16_t* dma_buffer;
uint16_t dma_length;
uint16_t dma_index;
Semaphore_t conversion_semaphore;
Mutex_t conversion_mutex;
} AdcDriverState_t;
static AdcDriverState_t adc_drivers[ADC_MAX_INSTANCES];
/* Initialize ADC Driver */
KernelStatus_t adc_init(uint8_t instance, AdcConfig_t* config) {
if (instance >= ADC_MAX_INSTANCES || config == NULL) {
return KERNEL_INVALID_PARAMETER;
}
AdcDriverState_t* driver = &adc_drivers[instance];
if (driver->initialized) {
return KERNEL_ERROR;
}
/* Copy configuration */
memcpy(&driver->config, config, sizeof(AdcConfig_t));
/* Initialize state */
memset(&driver->statistics, 0, sizeof(AdcStatistics_t));
driver->current_channel = 0;
driver->conversion_active = false;
driver->dma_active = false;
driver->dma_buffer = NULL;
driver->dma_length = 0;
driver->dma_index = 0;
/* Create synchronization primitives */
semaphore_create(&driver->conversion_semaphore, SEMAPHORE_BINARY, 0, 1);
mutex_create(&driver->conversion_mutex, false);
/* Initialize ADC hardware */
if (hal_adc_init(instance, config) != 0) {
return KERNEL_ERROR;
}
/* Enable interrupts */
hal_adc_enable_interrupts(instance);
driver->initialized = true;
return KERNEL_OK;
}
/* Start ADC Conversion */
KernelStatus_t adc_start_conversion(uint8_t instance) {
if (instance >= ADC_MAX_INSTANCES) {
return KERNEL_INVALID_PARAMETER;
}
AdcDriverState_t* driver = &adc_drivers[instance];
if (!driver->initialized) {
return KERNEL_ERROR;
}
if (driver->conversion_active) {
return KERNEL_RESOURCE_BUSY;
}
/* Reset conversion state */
driver->current_channel = 0;
driver->conversion_active = true;
/* Start conversion */
hal_adc_start_conversion(instance);
return KERNEL_OK;
}
/* Stop ADC Conversion */
KernelStatus_t adc_stop_conversion(uint8_t instance) {
if (instance >= ADC_MAX_INSTANCES) {
return KERNEL_INVALID_PARAMETER;
}
AdcDriverState_t* driver = &adc_drivers[instance];
if (!driver->initialized) {
return KERNEL_ERROR;
}
hal_adc_stop_conversion(instance);
driver->conversion_active = false;
return KERNEL_OK;
}
/* Read ADC Channel */
KernelStatus_t adc_read_channel(uint8_t instance, uint8_t channel, uint16_t* value,
uint32_t timeout_ms) {
if (instance >= ADC_MAX_INSTANCES || value == NULL) {
return KERNEL_INVALID_PARAMETER;
}
AdcDriverState_t* driver = &adc_drivers[instance];
if (!driver->initialized) {
return KERNEL_ERROR;
}
/* Lock conversion mutex */
if (mutex_lock(&driver->conversion_mutex, timeout_ms) != KERNEL_OK) {
return KERNEL_TIMEOUT;
}
/* Configure single channel conversion */
hal_adc_configure_channel(instance, channel);
/* Start conversion */
hal_adc_start_single_conversion(instance, channel);
/* Wait for conversion complete */
if (semaphore_take(&driver->conversion_semaphore, timeout_ms) != KERNEL_OK) {
mutex_unlock(&driver->conversion_mutex);
return KERNEL_TIMEOUT;
}
/* Read value */
*value = hal_adc_read_value(instance, channel);
/* Update statistics */
driver->statistics.conversions_completed++;
/* Unlock */
mutex_unlock(&driver->conversion_mutex);
return KERNEL_OK;
}
/* Read Multiple ADC Channels */
KernelStatus_t adc_read_channels(uint8_t instance, uint16_t* values, uint8_t count,
uint32_t timeout_ms) {
if (instance >= ADC_MAX_INSTANCES || values == NULL || count == 0) {
return KERNEL_INVALID_PARAMETER;
}
AdcDriverState_t* driver = &adc_drivers[instance];
if (!driver->initialized) {
return KERNEL_ERROR;
}
/* Start conversion */
if (adc_start_conversion(instance) != KERNEL_OK) {
return KERNEL_ERROR;
}
/* Wait for all channels */
if (semaphore_take(&driver->conversion_semaphore, timeout_ms) != KERNEL_OK) {
return KERNEL_TIMEOUT;
}
/* Copy values */
memcpy(values, driver->conversion_buffer, count * sizeof(uint16_t));
return KERNEL_OK;
}
/* Start DMA Conversion */
KernelStatus_t adc_start_dma(uint8_t instance, uint16_t* buffer, uint16_t length) {
if (instance >= ADC_MAX_INSTANCES || buffer == NULL || length == 0) {
return KERNEL_INVALID_PARAMETER;
}
AdcDriverState_t* driver = &adc_drivers[instance];
if (!driver->initialized) {
return KERNEL_ERROR;
}
if (driver->dma_active) {
return KERNEL_RESOURCE_BUSY;
}
/* Configure DMA */
driver->dma_buffer = buffer;
driver->dma_length = length;
driver->dma_index = 0;
driver->dma_active = true;
/* Start DMA conversion */
hal_adc_start_dma(instance, buffer, length);
return KERNEL_OK;
}
/* ADC Interrupt Handler */
void adc_process_interrupt(uint8_t instance) {
if (instance >= ADC_MAX_INSTANCES) {
return;
}
AdcDriverState_t* driver = &adc_drivers[instance];
if (!driver->initialized) {
return;
}
uint32_t interrupt_status = hal_adc_get_interrupt_status(instance);
/* Handle conversion complete */
if (interrupt_status & ADC_INTERRUPT_CONVERSION_COMPLETE) {
if (driver->conversion_active) {
/* Store converted value */
uint16_t value = hal_adc_read_current_value(instance);
if (driver->current_channel < ADC_MAX_CHANNELS) {
driver->conversion_buffer[driver->current_channel] = value;
driver->current_channel++;
}
/* Check if all channels converted */
if (driver->current_channel >= driver->config.channel_count) {
driver->conversion_active = false;
/* Call callback */
if (driver->config.conversion_complete_callback != NULL) {
driver->config.conversion_complete_callback(
driver->conversion_buffer,
driver->config.channel_count);
}
/* Signal conversion complete */
semaphore_give(&driver->conversion_semaphore);
} else {
/* Start next channel conversion */
hal_adc_start_channel_conversion(instance,
driver->config.channels[driver->current_channel].channel);
}
}
}
/* Handle DMA complete */
if (interrupt_status & ADC_INTERRUPT_DMA_COMPLETE) {
driver->dma_active = false;
driver->statistics.dma_transfers++;
}
/* Handle watchdog */
if (interrupt_status & ADC_INTERRUPT_WATCHDOG) {
driver->statistics.watchdog_events++;
}
/* Handle errors */
if (interrupt_status & ADC_INTERRUPT_ERROR) {
driver->statistics.conversions_failed++;
driver->statistics.overrun_errors++;
}
/* Clear interrupt flags */
hal_adc_clear_interrupts(instance, interrupt_status);
}
/* Convert ADC Value to Voltage */
float adc_convert_to_voltage(uint16_t adc_value, AdcResolution_t resolution,
float reference_voltage) {
uint32_t max_value = (1 << resolution) - 1;
return ((float)adc_value / (float)max_value) * reference_voltage;
}
+228
View File
@@ -0,0 +1,228 @@
/**
* @file can_driver.c
* @brief CAN driver implementation
*/
#include "can_driver.h"
#include "isr.h"
#include <string.h>
/* CAN Driver State */
typedef struct {
bool initialized;
CanConfig_t config;
CanStatistics_t statistics;
CanMessage_t rx_fifo[CAN_MAX_RX_FIFO_DEPTH];
uint8_t rx_head;
uint8_t rx_tail;
uint8_t rx_count;
Semaphore_t rx_semaphore;
Semaphore_t tx_semaphore;
Mutex_t tx_mutex;
bool bus_off;
} CanDriverState_t;
static CanDriverState_t can_driver;
/* Initialize CAN Driver */
KernelStatus_t can_init(CanConfig_t* config) {
if (config == NULL || can_driver.initialized) {
return KERNEL_ERROR;
}
/* Copy configuration */
memcpy(&can_driver.config, config, sizeof(CanConfig_t));
/* Initialize state */
memset(&can_driver.statistics, 0, sizeof(CanStatistics_t));
can_driver.rx_head = 0;
can_driver.rx_tail = 0;
can_driver.rx_count = 0;
can_driver.bus_off = false;
/* Create synchronization primitives */
semaphore_create(&can_driver.rx_semaphore, SEMAPHORE_COUNTING, 0,
CAN_MAX_RX_FIFO_DEPTH);
semaphore_create(&can_driver.tx_semaphore, SEMAPHORE_COUNTING,
CAN_MAX_TX_MAILBOXES, CAN_MAX_TX_MAILBOXES);
mutex_create(&can_driver.tx_mutex, false);
/* Configure CAN hardware */
if (hal_can_init(&config->nominal_baudrate, config->frame_type,
config->enable_fd) != 0) {
return KERNEL_ERROR;
}
/* Configure filters */
for (uint8_t i = 0; i < config->filter_count; i++) {
if (config->filters[i].enable) {
hal_can_configure_filter(&config->filters[i]);
}
}
/* Enable CAN interrupts */
hal_can_enable_interrupts();
can_driver.initialized = true;
return KERNEL_OK;
}
/* Send CAN Message */
KernelStatus_t can_send_message(const CanMessage_t* message, uint32_t timeout_ms) {
if (!can_driver.initialized || message == NULL) {
return KERNEL_ERROR;
}
if (can_driver.bus_off) {
return KERNEL_ERROR;
}
/* Take TX semaphore with timeout */
if (semaphore_take(&can_driver.tx_semaphore, timeout_ms) != KERNEL_OK) {
can_driver.statistics.tx_overflow++;
return KERNEL_TIMEOUT;
}
/* Lock TX mutex */
if (mutex_lock(&can_driver.tx_mutex, timeout_ms) != KERNEL_OK) {
semaphore_give(&can_driver.tx_semaphore);
return KERNEL_TIMEOUT;
}
/* Send message via hardware */
uint32_t mailbox;
if (hal_can_send_message(message, &mailbox) != 0) {
mutex_unlock(&can_driver.tx_mutex);
semaphore_give(&can_driver.tx_semaphore);
can_driver.statistics.tx_errors++;
return KERNEL_ERROR;
}
/* Update statistics */
can_driver.statistics.tx_messages++;
/* Unlock TX mutex */
mutex_unlock(&can_driver.tx_mutex);
return KERNEL_OK;
}
/* Receive CAN Message */
KernelStatus_t can_receive_message(CanMessage_t* message, uint32_t timeout_ms) {
if (!can_driver.initialized || message == NULL) {
return KERNEL_ERROR;
}
/* Wait for message */
if (semaphore_take(&can_driver.rx_semaphore, timeout_ms) != KERNEL_OK) {
return KERNEL_TIMEOUT;
}
/* Get message from FIFO */
critical_section_enter();
memcpy(message, &can_driver.rx_fifo[can_driver.rx_head], sizeof(CanMessage_t));
can_driver.rx_head = (can_driver.rx_head + 1) % CAN_MAX_RX_FIFO_DEPTH;
can_driver.rx_count--;
critical_section_exit();
can_driver.statistics.rx_messages++;
return KERNEL_OK;
}
/* CAN Interrupt Handler */
void can_process_interrupt(void) {
uint32_t interrupt_status = hal_can_get_interrupt_status();
/* Check for received messages */
if (interrupt_status & CAN_INTERRUPT_RX) {
CanMessage_t message;
while (hal_can_receive_message(&message) == 0) {
/* Add to RX FIFO */
critical_section_enter();
if (can_driver.rx_count < CAN_MAX_RX_FIFO_DEPTH) {
memcpy(&can_driver.rx_fifo[can_driver.rx_tail], &message,
sizeof(CanMessage_t));
can_driver.rx_tail = (can_driver.rx_tail + 1) % CAN_MAX_RX_FIFO_DEPTH;
can_driver.rx_count++;
/* Signal message available */
semaphore_give(&can_driver.rx_semaphore);
/* Call callback if registered */
if (can_driver.config.rx_callback != NULL) {
can_driver.config.rx_callback(&message);
}
} else {
can_driver.statistics.rx_overflow++;
}
critical_section_exit();
}
}
/* Check for transmit complete */
if (interrupt_status & CAN_INTERRUPT_TX) {
uint32_t mailbox = hal_can_get_tx_mailbox();
/* Release TX semaphore */
semaphore_give(&can_driver.tx_semaphore);
/* Call callback if registered */
if (can_driver.config.tx_callback != NULL) {
can_driver.config.tx_callback(mailbox, true);
}
}
/* Check for errors */
if (interrupt_status & CAN_INTERRUPT_ERROR) {
uint32_t error_code = hal_can_get_error_status();
can_driver.statistics.rx_errors++;
can_driver.statistics.tx_errors++;
/* Check for bus-off */
if (error_code & CAN_ERROR_BUS_OFF) {
can_driver.bus_off = true;
can_driver.statistics.bus_off_count++;
}
/* Call error callback */
if (can_driver.config.error_callback != NULL) {
can_driver.config.error_callback(error_code);
}
}
}
/* Recover from Bus-Off */
KernelStatus_t can_recover_bus_off(void) {
if (!can_driver.initialized) {
return KERNEL_ERROR;
}
/* Reset CAN controller */
hal_can_reset();
/* Reconfigure */
hal_can_init(&can_driver.config.nominal_baudrate,
can_driver.config.frame_type, can_driver.config.enable_fd);
/* Clear bus-off flag */
can_driver.bus_off = false;
return KERNEL_OK;
}
/* Get CAN Statistics */
KernelStatus_t can_get_statistics(CanStatistics_t* stats) {
if (stats == NULL) {
return KERNEL_ERROR;
}
memcpy(stats, &can_driver.statistics, sizeof(CanStatistics_t));
return KERNEL_OK;
}
+178
View File
@@ -0,0 +1,178 @@
/**
* @file gpio_driver.c
* @brief GPIO driver implementation
*/
#include "gpio_driver.h"
#include "isr.h"
#include <string.h>
/* GPIO Driver State */
typedef struct {
bool initialized;
GpioPinConfig_t pins[GPIO_MAX_PORTS][GPIO_MAX_PINS_PER_PORT];
GpioInterruptConfig_t interrupts[GPIO_MAX_INTERRUPTS];
uint8_t interrupt_count;
Mutex_t mutex;
} GpioDriverState_t;
static GpioDriverState_t gpio_driver;
/* Initialize GPIO Driver */
KernelStatus_t gpio_init(const GpioPinConfig_t* config) {
if (config == NULL) {
return KERNEL_INVALID_PARAMETER;
}
if (!gpio_driver.initialized) {
memset(&gpio_driver, 0, sizeof(GpioDriverState_t));
mutex_create(&gpio_driver.mutex, false);
gpio_driver.initialized = true;
}
/* Validate parameters */
if (config->port >= GPIO_MAX_PORTS || config->pin >= GPIO_MAX_PINS_PER_PORT) {
return KERNEL_INVALID_PARAMETER;
}
/* Store pin configuration */
gpio_driver.pins[config->port][config->pin] = *config;
/* Configure GPIO hardware */
hal_gpio_init(config->port, config->pin, config->mode);
/* Configure output type */
if (config->mode == GPIO_MODE_OUTPUT || config->mode == GPIO_MODE_ALTERNATE) {
hal_gpio_set_output_type(config->port, config->pin, config->output_type);
}
/* Configure pull */
hal_gpio_set_pull(config->port, config->pin, config->pull);
/* Configure speed */
hal_gpio_set_speed(config->port, config->pin, config->speed);
/* Configure alternate function */
if (config->mode == GPIO_MODE_ALTERNATE) {
hal_gpio_set_alternate_function(config->port, config->pin,
config->alternate_function);
}
return KERNEL_OK;
}
/* Set GPIO Mode */
KernelStatus_t gpio_set_mode(uint8_t port, uint8_t pin, GpioMode_t mode) {
if (port >= GPIO_MAX_PORTS || pin >= GPIO_MAX_PINS_PER_PORT) {
return KERNEL_INVALID_PARAMETER;
}
gpio_driver.pins[port][pin].mode = mode;
hal_gpio_init(port, pin, mode);
return KERNEL_OK;
}
/* Write GPIO Pin */
KernelStatus_t gpio_write(uint8_t port, uint8_t pin, bool value) {
if (port >= GPIO_MAX_PORTS || pin >= GPIO_MAX_PINS_PER_PORT) {
return KERNEL_INVALID_PARAMETER;
}
if (gpio_driver.pins[port][pin].mode != GPIO_MODE_OUTPUT) {
return KERNEL_ERROR;
}
hal_gpio_write(port, pin, value);
return KERNEL_OK;
}
/* Write GPIO Port */
KernelStatus_t gpio_write_port(uint8_t port, uint16_t value) {
if (port >= GPIO_MAX_PORTS) {
return KERNEL_INVALID_PARAMETER;
}
hal_gpio_write_port(port, value);
return KERNEL_OK;
}
/* Read GPIO Pin */
bool gpio_read(uint8_t port, uint8_t pin) {
if (port >= GPIO_MAX_PORTS || pin >= GPIO_MAX_PINS_PER_PORT) {
return false;
}
return hal_gpio_read(port, pin);
}
/* Read GPIO Port */
uint16_t gpio_read_port(uint8_t port) {
if (port >= GPIO_MAX_PORTS) {
return 0;
}
return hal_gpio_read_port(port);
}
/* Toggle GPIO Pin */
KernelStatus_t gpio_toggle(uint8_t port, uint8_t pin) {
if (port >= GPIO_MAX_PORTS || pin >= GPIO_MAX_PINS_PER_PORT) {
return KERNEL_INVALID_PARAMETER;
}
hal_gpio_toggle(port, pin);
return KERNEL_OK;
}
/* Configure GPIO Interrupt */
KernelStatus_t gpio_configure_interrupt(const GpioInterruptConfig_t* config) {
if (config == NULL || config->callback == NULL) {
return KERNEL_INVALID_PARAMETER;
}
if (config->port >= GPIO_MAX_PORTS || config->pin >= GPIO_MAX_PINS_PER_PORT) {
return KERNEL_INVALID_PARAMETER;
}
if (gpio_driver.interrupt_count >= GPIO_MAX_INTERRUPTS) {
return KERNEL_OUT_OF_MEMORY;
}
/* Store interrupt configuration */
gpio_driver.interrupts[gpio_driver.interrupt_count] = *config;
gpio_driver.interrupt_count++;
/* Configure hardware interrupt */
hal_gpio_configure_interrupt(config->port, config->pin, config->trigger);
return KERNEL_OK;
}
/* GPIO Interrupt Handler */
void gpio_process_interrupt(uint8_t port) {
if (port >= GPIO_MAX_PORTS) {
return;
}
/* Get interrupt status */
uint16_t interrupt_status = hal_gpio_get_interrupt_status(port);
/* Process each interrupt */
for (uint8_t pin = 0; pin < GPIO_MAX_PINS_PER_PORT; pin++) {
if (interrupt_status & (1 << pin)) {
/* Find matching interrupt configuration */
for (uint8_t i = 0; i < gpio_driver.interrupt_count; i++) {
if (gpio_driver.interrupts[i].port == port &&
gpio_driver.interrupts[i].pin == pin) {
/* Call callback */
gpio_driver.interrupts[i].callback(port, pin);
break;
}
}
/* Clear interrupt flag */
hal_gpio_clear_interrupt(port, pin);
}
}
}
+301
View File
@@ -0,0 +1,301 @@
/**
* @file i2c_driver.c
* @brief I2C driver implementation
*/
#include "i2c_driver.h"
#include "isr.h"
#include <string.h>
/* I2C Driver State */
typedef struct {
bool initialized;
I2cConfig_t config;
I2cStatistics_t statistics;
I2cMessage_t current_message;
uint16_t transfer_index;
bool transfer_active;
Semaphore_t transfer_semaphore;
Mutex_t transfer_mutex;
void* user_data;
} I2cDriverState_t;
static I2cDriverState_t i2c_drivers[I2C_MAX_INSTANCES];
/* Initialize I2C Driver */
KernelStatus_t i2c_init(uint8_t instance, I2cConfig_t* config) {
if (instance >= I2C_MAX_INSTANCES || config == NULL) {
return KERNEL_INVALID_PARAMETER;
}
I2cDriverState_t* driver = &i2c_drivers[instance];
if (driver->initialized) {
return KERNEL_ERROR;
}
/* Copy configuration */
memcpy(&driver->config, config, sizeof(I2cConfig_t));
/* Initialize state */
memset(&driver->statistics, 0, sizeof(I2cStatistics_t));
driver->transfer_index = 0;
driver->transfer_active = false;
/* Create synchronization primitives */
semaphore_create(&driver->transfer_semaphore, SEMAPHORE_BINARY, 1, 1);
mutex_create(&driver->transfer_mutex, false);
/* Initialize I2C hardware */
if (hal_i2c_init(instance, config) != 0) {
return KERNEL_ERROR;
}
/* Enable interrupts */
hal_i2c_enable_interrupts(instance);
driver->initialized = true;
return KERNEL_OK;
}
/* I2C Transfer */
KernelStatus_t i2c_transfer(uint8_t instance, const I2cMessage_t* message,
uint32_t timeout_ms) {
if (instance >= I2C_MAX_INSTANCES || message == NULL ||
message->data == NULL || message->length == 0) {
return KERNEL_INVALID_PARAMETER;
}
I2cDriverState_t* driver = &i2c_drivers[instance];
if (!driver->initialized) {
return KERNEL_ERROR;
}
if (driver->transfer_active) {
return KERNEL_RESOURCE_BUSY;
}
/* Take transfer semaphore */
if (semaphore_take(&driver->transfer_semaphore, timeout_ms) != KERNEL_OK) {
return KERNEL_TIMEOUT;
}
/* Lock transfer mutex */
if (mutex_lock(&driver->transfer_mutex, timeout_ms) != KERNEL_OK) {
semaphore_give(&driver->transfer_semaphore);
return KERNEL_TIMEOUT;
}
/* Set up transfer */
memcpy(&driver->current_message, message, sizeof(I2cMessage_t));
driver->transfer_index = 0;
driver->transfer_active = true;
/* Start transfer */
if (message->direction == I2C_DIRECTION_WRITE) {
hal_i2c_start_write(instance, message->slave_address);
} else {
hal_i2c_start_read(instance, message->slave_address);
}
/* Wait for completion */
if (timeout_ms > 0) {
TickType_t start_tick = kernel_get_tick_count();
while (driver->transfer_active) {
if ((kernel_get_tick_count() - start_tick) > timeout_ms) {
/* Timeout - abort transfer */
hal_i2c_abort_transfer(instance);
driver->transfer_active = false;
mutex_unlock(&driver->transfer_mutex);
semaphore_give(&driver->transfer_semaphore);
driver->statistics.timeout_errors++;
return KERNEL_TIMEOUT;
}
kernel_delay(1);
}
}
/* Update statistics */
driver->statistics.transfers_completed++;
driver->statistics.bytes_transferred += message->length;
/* Unlock */
mutex_unlock(&driver->transfer_mutex);
semaphore_give(&driver->transfer_semaphore);
return KERNEL_OK;
}
/* I2C Write */
KernelStatus_t i2c_write(uint8_t instance, uint16_t slave_address,
const uint8_t* data, uint16_t length, uint32_t timeout_ms) {
I2cMessage_t message = {
.slave_address = slave_address,
.direction = I2C_DIRECTION_WRITE,
.data = (uint8_t*)data,
.length = length,
.generate_stop = true,
.generate_restart = false
};
return i2c_transfer(instance, &message, timeout_ms);
}
/* I2C Read */
KernelStatus_t i2c_read(uint8_t instance, uint16_t slave_address,
uint8_t* data, uint16_t length, uint32_t timeout_ms) {
I2cMessage_t message = {
.slave_address = slave_address,
.direction = I2C_DIRECTION_READ,
.data = data,
.length = length,
.generate_stop = true,
.generate_restart = false
};
return i2c_transfer(instance, &message, timeout_ms);
}
/* I2C Write/Read */
KernelStatus_t i2c_write_read(uint8_t instance, uint16_t slave_address,
const uint8_t* tx_data, uint16_t tx_length,
uint8_t* rx_data, uint16_t rx_length,
uint32_t timeout_ms) {
/* First write */
I2cMessage_t write_message = {
.slave_address = slave_address,
.direction = I2C_DIRECTION_WRITE,
.data = (uint8_t*)tx_data,
.length = tx_length,
.generate_stop = false,
.generate_restart = true
};
KernelStatus_t status = i2c_transfer(instance, &write_message, timeout_ms);
if (status != KERNEL_OK) {
return status;
}
/* Then read */
I2cMessage_t read_message = {
.slave_address = slave_address,
.direction = I2C_DIRECTION_READ,
.data = rx_data,
.length = rx_length,
.generate_stop = true,
.generate_restart = false
};
return i2c_transfer(instance, &read_message, timeout_ms);
}
/* Check if Device is Ready */
bool i2c_is_device_ready(uint8_t instance, uint16_t slave_address) {
if (instance >= I2C_MAX_INSTANCES) {
return false;
}
I2cDriverState_t* driver = &i2c_drivers[instance];
if (!driver->initialized) {
return false;
}
return hal_i2c_check_device(instance, slave_address);
}
/* I2C Interrupt Handler */
void i2c_process_interrupt(uint8_t instance) {
if (instance >= I2C_MAX_INSTANCES) {
return;
}
I2cDriverState_t* driver = &i2c_drivers[instance];
if (!driver->initialized || !driver->transfer_active) {
return;
}
uint32_t interrupt_status = hal_i2c_get_interrupt_status(instance);
/* Handle address sent */
if (interrupt_status & I2C_INTERRUPT_ADDRESS_SENT) {
if (driver->current_message.direction == I2C_DIRECTION_READ) {
hal_i2c_prepare_receive(instance);
}
}
/* Handle data transfer */
if (interrupt_status & I2C_INTERRUPT_DATA) {
if (driver->transfer_index < driver->current_message.length) {
if (driver->current_message.direction == I2C_DIRECTION_WRITE) {
/* Transmit next byte */
uint8_t byte = driver->current_message.data[driver->transfer_index];
hal_i2c_transmit_byte(instance, byte);
} else {
/* Receive next byte */
driver->current_message.data[driver->transfer_index] =
hal_i2c_receive_byte(instance);
}
driver->transfer_index++;
/* Check if last byte */
if (driver->transfer_index == driver->current_message.length) {
if (driver->current_message.generate_stop) {
hal_i2c_generate_stop(instance);
}
}
}
}
/* Handle NACK */
if (interrupt_status & I2C_INTERRUPT_NACK) {
driver->transfer_active = false;
driver->statistics.nack_errors++;
if (driver->config.transfer_complete_callback != NULL) {
driver->config.transfer_complete_callback(I2C_TRANSFER_NACK,
driver->user_data);
}
semaphore_give(&driver->transfer_semaphore);
}
/* Handle transfer complete */
if (interrupt_status & I2C_INTERRUPT_COMPLETE) {
driver->transfer_active = false;
if (driver->config.transfer_complete_callback != NULL) {
driver->config.transfer_complete_callback(I2C_TRANSFER_COMPLETE,
driver->user_data);
}
semaphore_give(&driver->transfer_semaphore);
}
/* Handle errors */
if (interrupt_status & I2C_INTERRUPT_ERROR) {
driver->transfer_active = false;
driver->statistics.transfers_failed++;
uint32_t error = hal_i2c_get_error(instance);
if (error & I2C_ERROR_ARBITRATION_LOST) {
driver->statistics.arbitration_lost++;
}
if (error & I2C_ERROR_BUS) {
driver->statistics.bus_errors++;
}
if (driver->config.transfer_complete_callback != NULL) {
driver->config.transfer_complete_callback(I2C_TRANSFER_ERROR,
driver->user_data);
}
semaphore_give(&driver->transfer_semaphore);
}
}
+328
View File
@@ -0,0 +1,328 @@
/**
* @file pwm_driver.c
* @brief PWM driver implementation
*/
#include "pwm_driver.h"
#include "isr.h"
#include <string.h>
/* PWM Driver State */
typedef struct {
bool initialized;
PwmConfig_t config;
PwmStatistics_t statistics;
uint32_t current_duty_cycles[PWM_MAX_CHANNELS];
bool channel_enabled[PWM_MAX_CHANNELS];
uint32_t fault_flags;
Mutex_t mutex;
} PwmDriverState_t;
static PwmDriverState_t pwm_drivers[PWM_MAX_INSTANCES];
/* Initialize PWM Driver */
KernelStatus_t pwm_init(uint8_t instance, PwmConfig_t* config) {
if (instance >= PWM_MAX_INSTANCES || config == NULL) {
return KERNEL_INVALID_PARAMETER;
}
PwmDriverState_t* driver = &pwm_drivers[instance];
if (driver->initialized) {
return KERNEL_ERROR;
}
/* Copy configuration */
memcpy(&driver->config, config, sizeof(PwmConfig_t));
/* Initialize state */
memset(&driver->statistics, 0, sizeof(PwmStatistics_t));
driver->fault_flags = 0;
/* Initialize channel states */
for (uint8_t i = 0; i < PWM_MAX_CHANNELS; i++) {
driver->current_duty_cycles[i] = 0;
driver->channel_enabled[i] = false;
}
/* Create mutex */
mutex_create(&driver->mutex, false);
/* Initialize PWM hardware */
if (hal_pwm_init(instance, config) != 0) {
return KERNEL_ERROR;
}
/* Configure channels */
for (uint8_t i = 0; i < config->channel_count; i++) {
driver->current_duty_cycles[config->channels[i].channel] =
config->channels[i].duty_cycle;
driver->channel_enabled[config->channels[i].channel] = true;
hal_pwm_configure_channel(instance, &config->channels[i]);
}
/* Configure fault protection */
if (config->enable_fault_protection) {
hal_pwm_configure_fault(instance, config->fault_action);
}
/* Enable interrupts */
hal_pwm_enable_interrupts(instance);
driver->initialized = true;
return KERNEL_OK;
}
/* Start PWM */
KernelStatus_t pwm_start(uint8_t instance) {
if (instance >= PWM_MAX_INSTANCES) {
return KERNEL_INVALID_PARAMETER;
}
PwmDriverState_t* driver = &pwm_drivers[instance];
if (!driver->initialized) {
return KERNEL_ERROR;
}
hal_pwm_start(instance);
return KERNEL_OK;
}
/* Stop PWM */
KernelStatus_t pwm_stop(uint8_t instance) {
if (instance >= PWM_MAX_INSTANCES) {
return KERNEL_INVALID_PARAMETER;
}
PwmDriverState_t* driver = &pwm_drivers[instance];
if (!driver->initialized) {
return KERNEL_ERROR;
}
hal_pwm_stop(instance);
return KERNEL_OK;
}
/* Set PWM Duty Cycle */
KernelStatus_t pwm_set_duty_cycle(uint8_t instance, uint8_t channel,
uint32_t duty_cycle) {
if (instance >= PWM_MAX_INSTANCES || channel >= PWM_MAX_CHANNELS) {
return KERNEL_INVALID_PARAMETER;
}
if (duty_cycle > PWM_MAX_DUTY_CYCLE) {
return KERNEL_INVALID_PARAMETER;
}
PwmDriverState_t* driver = &pwm_drivers[instance];
if (!driver->initialized) {
return KERNEL_ERROR;
}
/* Lock mutex */
if (mutex_lock(&driver->mutex, 100) != KERNEL_OK) {
return KERNEL_TIMEOUT;
}
/* Update duty cycle */
driver->current_duty_cycles[channel] = duty_cycle;
driver->statistics.duty_cycle_updates++;
/* Update hardware */
hal_pwm_set_duty_cycle(instance, channel, duty_cycle);
/* Unlock mutex */
mutex_unlock(&driver->mutex);
return KERNEL_OK;
}
/* Set PWM Frequency */
KernelStatus_t pwm_set_frequency(uint8_t instance, uint32_t frequency_hz) {
if (instance >= PWM_MAX_INSTANCES || frequency_hz == 0) {
return KERNEL_INVALID_PARAMETER;
}
PwmDriverState_t* driver = &pwm_drivers[instance];
if (!driver->initialized) {
return KERNEL_ERROR;
}
/* Lock mutex */
if (mutex_lock(&driver->mutex, 100) != KERNEL_OK) {
return KERNEL_TIMEOUT;
}
/* Update frequency */
driver->config.frequency_hz = frequency_hz;
/* Update hardware */
hal_pwm_set_frequency(instance, frequency_hz);
/* Unlock mutex */
mutex_unlock(&driver->mutex);
return KERNEL_OK;
}
/* Set PWM Dead Time */
KernelStatus_t pwm_set_dead_time(uint8_t instance, uint8_t channel,
const PwmDeadTime_t* dead_time) {
if (instance >= PWM_MAX_INSTANCES || channel >= PWM_MAX_CHANNELS ||
dead_time == NULL) {
return KERNEL_INVALID_PARAMETER;
}
PwmDriverState_t* driver = &pwm_drivers[instance];
if (!driver->initialized) {
return KERNEL_ERROR;
}
/* Lock mutex */
if (mutex_lock(&driver->mutex, 100) != KERNEL_OK) {
return KERNEL_TIMEOUT;
}
/* Update dead time */
driver->config.channels[channel].dead_time = *dead_time;
/* Update hardware */
hal_pwm_set_dead_time(instance, channel, dead_time);
/* Unlock mutex */
mutex_unlock(&driver->mutex);
return KERNEL_OK;
}
/* Enable PWM Channel */
KernelStatus_t pwm_enable_channel(uint8_t instance, uint8_t channel) {
if (instance >= PWM_MAX_INSTANCES || channel >= PWM_MAX_CHANNELS) {
return KERNEL_INVALID_PARAMETER;
}
PwmDriverState_t* driver = &pwm_drivers[instance];
if (!driver->initialized) {
return KERNEL_ERROR;
}
driver->channel_enabled[channel] = true;
hal_pwm_enable_channel(instance, channel);
return KERNEL_OK;
}
/* Disable PWM Channel */
KernelStatus_t pwm_disable_channel(uint8_t instance, uint8_t channel) {
if (instance >= PWM_MAX_INSTANCES || channel >= PWM_MAX_CHANNELS) {
return KERNEL_INVALID_PARAMETER;
}
PwmDriverState_t* driver = &pwm_drivers[instance];
if (!driver->initialized) {
return KERNEL_ERROR;
}
driver->channel_enabled[channel] = false;
hal_pwm_disable_channel(instance, channel);
return KERNEL_OK;
}
/* Clear PWM Fault */
KernelStatus_t pwm_clear_fault(uint8_t instance) {
if (instance >= PWM_MAX_INSTANCES) {
return KERNEL_INVALID_PARAMETER;
}
PwmDriverState_t* driver = &pwm_drivers[instance];
if (!driver->initialized) {
return KERNEL_ERROR;
}
driver->fault_flags = 0;
hal_pwm_clear_fault(instance);
return KERNEL_OK;
}
/* PWM Interrupt Handler */
void pwm_process_interrupt(uint8_t instance) {
if (instance >= PWM_MAX_INSTANCES) {
return;
}
PwmDriverState_t* driver = &pwm_drivers[instance];
if (!driver->initialized) {
return;
}
uint32_t interrupt_status = hal_pwm_get_interrupt_status(instance);
/* Handle period elapsed */
if (interrupt_status & PWM_INTERRUPT_PERIOD_ELAPSED) {
driver->statistics.period_elapsed_count++;
/* Call callback */
if (driver->config.period_elapsed_callback != NULL) {
driver->config.period_elapsed_callback(instance);
}
}
/* Handle fault */
if (interrupt_status & PWM_INTERRUPT_FAULT) {
driver->statistics.fault_events++;
driver->fault_flags = hal_pwm_get_fault_flags(instance);
/* Apply fault action */
hal_pwm_apply_fault_action(instance, driver->config.fault_action);
/* Call callback */
if (driver->config.fault_callback != NULL) {
driver->config.fault_callback(instance, driver->fault_flags);
}
}
/* Clear interrupt flags */
hal_pwm_clear_interrupts(instance, interrupt_status);
}
/* Get PWM Statistics */
KernelStatus_t pwm_get_statistics(uint8_t instance, PwmStatistics_t* stats) {
if (instance >= PWM_MAX_INSTANCES || stats == NULL) {
return KERNEL_INVALID_PARAMETER;
}
memcpy(stats, &pwm_drivers[instance].statistics, sizeof(PwmStatistics_t));
return KERNEL_OK;
}
/* Get PWM Duty Cycle */
uint32_t pwm_get_duty_cycle(uint8_t instance, uint8_t channel) {
if (instance >= PWM_MAX_INSTANCES || channel >= PWM_MAX_CHANNELS) {
return 0;
}
return pwm_drivers[instance].current_duty_cycles[channel];
}
/* Get PWM Frequency */
uint32_t pwm_get_frequency(uint8_t instance) {
if (instance >= PWM_MAX_INSTANCES) {
return 0;
}
return pwm_drivers[instance].config.frequency_hz;
}
+320
View File
@@ -0,0 +1,320 @@
/**
* @file spi_driver.c
* @brief SPI driver implementation
*/
#include "spi_driver.h"
#include "isr.h"
#include <string.h>
/* SPI Driver State */
typedef struct {
bool initialized;
SpiConfig_t config;
SpiStatistics_t statistics;
uint8_t tx_buffer[SPI_MAX_BUFFER_SIZE];
uint8_t rx_buffer[SPI_MAX_BUFFER_SIZE];
uint16_t transfer_length;
uint16_t transfer_index;
bool transfer_active;
bool use_dma;
Semaphore_t transfer_semaphore;
Mutex_t transfer_mutex;
void* user_data;
} SpiDriverState_t;
static SpiDriverState_t spi_drivers[SPI_MAX_INSTANCES];
/* Initialize SPI Driver */
KernelStatus_t spi_init(uint8_t instance, SpiConfig_t* config) {
if (instance >= SPI_MAX_INSTANCES || config == NULL) {
return KERNEL_INVALID_PARAMETER;
}
SpiDriverState_t* driver = &spi_drivers[instance];
if (driver->initialized) {
return KERNEL_ERROR;
}
/* Copy configuration */
memcpy(&driver->config, config, sizeof(SpiConfig_t));
/* Initialize state */
memset(&driver->statistics, 0, sizeof(SpiStatistics_t));
driver->transfer_length = 0;
driver->transfer_index = 0;
driver->transfer_active = false;
driver->use_dma = config->use_dma;
/* Create synchronization primitives */
semaphore_create(&driver->transfer_semaphore, SEMAPHORE_BINARY, 1, 1);
mutex_create(&driver->transfer_mutex, false);
/* Initialize SPI hardware */
if (hal_spi_init(instance, config) != 0) {
return KERNEL_ERROR;
}
/* Enable interrupts if not using DMA */
if (!driver->use_dma) {
hal_spi_enable_interrupts(instance);
}
driver->initialized = true;
return KERNEL_OK;
}
/* SPI Transfer */
KernelStatus_t spi_transfer(uint8_t instance, const SpiTransaction_t* transaction,
uint32_t timeout_ms) {
if (instance >= SPI_MAX_INSTANCES || transaction == NULL ||
transaction->length == 0) {
return KERNEL_INVALID_PARAMETER;
}
SpiDriverState_t* driver = &spi_drivers[instance];
if (!driver->initialized) {
return KERNEL_ERROR;
}
/* Check if transfer is already active */
if (driver->transfer_active) {
return KERNEL_RESOURCE_BUSY;
}
/* Take transfer semaphore */
if (semaphore_take(&driver->transfer_semaphore, timeout_ms) != KERNEL_OK) {
return KERNEL_TIMEOUT;
}
/* Lock transfer mutex */
if (mutex_lock(&driver->transfer_mutex, timeout_ms) != KERNEL_OK) {
semaphore_give(&driver->transfer_semaphore);
return KERNEL_TIMEOUT;
}
/* Set up transfer */
driver->transfer_length = transaction->length;
driver->transfer_index = 0;
driver->transfer_active = true;
driver->user_data = transaction->user_data;
/* Copy TX data if provided */
if (transaction->tx_data != NULL) {
memcpy(driver->tx_buffer, transaction->tx_data, transaction->length);
} else {
memset(driver->tx_buffer, 0xFF, transaction->length); /* Dummy data */
}
/* Clear RX buffer */
memset(driver->rx_buffer, 0, transaction->length);
/* Select chip if hardware CS is not used */
if (!driver->config.enable_hardware_cs) {
spi_set_chip_select(instance, true);
}
/* Start transfer */
if (driver->use_dma) {
hal_spi_start_dma_transfer(instance, driver->tx_buffer, driver->rx_buffer,
transaction->length);
} else {
hal_spi_start_transfer(instance);
}
/* Wait for completion */
if (timeout_ms > 0) {
TickType_t start_tick = kernel_get_tick_count();
while (driver->transfer_active) {
if ((kernel_get_tick_count() - start_tick) > timeout_ms) {
/* Timeout - abort transfer */
hal_spi_abort_transfer(instance);
driver->transfer_active = false;
if (!driver->config.enable_hardware_cs) {
spi_set_chip_select(instance, false);
}
mutex_unlock(&driver->transfer_mutex);
semaphore_give(&driver->transfer_semaphore);
driver->statistics.timeout_errors++;
return KERNEL_TIMEOUT;
}
kernel_delay(1);
}
}
/* Copy RX data if requested */
if (transaction->rx_data != NULL) {
memcpy(transaction->rx_data, driver->rx_buffer, transaction->length);
}
/* Deselect chip */
if (!driver->config.enable_hardware_cs) {
spi_set_chip_select(instance, false);
}
/* Update statistics */
driver->statistics.transfers_completed++;
driver->statistics.bytes_transferred += transaction->length;
/* Unlock */
mutex_unlock(&driver->transfer_mutex);
semaphore_give(&driver->transfer_semaphore);
return KERNEL_OK;
}
/* SPI Transfer Asynchronously */
KernelStatus_t spi_transfer_async(uint8_t instance, const SpiTransaction_t* transaction) {
if (instance >= SPI_MAX_INSTANCES || transaction == NULL ||
transaction->length == 0) {
return KERNEL_INVALID_PARAMETER;
}
SpiDriverState_t* driver = &spi_drivers[instance];
if (!driver->initialized) {
return KERNEL_ERROR;
}
if (driver->transfer_active) {
return KERNEL_RESOURCE_BUSY;
}
/* Set up transfer */
driver->transfer_length = transaction->length;
driver->transfer_index = 0;
driver->transfer_active = true;
driver->user_data = transaction->user_data;
/* Copy TX data */
if (transaction->tx_data != NULL) {
memcpy(driver->tx_buffer, transaction->tx_data, transaction->length);
} else {
memset(driver->tx_buffer, 0xFF, transaction->length);
}
/* Select chip */
if (!driver->config.enable_hardware_cs) {
spi_set_chip_select(instance, true);
}
/* Start transfer */
if (driver->use_dma) {
hal_spi_start_dma_transfer(instance, driver->tx_buffer, driver->rx_buffer,
transaction->length);
} else {
hal_spi_start_transfer(instance);
}
return KERNEL_OK;
}
/* SPI Read */
KernelStatus_t spi_read(uint8_t instance, uint8_t* data, uint16_t length,
uint32_t timeout_ms) {
SpiTransaction_t transaction = {
.tx_data = NULL,
.rx_data = data,
.length = length,
.keep_cs_active = false,
.user_data = NULL
};
return spi_transfer(instance, &transaction, timeout_ms);
}
/* SPI Write */
KernelStatus_t spi_write(uint8_t instance, const uint8_t* data, uint16_t length,
uint32_t timeout_ms) {
SpiTransaction_t transaction = {
.tx_data = data,
.rx_data = NULL,
.length = length,
.keep_cs_active = false,
.user_data = NULL
};
return spi_transfer(instance, &transaction, timeout_ms);
}
/* SPI Read/Write */
KernelStatus_t spi_read_write(uint8_t instance, const uint8_t* tx_data,
uint8_t* rx_data, uint16_t length, uint32_t timeout_ms) {
SpiTransaction_t transaction = {
.tx_data = tx_data,
.rx_data = rx_data,
.length = length,
.keep_cs_active = false,
.user_data = NULL
};
return spi_transfer(instance, &transaction, timeout_ms);
}
/* SPI Interrupt Handler */
void spi_process_interrupt(uint8_t instance) {
if (instance >= SPI_MAX_INSTANCES) {
return;
}
SpiDriverState_t* driver = &spi_drivers[instance];
if (!driver->initialized || !driver->transfer_active) {
return;
}
/* Check if more data to transfer */
if (driver->transfer_index < driver->transfer_length) {
/* Transmit next byte */
uint8_t tx_byte = driver->tx_buffer[driver->transfer_index];
uint8_t rx_byte = hal_spi_transfer_byte(instance, tx_byte);
/* Store received byte */
if (driver->transfer_index < SPI_MAX_BUFFER_SIZE) {
driver->rx_buffer[driver->transfer_index] = rx_byte;
}
driver->transfer_index++;
} else {
/* Transfer complete */
driver->transfer_active = false;
/* Deselect chip */
if (!driver->config.enable_hardware_cs) {
spi_set_chip_select(instance, false);
}
/* Update statistics */
driver->statistics.transfers_completed++;
driver->statistics.bytes_transferred += driver->transfer_length;
/* Call callback */
if (driver->config.transfer_complete_callback != NULL) {
driver->config.transfer_complete_callback(SPI_TRANSFER_COMPLETE,
driver->user_data);
}
/* Signal completion */
semaphore_give(&driver->transfer_semaphore);
}
}
/* Set Chip Select */
void spi_set_chip_select(uint8_t instance, bool active) {
if (instance >= SPI_MAX_INSTANCES) {
return;
}
SpiDriverState_t* driver = &spi_drivers[instance];
bool cs_level = active ?
(driver->config.cs_polarity == SPI_CS_ACTIVE_LOW ? false : true) :
(driver->config.cs_polarity == SPI_CS_ACTIVE_LOW ? true : false);
gpio_write(driver->config.cs_port, driver->config.cs_pin, cs_level);
}
+325
View File
@@ -0,0 +1,325 @@
/**
* @file uart_driver.c
* @brief UART driver implementation
*/
#include "uart_driver.h"
#include "isr.h"
#include <string.h>
/* UART Driver State */
typedef struct {
bool initialized;
UartConfig_t config;
UartStatistics_t statistics;
uint8_t tx_buffer[UART_MAX_BUFFER_SIZE];
uint8_t rx_buffer[UART_MAX_BUFFER_SIZE];
uint16_t tx_head;
uint16_t tx_tail;
uint16_t rx_head;
uint16_t rx_tail;
uint16_t tx_count;
uint16_t rx_count;
Semaphore_t tx_semaphore;
Semaphore_t rx_semaphore;
Mutex_t tx_mutex;
Mutex_t rx_mutex;
} UartDriverState_t;
static UartDriverState_t uart_drivers[UART_MAX_INSTANCES];
/* Initialize UART Driver */
KernelStatus_t uart_init(uint8_t instance, UartConfig_t* config) {
if (instance >= UART_MAX_INSTANCES || config == NULL) {
return KERNEL_INVALID_PARAMETER;
}
UartDriverState_t* driver = &uart_drivers[instance];
if (driver->initialized) {
return KERNEL_ERROR;
}
/* Copy configuration */
memcpy(&driver->config, config, sizeof(UartConfig_t));
/* Initialize state */
memset(&driver->statistics, 0, sizeof(UartStatistics_t));
driver->tx_head = 0;
driver->tx_tail = 0;
driver->rx_head = 0;
driver->rx_tail = 0;
driver->tx_count = 0;
driver->rx_count = 0;
/* Create synchronization primitives */
semaphore_create(&driver->tx_semaphore, SEMAPHORE_COUNTING,
UART_MAX_BUFFER_SIZE, UART_MAX_BUFFER_SIZE);
semaphore_create(&driver->rx_semaphore, SEMAPHORE_COUNTING, 0,
UART_MAX_BUFFER_SIZE);
mutex_create(&driver->tx_mutex, false);
mutex_create(&driver->rx_mutex, false);
/* Initialize UART hardware */
if (hal_uart_init(instance, config) != 0) {
return KERNEL_ERROR;
}
/* Enable interrupts */
hal_uart_enable_interrupts(instance, true, true);
driver->initialized = true;
return KERNEL_OK;
}
/* Send Data via UART */
KernelStatus_t uart_send(uint8_t instance, const uint8_t* data, uint16_t length,
uint32_t timeout_ms) {
if (instance >= UART_MAX_INSTANCES || data == NULL || length == 0) {
return KERNEL_INVALID_PARAMETER;
}
UartDriverState_t* driver = &uart_drivers[instance];
if (!driver->initialized) {
return KERNEL_ERROR;
}
/* Lock TX mutex */
if (mutex_lock(&driver->tx_mutex, timeout_ms) != KERNEL_OK) {
return KERNEL_TIMEOUT;
}
/* Check if async transfer is in progress */
if (driver->tx_count > 0) {
mutex_unlock(&driver->tx_mutex);
return KERNEL_RESOURCE_BUSY;
}
/* Copy data to TX buffer */
uint16_t copy_length = (length < UART_MAX_BUFFER_SIZE) ? length : UART_MAX_BUFFER_SIZE;
critical_section_enter();
memcpy(driver->tx_buffer, data, copy_length);
driver->tx_head = 0;
driver->tx_tail = copy_length;
driver->tx_count = copy_length;
critical_section_exit();
/* Start transmission */
hal_uart_start_tx(instance);
/* Wait for completion if synchronous */
if (timeout_ms > 0) {
TickType_t start_tick = kernel_get_tick_count();
while (driver->tx_count > 0) {
if ((kernel_get_tick_count() - start_tick) > timeout_ms) {
mutex_unlock(&driver->tx_mutex);
driver->statistics.tx_errors++;
return KERNEL_TIMEOUT;
}
kernel_delay(1);
}
}
/* Update statistics */
driver->statistics.tx_bytes += copy_length;
/* Unlock TX mutex */
mutex_unlock(&driver->tx_mutex);
return KERNEL_OK;
}
/* Receive Data via UART */
KernelStatus_t uart_receive(uint8_t instance, uint8_t* data, uint16_t length,
uint32_t timeout_ms) {
if (instance >= UART_MAX_INSTANCES || data == NULL || length == 0) {
return KERNEL_INVALID_PARAMETER;
}
UartDriverState_t* driver = &uart_drivers[instance];
if (!driver->initialized) {
return KERNEL_ERROR;
}
/* Wait for data */
if (semaphore_take(&driver->rx_semaphore, timeout_ms) != KERNEL_OK) {
return KERNEL_TIMEOUT;
}
/* Lock RX mutex */
if (mutex_lock(&driver->rx_mutex, timeout_ms) != KERNEL_OK) {
return KERNEL_TIMEOUT;
}
/* Copy data from RX buffer */
critical_section_enter();
uint16_t copy_length = 0;
while (copy_length < length && driver->rx_count > 0) {
data[copy_length] = driver->rx_buffer[driver->rx_head];
driver->rx_head = (driver->rx_head + 1) % UART_MAX_BUFFER_SIZE;
driver->rx_count--;
copy_length++;
}
critical_section_exit();
/* Update statistics */
driver->statistics.rx_bytes += copy_length;
/* Unlock RX mutex */
mutex_unlock(&driver->rx_mutex);
return (copy_length == length) ? KERNEL_OK : KERNEL_TIMEOUT;
}
/* Send Data Asynchronously */
KernelStatus_t uart_send_async(uint8_t instance, const uint8_t* data, uint16_t length) {
if (instance >= UART_MAX_INSTANCES || data == NULL || length == 0) {
return KERNEL_INVALID_PARAMETER;
}
UartDriverState_t* driver = &uart_drivers[instance];
if (!driver->initialized) {
return KERNEL_ERROR;
}
if (driver->tx_count > 0) {
return KERNEL_RESOURCE_BUSY;
}
/* Copy data to TX buffer */
uint16_t copy_length = (length < UART_MAX_BUFFER_SIZE) ? length : UART_MAX_BUFFER_SIZE;
critical_section_enter();
memcpy(driver->tx_buffer, data, copy_length);
driver->tx_head = 0;
driver->tx_tail = copy_length;
driver->tx_count = copy_length;
critical_section_exit();
/* Start transmission */
hal_uart_start_tx(instance);
return KERNEL_OK;
}
/* UART Interrupt Handler */
void uart_process_interrupt(uint8_t instance) {
if (instance >= UART_MAX_INSTANCES) {
return;
}
UartDriverState_t* driver = &uart_drivers[instance];
if (!driver->initialized) {
return;
}
uint32_t interrupt_status = hal_uart_get_interrupt_status(instance);
/* Handle TX complete */
if (interrupt_status & UART_INTERRUPT_TX_COMPLETE) {
if (driver->tx_count > 0) {
/* Get next byte to transmit */
uint8_t byte = driver->tx_buffer[driver->tx_head];
driver->tx_head = (driver->tx_head + 1) % UART_MAX_BUFFER_SIZE;
driver->tx_count--;
/* Transmit byte */
hal_uart_transmit_byte(instance, byte);
if (driver->tx_count == 0) {
/* All data transmitted */
if (driver->config.tx_callback != NULL) {
driver->config.tx_callback();
}
hal_uart_disable_tx_interrupt(instance);
}
}
}
/* Handle RX ready */
if (interrupt_status & UART_INTERRUPT_RX_READY) {
while (hal_uart_is_rx_ready(instance)) {
uint8_t byte = hal_uart_receive_byte(instance);
/* Add to RX buffer */
critical_section_enter();
if (driver->rx_count < UART_MAX_BUFFER_SIZE) {
driver->rx_buffer[driver->rx_tail] = byte;
driver->rx_tail = (driver->rx_tail + 1) % UART_MAX_BUFFER_SIZE;
driver->rx_count++;
/* Signal data available */
semaphore_give(&driver->rx_semaphore);
/* Call callback if registered */
if (driver->config.rx_callback != NULL) {
driver->config.rx_callback(&byte, 1);
}
} else {
driver->statistics.rx_errors++;
driver->statistics.overrun_errors++;
}
critical_section_exit();
}
}
/* Handle errors */
if (interrupt_status & UART_INTERRUPT_ERROR) {
uint32_t error = hal_uart_get_error_status(instance);
if (error & UART_ERROR_PARITY) {
driver->statistics.parity_errors++;
}
if (error & UART_ERROR_FRAMING) {
driver->statistics.framing_errors++;
}
if (error & UART_ERROR_OVERRUN) {
driver->statistics.overrun_errors++;
}
if (driver->config.error_callback != NULL) {
driver->config.error_callback(error);
}
/* Clear error flags */
hal_uart_clear_errors(instance);
}
}
/* Get UART Statistics */
KernelStatus_t uart_get_statistics(uint8_t instance, UartStatistics_t* stats) {
if (instance >= UART_MAX_INSTANCES || stats == NULL) {
return KERNEL_INVALID_PARAMETER;
}
memcpy(stats, &uart_drivers[instance].statistics, sizeof(UartStatistics_t));
return KERNEL_OK;
}
/* Get RX Count */
uint16_t uart_get_rx_count(uint8_t instance) {
if (instance >= UART_MAX_INSTANCES) {
return 0;
}
return uart_drivers[instance].rx_count;
}
/* Get TX Count */
uint16_t uart_get_tx_count(uint8_t instance) {
if (instance >= UART_MAX_INSTANCES) {
return 0;
}
return uart_drivers[instance].tx_count;
}
+195
View File
@@ -0,0 +1,195 @@
/**
* @file port.c
* @brief ARM Cortex-M0 architecture specific port
* @note Cortex-M0 is used in low-power automotive applications
*/
#include "kernel.h"
#include "task.h"
#include "scheduler.h"
#include "portmacro.h"
/* Global variables for context switching */
uint32_t* current_task_sp = NULL;
uint32_t* next_task_sp = NULL;
/* Initialize Architecture Port */
void port_init(void) {
/* Configure SysTick for 1ms interrupts */
SysTick->LOAD = (SystemCoreClock / 1000) - 1;
SysTick->VAL = 0;
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
SysTick_CTRL_TICKINT_Msk |
SysTick_CTRL_ENABLE_Msk;
/* Set lowest priority for SysTick and PendSV */
NVIC_SetPriority(SysTick_IRQn, 3);
NVIC_SetPriority(PendSV_IRQn, 3);
/* Enable interrupts */
__enable_irq();
}
/* Start First Task */
void port_start_first_task(void) {
TaskHandle_t first_task = scheduler_get_current_task();
if (first_task == NULL) {
return;
}
/* Set PSP to task stack pointer */
__set_PSP((uint32_t)first_task->stack_pointer);
/* Switch to using PSP */
__set_CONTROL(0x02);
__ISB();
/* Restore context and start task */
__asm volatile (
"POP {R4-R7}\n"
"MOV R8, R4\n"
"MOV R9, R5\n"
"MOV R10, R6\n"
"MOV R11, R7\n"
"POP {R4-R7}\n"
"POP {R0-R3}\n"
"POP {R12}\n"
"POP {LR}\n"
"POP {PC}\n"
);
}
/* Context Switch Trigger */
void port_context_switch(uint32_t* current_context, uint32_t* next_context) {
current_task_sp = current_context;
next_task_sp = next_context;
/* Trigger PendSV */
SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk;
}
/* Yield from ISR */
void port_yield_from_isr(void) {
SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk;
}
/* Enter Critical Section */
void port_disable_interrupts(void) {
__disable_irq();
}
/* Exit Critical Section */
void port_enable_interrupts(void) {
__enable_irq();
}
/* Get Current Exception Number */
uint32_t port_get_current_exception(void) {
return (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) >> SCB_ICSR_VECTACTIVE_Pos;
}
/* Initialize Task Stack */
uint32_t* port_initialize_task_stack(TaskFunction_t task_function,
void* parameters,
uint32_t* stack_top) {
uint32_t* stack_ptr = stack_top;
/* Align stack to 8 bytes */
stack_ptr = (uint32_t*)((uint32_t)stack_ptr & ~0x7);
/* Initial stack frame for Cortex-M0 */
*(--stack_ptr) = 0x01000000; /* xPSR */
*(--stack_ptr) = (uint32_t)task_function; /* PC */
*(--stack_ptr) = 0xFFFFFFFD; /* LR (return to thread mode) */
*(--stack_ptr) = 0x00000000; /* R12 */
*(--stack_ptr) = 0x00000003; /* R3 */
*(--stack_ptr) = 0x00000002; /* R2 */
*(--stack_ptr) = 0x00000001; /* R1 */
*(--stack_ptr) = (uint32_t)parameters; /* R0 */
/* Additional registers */
*(--stack_ptr) = 0x0000000B; /* R11 */
*(--stack_ptr) = 0x0000000A; /* R10 */
*(--stack_ptr) = 0x00000009; /* R9 */
*(--stack_ptr) = 0x00000008; /* R8 */
*(--stack_ptr) = 0x00000007; /* R7 */
*(--stack_ptr) = 0x00000006; /* R6 */
*(--stack_ptr) = 0x00000005; /* R5 */
*(--stack_ptr) = 0x00000004; /* R4 */
return stack_ptr;
}
/* SysTick Handler */
void SysTick_Handler(void) {
/* Increment tick count */
extern void kernel_tick_handler(void);
kernel_tick_handler();
}
/* PendSV Handler */
void PendSV_Handler(void) {
/* Save current context */
__asm volatile (
"MRS R0, PSP\n"
"SUBS R0, R0, #32\n"
"STMIA R0!, {R4-R7}\n"
"MOV R4, R8\n"
"MOV R5, R9\n"
"MOV R6, R10\n"
"MOV R7, R11\n"
"STMIA R0!, {R4-R7}\n"
"SUBS R0, R0, #32\n"
"LDR R1, =current_task_sp\n"
"STR R0, [R1]\n"
);
/* Load next context */
__asm volatile (
"LDR R0, =next_task_sp\n"
"LDR R1, [R0]\n"
"LDMIA R1!, {R4-R7}\n"
"MOV R8, R4\n"
"MOV R9, R5\n"
"MOV R10, R6\n"
"MOV R11, R7\n"
"LDMIA R1!, {R4-R7}\n"
"MSR PSP, R1\n"
"BX LR\n"
);
}
/* SVC Handler */
void SVC_Handler(void) {
/* Handle system calls */
__asm volatile (
"TST LR, #4\n"
"ITE EQ\n"
"MRSEQ R0, MSP\n"
"MRSNE R0, PSP\n"
"LDR R0, [R0, #24]\n"
"LDRB R0, [R0, #-2]\n"
"BX LR\n"
);
}
/* Hard Fault Handler */
void HardFault_Handler(void) {
/* Save fault information */
uint32_t fault_address;
uint32_t fault_status;
__asm volatile (
"MRS %0, BFAR\n"
"MRS %1, BFSR\n"
: "=r" (fault_address), "=r" (fault_status)
);
/* Call fault handler */
extern void fault_handler_process(uint32_t type, uint32_t address, uint32_t status);
fault_handler_process(1, fault_address, fault_status);
/* Infinite loop */
while(1);
}
+113
View File
@@ -0,0 +1,113 @@
/**
* @file port_asm.s
* @brief ARM Cortex-M0 assembly routines
*/
.syntax unified
.thumb
.arch armv6-m
.section .text
/* Global symbols */
.global current_task_sp
.global next_task_sp
.global port_context_switch
.global port_start_first_task
.global port_initialize_task_stack
/* Variables */
.section .bss
.align 2
current_task_sp: .word 0
next_task_sp: .word 0
.section .text
.thumb_func
/* Start First Task */
port_start_first_task:
/* Load task stack pointer */
ldr r0, =next_task_sp
ldr r1, [r0]
/* Set PSP */
msr PSP, r1
/* Switch to PSP */
movs r0, #2
msr CONTROL, r0
isb
/* Restore context */
pop {r4-r7}
mov r8, r4
mov r9, r5
mov r10, r6
mov r11, r7
pop {r4-r7}
pop {r0-r3}
pop {r12}
pop {lr}
pop {pc}
/* PendSV Handler */
PendSV_Handler:
/* Save context */
mrs r0, PSP
subs r0, r0, #32
stmia r0!, {r4-r7}
mov r4, r8
mov r5, r9
mov r6, r10
mov r7, r11
stmia r0!, {r4-r7}
subs r0, r0, #32
ldr r1, =current_task_sp
str r0, [r1]
/* Load next context */
ldr r0, =next_task_sp
ldr r1, [r0]
ldmia r1!, {r4-r7}
mov r8, r4
mov r9, r5
mov r10, r6
mov r11, r7
ldmia r1!, {r4-r7}
msr PSP, r1
bx lr
/* SVC Handler */
SVC_Handler:
tst lr, #4
ite eq
mrseq r0, MSP
mrsne r0, PSP
ldr r0, [r0, #24]
ldrb r0, [r0, #-2]
bx lr
/* Hard Fault Handler */
HardFault_Handler:
/* Save registers */
mrs r0, PSP
stmdb r0!, {r4-r7}
mov r4, r8
mov r5, r9
mov r6, r10
mov r7, r11
stmdb r0!, {r4-r7}
/* Get fault information */
mrs r0, BFAR
mrs r1, BFSR
/* Call fault handler */
movs r2, #1
bl fault_handler_process
/* Infinite loop */
b .
.end
+40
View File
@@ -0,0 +1,40 @@
/**
* @file portmacro.h
* @brief ARM Cortex-M0 specific macros
*/
#ifndef PORTMACRO_H
#define PORTMACRO_H
#include <stdint.h>
/* Data Types */
typedef uint32_t port_stack_type_t;
typedef uint32_t port_base_type_t;
/* Architecture Constants */
#define PORT_STACK_GROWTH_DIRECTION (-1)
#define PORT_BYTE_ALIGNMENT 8
#define PORT_MAX_SYSCALL_INTERRUPT_PRIORITY 3
/* Critical Section Macros */
#define portENTER_CRITICAL() __disable_irq()
#define portEXIT_CRITICAL() __enable_irq()
/* Interrupt Control */
#define portENABLE_INTERRUPTS() __enable_irq()
#define portDISABLE_INTERRUPTS() __disable_irq()
/* Context Switch */
#define portYIELD() SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk
#define portYIELD_FROM_ISR() SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk
/* Memory Barriers */
#define portMEMORY_BARRIER() __asm volatile("DMB")
#define portSYNC_BARRIER() __asm volatile("DSB")
#define portINSTRUCTION_BARRIER() __asm volatile("ISB")
/* NOP */
#define portNOP() __asm volatile("NOP")
#endif /* PORTMACRO_H */
+222
View File
@@ -0,0 +1,222 @@
/**
* @file port.c
* @brief ARM Cortex-M3 architecture specific port
* @note Cortex-M3 is widely used in automotive ECUs
*/
#include "kernel.h"
#include "task.h"
#include "scheduler.h"
#include "portmacro.h"
/* Context storage */
uint32_t* current_task_sp = NULL;
uint32_t* next_task_sp = NULL;
/* Exception priorities */
#define SYSTICK_PRIORITY 0xFF
#define PENDSV_PRIORITY 0xFF
#define SVC_PRIORITY 0x00
/* Initialize Architecture Port */
void port_init(void) {
/* Set priority grouping - 4 bits preemption, 0 bits sub-priority */
NVIC_SetPriorityGrouping(4);
/* Configure SysTick */
SysTick->LOAD = (SystemCoreClock / 1000) - 1;
SysTick->VAL = 0;
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
SysTick_CTRL_TICKINT_Msk |
SysTick_CTRL_ENABLE_Msk;
/* Set exception priorities */
NVIC_SetPriority(SysTick_IRQn, SYSTICK_PRIORITY);
NVIC_SetPriority(PendSV_IRQn, PENDSV_PRIORITY);
NVIC_SetPriority(SVCall_IRQn, SVC_PRIORITY);
/* Enable faults */
SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk |
SCB_SHCSR_BUSFAULTENA_Msk |
SCB_SHCSR_USGFAULTENA_Msk;
}
/* Start First Task */
void port_start_first_task(void) {
TaskHandle_t first_task = scheduler_get_current_task();
if (first_task == NULL) {
return;
}
/* Set PSP */
__set_PSP((uint32_t)first_task->stack_pointer);
/* Switch to PSP */
__set_CONTROL(0x02);
__ISB();
/* Restore context */
__asm volatile (
"LDMIA R0!, {R4-R11}\n"
"MSR PSP, R0\n"
"MOV LR, #0xFFFFFFFD\n"
"BX LR\n"
);
}
/* Context Switch */
void port_context_switch(uint32_t* current_context, uint32_t* next_context) {
current_task_sp = current_context;
next_task_sp = next_context;
/* Trigger PendSV */
SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk;
/* Data synchronization barrier */
__DSB();
__ISB();
}
/* Yield */
void port_yield(void) {
SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk;
}
/* Yield from ISR */
void port_yield_from_isr(void) {
SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk;
}
/* Enter Critical Section */
void port_disable_interrupts(void) {
__disable_irq();
}
/* Exit Critical Section */
void port_enable_interrupts(void) {
__enable_irq();
}
/* Get Current Exception Number */
uint32_t port_get_current_exception(void) {
return (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) >> SCB_ICSR_VECTACTIVE_Pos;
}
/* Initialize Task Stack */
uint32_t* port_initialize_task_stack(TaskFunction_t task_function,
void* parameters,
uint32_t* stack_top) {
uint32_t* stack_ptr = stack_top;
/* 8-byte alignment */
stack_ptr = (uint32_t*)((uint32_t)stack_ptr & ~0x7);
/* Exception frame */
*(--stack_ptr) = 0x01000000; /* xPSR */
*(--stack_ptr) = (uint32_t)task_function; /* PC */
*(--stack_ptr) = 0xFFFFFFFD; /* LR */
*(--stack_ptr) = 0x00000000; /* R12 */
*(--stack_ptr) = 0x00000003; /* R3 */
*(--stack_ptr) = 0x00000002; /* R2 */
*(--stack_ptr) = 0x00000001; /* R1 */
*(--stack_ptr) = (uint32_t)parameters; /* R0 */
/* Additional context */
*(--stack_ptr) = 0x0000000B; /* R11 */
*(--stack_ptr) = 0x0000000A; /* R10 */
*(--stack_ptr) = 0x00000009; /* R9 */
*(--stack_ptr) = 0x00000008; /* R8 */
*(--stack_ptr) = 0x00000007; /* R7 */
*(--stack_ptr) = 0x00000006; /* R6 */
*(--stack_ptr) = 0x00000005; /* R5 */
*(--stack_ptr) = 0x00000004; /* R4 */
return stack_ptr;
}
/* SysTick Handler */
void SysTick_Handler(void) {
extern void kernel_tick_handler(void);
kernel_tick_handler();
}
/* PendSV Handler */
__attribute__((naked)) void PendSV_Handler(void) {
__asm volatile (
"MRS R0, PSP\n"
"STMDB R0!, {R4-R11}\n"
"LDR R1, =current_task_sp\n"
"STR R0, [R1]\n"
"LDR R0, =next_task_sp\n"
"LDR R1, [R0]\n"
"LDMIA R1!, {R4-R11}\n"
"MSR PSP, R1\n"
"BX LR\n"
);
}
/* SVC Handler */
__attribute__((naked)) void SVC_Handler(void) {
__asm volatile (
"TST LR, #4\n"
"ITE EQ\n"
"MRSEQ R0, MSP\n"
"MRSNE R0, PSP\n"
"LDR R0, [R0, #24]\n"
"LDRB R0, [R0, #-2]\n"
"PUSH {LR}\n"
"BL svc_handler\n"
"POP {LR}\n"
"BX LR\n"
);
}
/* Memory Management Fault Handler */
void MemManage_Handler(void) {
uint32_t fault_address;
uint32_t fault_status;
fault_address = SCB->MMFAR;
fault_status = SCB->CFSR;
extern void fault_handler_process(uint32_t type, uint32_t address, uint32_t status);
fault_handler_process(2, fault_address, fault_status);
while(1);
}
/* Bus Fault Handler */
void BusFault_Handler(void) {
uint32_t fault_address;
uint32_t fault_status;
fault_address = SCB->BFAR;
fault_status = SCB->CFSR;
extern void fault_handler_process(uint32_t type, uint32_t address, uint32_t status);
fault_handler_process(3, fault_address, fault_status);
while(1);
}
/* Usage Fault Handler */
void UsageFault_Handler(void) {
uint32_t fault_status = SCB->CFSR;
extern void fault_handler_process(uint32_t type, uint32_t address, uint32_t status);
fault_handler_process(4, 0, fault_status);
while(1);
}
/* Hard Fault Handler */
void HardFault_Handler(void) {
uint32_t fault_address = 0;
uint32_t fault_status = SCB->HFSR;
extern void fault_handler_process(uint32_t type, uint32_t address, uint32_t status);
fault_handler_process(1, fault_address, fault_status);
while(1);
}
+162
View File
@@ -0,0 +1,162 @@
/**
* @file port_asm.s
* @brief ARM Cortex-M3 assembly routines
*/
.syntax unified
.thumb
.arch armv7-m
.section .text
/* Global symbols */
.global current_task_sp
.global next_task_sp
.global port_context_switch
.global port_start_first_task
.global port_initialize_task_stack
.global port_disable_interrupts
.global port_enable_interrupts
/* Variables */
.section .bss
.align 2
current_task_sp: .word 0
next_task_sp: .word 0
.section .text
.thumb_func
/* Start First Task */
port_start_first_task:
/* Load task stack pointer */
ldr r0, =next_task_sp
ldr r1, [r0]
/* Set PSP */
msr PSP, r1
/* Switch to PSP */
mov r0, #2
msr CONTROL, r0
isb
/* Restore context */
ldmia r1!, {r4-r11}
msr PSP, r1
mov lr, #0xFFFFFFFD
bx lr
/* PendSV Handler */
PendSV_Handler:
/* Save context */
mrs r0, PSP
stmdb r0!, {r4-r11}
ldr r1, =current_task_sp
str r0, [r1]
/* Load next context */
ldr r0, =next_task_sp
ldr r1, [r0]
ldmia r1!, {r4-r11}
msr PSP, r1
bx lr
/* SVC Handler */
SVC_Handler:
tst lr, #4
ite eq
mrseq r0, MSP
mrsne r0, PSP
ldr r0, [r0, #24]
ldrb r0, [r0, #-2]
push {lr}
bl svc_handler
pop {lr}
bx lr
/* Disable Interrupts */
port_disable_interrupts:
cpsid i
bx lr
/* Enable Interrupts */
port_enable_interrupts:
cpsie i
bx lr
/* Memory Management Fault */
MemManage_Handler:
/* Save context */
mrs r0, PSP
stmdb r0!, {r4-r11}
/* Get fault information */
ldr r1, =0xE000ED34 /* MMFAR */
ldr r1, [r1]
ldr r2, =0xE000ED28 /* CFSR */
ldr r2, [r2]
/* Call fault handler */
movs r0, #2
bl fault_handler_process
/* Infinite loop */
b .
/* Bus Fault Handler */
BusFault_Handler:
/* Save context */
mrs r0, PSP
stmdb r0!, {r4-r11}
/* Get fault information */
ldr r1, =0xE000ED38 /* BFAR */
ldr r1, [r1]
ldr r2, =0xE000ED28 /* CFSR */
ldr r2, [r2]
/* Call fault handler */
movs r0, #3
bl fault_handler_process
/* Infinite loop */
b .
/* Usage Fault Handler */
UsageFault_Handler:
/* Save context */
mrs r0, PSP
stmdb r0!, {r4-r11}
/* Get fault status */
ldr r2, =0xE000ED28 /* CFSR */
ldr r2, [r2]
/* Call fault handler */
movs r0, #4
movs r1, #0
bl fault_handler_process
/* Infinite loop */
b .
/* Hard Fault Handler */
HardFault_Handler:
/* Save context */
mrs r0, PSP
stmdb r0!, {r4-r11}
/* Get fault status */
ldr r2, =0xE000ED2C /* HFSR */
ldr r2, [r2]
/* Call fault handler */
movs r0, #1
movs r1, #0
bl fault_handler_process
/* Infinite loop */
b .
.end
+43
View File
@@ -0,0 +1,43 @@
/**
* @file portmacro.h
* @brief ARM Cortex-M3 specific macros
*/
#ifndef PORTMACRO_H
#define PORTMACRO_H
#include <stdint.h>
/* Data Types */
typedef uint32_t port_stack_type_t;
typedef uint32_t port_base_type_t;
/* Architecture Constants */
#define PORT_STACK_GROWTH_DIRECTION (-1)
#define PORT_BYTE_ALIGNMENT 8
#define PORT_MAX_SYSCALL_INTERRUPT_PRIORITY 0x50
/* Critical Section Macros */
#define portENTER_CRITICAL() __asm volatile("CPSID I" ::: "memory")
#define portEXIT_CRITICAL() __asm volatile("CPSIE I" ::: "memory")
/* Interrupt Control */
#define portENABLE_INTERRUPTS() __asm volatile("CPSIE I" ::: "memory")
#define portDISABLE_INTERRUPTS() __asm volatile("CPSID I" ::: "memory")
/* Context Switch */
#define portYIELD() SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk
#define portYIELD_FROM_ISR() SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk
/* Memory Barriers */
#define portMEMORY_BARRIER() __asm volatile("DMB" ::: "memory")
#define portSYNC_BARRIER() __asm volatile("DSB" ::: "memory")
#define portINSTRUCTION_BARRIER() __asm volatile("ISB" ::: "memory")
/* NOP */
#define portNOP() __asm volatile("NOP")
/* Endian Definition */
#define portBYTE_ORDER LITTLE_ENDIAN
#endif /* PORTMACRO_H */
+251
View File
@@ -0,0 +1,251 @@
/**
* @file port.c
* @brief ARM Cortex-M4 architecture specific port with FPU support
* @note Cortex-M4 with FPU is common in modern automotive MCUs
*/
#include "kernel.h"
#include "task.h"
#include "scheduler.h"
#include "portmacro.h"
/* Context storage */
uint32_t* current_task_sp = NULL;
uint32_t* next_task_sp = NULL;
/* FPU context storage */
uint32_t current_fpu_context[32];
uint32_t next_fpu_context[32];
/* Exception priorities */
#define SYSTICK_PRIORITY 0xFF
#define PENDSV_PRIORITY 0xFF
#define SVC_PRIORITY 0x00
/* Initialize Architecture Port */
void port_init(void) {
/* Set priority grouping - 4 bits preemption, 0 bits sub-priority */
NVIC_SetPriorityGrouping(4);
/* Enable FPU */
SCB->CPACR |= ((3UL << 10*2) | (3UL << 11*2));
/* Configure SysTick */
SysTick->LOAD = (SystemCoreClock / 1000) - 1;
SysTick->VAL = 0;
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
SysTick_CTRL_TICKINT_Msk |
SysTick_CTRL_ENABLE_Msk;
/* Set exception priorities */
NVIC_SetPriority(SysTick_IRQn, SYSTICK_PRIORITY);
NVIC_SetPriority(PendSV_IRQn, PENDSV_PRIORITY);
NVIC_SetPriority(SVCall_IRQn, SVC_PRIORITY);
/* Enable faults */
SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk |
SCB_SHCSR_BUSFAULTENA_Msk |
SCB_SHCSR_USGFAULTENA_Msk;
/* Enable divide by zero trap */
SCB->CCR |= SCB_CCR_DIV_0_TRP_Msk;
/* Enable unaligned access trap */
SCB->CCR |= SCB_CCR_UNALIGN_TRP_Msk;
}
/* Start First Task */
void port_start_first_task(void) {
TaskHandle_t first_task = scheduler_get_current_task();
if (first_task == NULL) {
return;
}
/* Restore FPU context if task uses FPU */
if (first_task->context[31] & 0x10) {
/* FPU was used - restore FPU registers */
__asm volatile (
"VLDM R0!, {S16-S31}\n"
"VLDM R0!, {S0-S15}\n"
:
: "r" (first_task->context)
);
}
/* Set PSP */
__set_PSP((uint32_t)first_task->stack_pointer);
/* Switch to PSP */
__set_CONTROL(0x02);
__ISB();
/* Restore context */
__asm volatile (
"LDMIA R0!, {R4-R11}\n"
"MSR PSP, R0\n"
"MOV LR, #0xFFFFFFFD\n"
"BX LR\n"
:
: "r" (first_task->stack_pointer)
);
}
/* Context Switch */
void port_context_switch(uint32_t* current_context, uint32_t* next_context) {
current_task_sp = current_context;
next_task_sp = next_context;
/* Trigger PendSV */
SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk;
/* Data synchronization barrier */
__DSB();
__ISB();
}
/* Initialize Task Stack with FPU support */
uint32_t* port_initialize_task_stack(TaskFunction_t task_function,
void* parameters,
uint32_t* stack_top) {
uint32_t* stack_ptr = stack_top;
/* 8-byte alignment */
stack_ptr = (uint32_t*)((uint32_t)stack_ptr & ~0x7);
/* Exception frame with FPU */
*(--stack_ptr) = 0x01000000; /* xPSR */
*(--stack_ptr) = (uint32_t)task_function; /* PC */
*(--stack_ptr) = 0xFFFFFFFD; /* LR */
*(--stack_ptr) = 0x00000000; /* R12 */
*(--stack_ptr) = 0x00000003; /* R3 */
*(--stack_ptr) = 0x00000002; /* R2 */
*(--stack_ptr) = 0x00000001; /* R1 */
*(--stack_ptr) = (uint32_t)parameters; /* R0 */
/* Additional context */
*(--stack_ptr) = 0x0000000B; /* R11 */
*(--stack_ptr) = 0x0000000A; /* R10 */
*(--stack_ptr) = 0x00000009; /* R9 */
*(--stack_ptr) = 0x00000008; /* R8 */
*(--stack_ptr) = 0x00000007; /* R7 */
*(--stack_ptr) = 0x00000006; /* R6 */
*(--stack_ptr) = 0x00000005; /* R5 */
*(--stack_ptr) = 0x00000004; /* R4 */
/* FPU context (S0-S31) */
for (int i = 0; i < 32; i++) {
*(--stack_ptr) = 0;
}
/* FPSCR */
*(--stack_ptr) = 0;
return stack_ptr;
}
/* SysTick Handler */
void SysTick_Handler(void) {
extern void kernel_tick_handler(void);
kernel_tick_handler();
}
/* PendSV Handler with FPU context saving */
__attribute__((naked)) void PendSV_Handler(void) {
__asm volatile (
/* Check if FPU was used */
"TST LR, #0x10\n"
"IT EQ\n"
"BEQ 1f\n"
/* Save FPU context */
"MRS R0, CONTROL\n"
"TST R0, #0x04\n"
"IT EQ\n"
"BEQ 1f\n"
/* Save FPU registers */
"VSTMDB R0!, {S16-S31}\n"
"VSTMDB R0!, {S0-S15}\n"
"1:\n"
/* Save core context */
"MRS R0, PSP\n"
"STMDB R0!, {R4-R11}\n"
"LDR R1, =current_task_sp\n"
"STR R0, [R1]\n"
/* Load next context */
"LDR R0, =next_task_sp\n"
"LDR R1, [R0]\n"
"LDMIA R1!, {R4-R11}\n"
"MSR PSP, R1\n"
/* Restore FPU context if needed */
"TST LR, #0x10\n"
"IT EQ\n"
"BEQ 2f\n"
/* Restore FPU registers */
"VLDMIA R0!, {S0-S15}\n"
"VLDMIA R0!, {S16-S31}\n"
"2:\n"
"BX LR\n"
);
}
/* SVC Handler */
__attribute__((naked)) void SVC_Handler(void) {
__asm volatile (
"TST LR, #4\n"
"ITE EQ\n"
"MRSEQ R0, MSP\n"
"MRSNE R0, PSP\n"
"LDR R0, [R0, #24]\n"
"LDRB R0, [R0, #-2]\n"
"PUSH {LR}\n"
"BL svc_handler\n"
"POP {LR}\n"
"BX LR\n"
);
}
/* Fault Handlers */
void MemManage_Handler(void) {
uint32_t fault_address = SCB->MMFAR;
uint32_t fault_status = SCB->CFSR;
extern void fault_handler_process(uint32_t type, uint32_t address, uint32_t status);
fault_handler_process(2, fault_address, fault_status);
while(1);
}
void BusFault_Handler(void) {
uint32_t fault_address = SCB->BFAR;
uint32_t fault_status = SCB->CFSR;
extern void fault_handler_process(uint32_t type, uint32_t address, uint32_t status);
fault_handler_process(3, fault_address, fault_status);
while(1);
}
void UsageFault_Handler(void) {
uint32_t fault_status = SCB->CFSR;
extern void fault_handler_process(uint32_t type, uint32_t address, uint32_t status);
fault_handler_process(4, 0, fault_status);
while(1);
}
void HardFault_Handler(void) {
uint32_t fault_status = SCB->HFSR;
extern void fault_handler_process(uint32_t type, uint32_t address, uint32_t status);
fault_handler_process(1, 0, fault_status);
while(1);
}
+226
View File
@@ -0,0 +1,226 @@
/**
* @file port_asm.s
* @brief ARM Cortex-M4 assembly routines with FPU support
*/
.syntax unified
.thumb
.arch armv7e-m
.fpu fpv4-sp-d16
.section .text
/* Global symbols */
.global current_task_sp
.global next_task_sp
.global port_context_switch
.global port_start_first_task
.global port_initialize_task_stack
.global port_disable_interrupts
.global port_enable_interrupts
.global port_enable_fpu
.global port_disable_fpu
/* Variables */
.section .bss
.align 3
current_task_sp: .word 0
next_task_sp: .word 0
.section .text
.thumb_func
/* Start First Task */
port_start_first_task:
/* Load task stack pointer */
ldr r0, =next_task_sp
ldr r1, [r0]
/* Check if FPU context needs restoring */
tst lr, #0x10
beq 1f
/* Restore FPU registers */
add r1, r1, #64
vldmia r1!, {s16-s31}
vldmia r1!, {s0-s15}
sub r1, r1, #128
1:
/* Set PSP */
msr PSP, r1
/* Switch to PSP */
mov r0, #2
msr CONTROL, r0
isb
/* Restore core context */
ldmia r1!, {r4-r11}
msr PSP, r1
mov lr, #0xFFFFFFFD
bx lr
/* PendSV Handler */
PendSV_Handler:
/* Check if using PSP */
mrs r0, CONTROL
tst r0, #2
beq 1f
/* Check if FPU was used */
tst lr, #0x10
beq 1f
/* Save FPU context */
mrs r0, PSP
add r0, r0, #64
vstmdb r0!, {s16-s31}
vstmdb r0!, {s0-s15}
1:
/* Save core context */
mrs r0, PSP
stmdb r0!, {r4-r11}
ldr r1, =current_task_sp
str r0, [r1]
/* Load next context */
ldr r0, =next_task_sp
ldr r1, [r0]
ldmia r1!, {r4-r11}
msr PSP, r1
/* Restore FPU context if needed */
tst lr, #0x10
beq 2f
/* Restore FPU registers */
add r1, r1, #64
vldmia r1!, {s0-s15}
vldmia r1!, {s16-s31}
2:
/* Return from exception */
bx lr
/* SVC Handler */
SVC_Handler:
tst lr, #4
ite eq
mrseq r0, MSP
mrsne r0, PSP
ldr r0, [r0, #24]
ldrb r0, [r0, #-2]
push {lr}
bl svc_handler
pop {lr}
bx lr
/* Enable FPU */
port_enable_fpu:
/* Enable CP10 and CP11 */
ldr r0, =0xE000ED88 /* CPACR */
ldr r1, [r0]
orr r1, r1, #(0xF << 20)
str r1, [r0]
dsb
isb
bx lr
/* Disable FPU */
port_disable_fpu:
/* Disable CP10 and CP11 */
ldr r0, =0xE000ED88 /* CPACR */
ldr r1, [r0]
bic r1, r1, #(0xF << 20)
str r1, [r0]
dsb
isb
bx lr
/* Disable Interrupts */
port_disable_interrupts:
cpsid i
bx lr
/* Enable Interrupts */
port_enable_interrupts:
cpsie i
bx lr
/* Memory Management Fault */
MemManage_Handler:
/* Save context */
mrs r0, PSP
stmdb r0!, {r4-r11}
/* Get fault information */
ldr r1, =0xE000ED34 /* MMFAR */
ldr r1, [r1]
ldr r2, =0xE000ED28 /* CFSR */
ldr r2, [r2]
/* Call fault handler */
movs r0, #2
bl fault_handler_process
/* Infinite loop */
b .
/* Bus Fault Handler */
BusFault_Handler:
/* Save context */
mrs r0, PSP
stmdb r0!, {r4-r11}
/* Get fault information */
ldr r1, =0xE000ED38 /* BFAR */
ldr r1, [r1]
ldr r2, =0xE000ED28 /* CFSR */
ldr r2, [r2]
/* Call fault handler */
movs r0, #3
bl fault_handler_process
/* Infinite loop */
b .
/* Usage Fault Handler */
UsageFault_Handler:
/* Save context */
mrs r0, PSP
stmdb r0!, {r4-r11}
/* Get fault status */
ldr r2, =0xE000ED28 /* CFSR */
ldr r2, [r2]
/* Call fault handler */
movs r0, #4
movs r1, #0
bl fault_handler_process
/* Infinite loop */
b .
/* Hard Fault Handler */
HardFault_Handler:
/* Save context */
mrs r0, PSP
stmdb r0!, {r4-r11}
/* Get fault status */
ldr r2, =0xE000ED2C /* HFSR */
ldr r2, [r2]
/* Call fault handler */
movs r0, #1
movs r1, #0
bl fault_handler_process
/* Infinite loop */
b .
.end
+65
View File
@@ -0,0 +1,65 @@
/**
* @file portmacro.h
* @brief ARM Cortex-M4 specific macros with FPU support
*/
#ifndef PORTMACRO_H
#define PORTMACRO_H
#include <stdint.h>
#include "stm32f4xx.h" /* Adjust for specific MCU */
/* Data Types */
typedef uint32_t port_stack_type_t;
typedef uint32_t port_base_type_t;
/* Architecture Constants */
#define PORT_STACK_GROWTH_DIRECTION (-1)
#define PORT_BYTE_ALIGNMENT 8
#define PORT_MAX_SYSCALL_INTERRUPT_PRIORITY 0x50
/* Critical Section Macros */
#define portENTER_CRITICAL() __asm volatile("CPSID I" ::: "memory")
#define portEXIT_CRITICAL() __asm volatile("CPSIE I" ::: "memory")
/* Interrupt Control */
#define portENABLE_INTERRUPTS() __asm volatile("CPSIE I" ::: "memory")
#define portDISABLE_INTERRUPTS() __asm volatile("CPSID I" ::: "memory")
/* Context Switch */
#define portYIELD() SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk
#define portYIELD_FROM_ISR() SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk
/* Memory Barriers */
#define portMEMORY_BARRIER() __asm volatile("DMB" ::: "memory")
#define portSYNC_BARRIER() __asm volatile("DSB" ::: "memory")
#define portINSTRUCTION_BARRIER() __asm volatile("ISB" ::: "memory")
/* NOP */
#define portNOP() __asm volatile("NOP")
/* FPU Control */
#define portENABLE_FPU() \
do { \
SCB->CPACR |= ((3UL << 10*2) | (3UL << 11*2)); \
__DSB(); \
__ISB(); \
} while(0)
#define portDISABLE_FPU() \
do { \
SCB->CPACR &= ~((3UL << 10*2) | (3UL << 11*2)); \
__DSB(); \
__ISB(); \
} while(0)
/* Endian Definition */
#define portBYTE_ORDER LITTLE_ENDIAN
/* Optimization */
#define portFORCE_INLINE __attribute__((always_inline)) inline
/* Task Utilities */
#define portTASK_RETURN_ADDRESS (0xFFFFFFFD)
#endif /* PORTMACRO_H */
+40
View File
@@ -0,0 +1,40 @@
/**
* @file port_common.h
* @brief Common port interface definitions
*/
#ifndef PORT_COMMON_H
#define PORT_COMMON_H
#include "kernel.h"
/* Common port function declarations */
void port_common_init(void);
void port_common_context_switch(TaskHandle_t current, TaskHandle_t next);
uint32_t* port_common_init_stack(TaskFunction_t function,
void* parameters,
uint32_t* stack_top,
uint32_t stack_size);
void port_common_fault_handler(uint32_t fault_type, uint32_t fault_address,
uint32_t fault_status);
void port_enter_safe_state(void);
void port_set_safe_outputs(void);
void port_log_fault(void* fault_info);
/* Architecture-specific functions that must be implemented */
void port_init(void);
void port_start_first_task(void);
void port_context_switch(uint32_t* current_context, uint32_t* next_context);
uint32_t* port_initialize_task_stack(TaskFunction_t function,
void* parameters,
uint32_t* stack_top);
void port_save_context(uint32_t* context);
void port_restore_context(uint32_t* context);
void port_disable_interrupts(void);
void port_enable_interrupts(void);
uint32_t port_get_current_exception(void);
void port_service_watchdog(void);
void port_yield(void);
void port_yield_from_isr(void);
#endif /* PORT_COMMON_H */
+262
View File
@@ -0,0 +1,262 @@
/**
* @file port.c
* @brief Infineon TriCore TC3xx architecture specific port
* @note TriCore is widely used in automotive powertrain and safety applications
*/
#include "kernel.h"
#include "task.h"
#include "scheduler.h"
#include "portmacro.h"
#include "Ifx_Types.h"
#include "IfxCpu.h"
#include "IfxStm.h"
#include "IfxScuWdt.h"
/* Context storage */
uint32_t* current_task_sp = NULL;
uint32_t* next_task_sp = NULL;
/* STM configuration for system tick */
static IfxStm_CompareConfig stmCompareConfig;
static volatile uint32_t stmTickCount = 0;
/* CSA (Context Save Area) management */
#define MAX_CSA_AREAS 64
static uint32_t csa_areas[MAX_CSA_AREAS][16] __attribute__((aligned(64)));
static uint32_t csa_index = 0;
/* Interrupt priorities */
#define SYSTICK_PRIORITY 255
#define PENDSV_PRIORITY 255
#define SVC_PRIORITY 0
/* Initialize Architecture Port */
void port_init(void) {
/* Initialize CPU configuration */
IfxCpu_init();
/* Disable global interrupts during initialization */
IfxCpu_disableInterrupts();
/* Initialize CSA areas */
for (uint32_t i = 0; i < MAX_CSA_AREAS; i++) {
/* Initialize PCXI register for each CSA */
uint32_t pcxi_value = ((uint32_t)&csa_areas[i][0]) & 0xFFFFF000;
pcxi_value |= (i << 16); /* Set previous context pointer */
csa_areas[i][0] = pcxi_value;
}
/* Configure STM for 1ms tick */
IfxStm_initCompareConfig(&stmCompareConfig);
stmCompareConfig.triggerPriority = SYSTICK_PRIORITY;
stmCompareConfig.typeOfService = IfxSrc_Tos_cpu0;
stmCompareConfig.ticks = IfxStm_getFrequency(&MODULE_STM0) / 1000;
/* Initialize STM compare */
IfxStm_initCompare(&MODULE_STM0, &stmCompareConfig);
/* Enable safety watchdog */
IfxScuWdt_disableCpuWatchdog(IfxScuWdt_getCpuWatchdogPassword());
IfxScuWdt_clearCpuEndinit(IfxScuWdt_getCpuWatchdogPassword());
IfxScuWdt_enableSafetyWatchdog(IfxScuWdt_getSafetyWatchdogPassword(),
100, 200);
IfxScuWdt_setCpuEndinit(IfxScuWdt_getCpuWatchdogPassword());
/* Enable global interrupts */
IfxCpu_enableInterrupts();
}
/* Start First Task */
void port_start_first_task(void) {
TaskHandle_t first_task = scheduler_get_current_task();
if (first_task == NULL) {
return;
}
/* Get task context from CSA */
uint32_t* context = (uint32_t*)first_task->context;
uint32_t pcxi = context[0];
uint32_t pc = context[1];
uint32_t sp = context[2];
/* Set up context for first task execution */
__asm volatile (
"mov.a %%sp, %0\n" /* Set stack pointer */
"mov %%a11, %1\n" /* Set return address */
"mtsv %%pcxi, %2\n" /* Set context */
"rslcx\n" /* Restore lower context */
"rfe\n" /* Return from exception */
:
: "r" (sp), "r" (pc), "r" (pcxi)
: "a11", "memory"
);
}
/* Context Switch */
void port_context_switch(uint32_t* current_context, uint32_t* next_context) {
current_task_sp = current_context;
next_task_sp = next_context;
/* Trigger software interrupt for context switch */
__asm volatile (
"syscall 0\n" /* System call for context switch */
);
}
/* Initialize Task Stack */
uint32_t* port_initialize_task_stack(TaskFunction_t task_function,
void* parameters,
uint32_t* stack_top) {
uint32_t* stack_ptr = stack_top;
/* Align to 64 bytes */
stack_ptr = (uint32_t*)((uint32_t)stack_ptr & ~0x3F);
/* Allocate CSA for task */
if (csa_index >= MAX_CSA_AREAS) {
return NULL; /* Out of CSA areas */
}
uint32_t* csa = csa_areas[csa_index];
csa_index++;
/* Initialize CSA */
csa[0] = 0; /* PCXI will be set during first context switch */
csa[1] = (uint32_t)task_function; /* PC */
csa[2] = (uint32_t)stack_ptr; /* SP */
csa[3] = (uint32_t)parameters; /* A4 (first argument) */
/* Initialize upper context registers */
csa[4] = 0; /* A5 */
csa[5] = 0; /* A6 */
csa[6] = 0; /* A7 */
csa[7] = 0; /* A8 */
csa[8] = 0; /* A9 */
csa[9] = 0; /* A10 */
csa[10] = 0; /* A11 */
csa[11] = 0; /* A12 */
csa[12] = 0; /* A13 */
csa[13] = 0; /* A14 */
csa[14] = 0; /* A15 */
csa[15] = 0; /* D8 */
/* Store CSA pointer in task context */
TaskHandle_t task = scheduler_get_current_task();
if (task != NULL) {
task->context[0] = (uint32_t)csa;
}
return stack_ptr;
}
/* System Timer Interrupt Handler */
IFX_INTERRUPT(stm_compare_match_isr, 0, SYSTICK_PRIORITY) {
/* Clear interrupt flag */
IfxStm_clearCompareFlag(&MODULE_STM0, stmCompareConfig.comparator);
/* Update compare value for next interrupt */
IfxStm_increaseCompare(&MODULE_STM0, stmCompareConfig.comparator,
IfxStm_getFrequency(&MODULE_STM0) / 1000);
/* Call kernel tick handler */
extern void kernel_tick_handler(void);
kernel_tick_handler();
/* Refresh watchdog */
IfxScuWdt_clearSafetyWatchdog(IfxScuWdt_getSafetyWatchdogPassword());
}
/* Software Interrupt Handler for Context Switch */
IFX_INTERRUPT(software_context_switch_isr, 0, PENDSV_PRIORITY) {
__asm volatile (
/* Save current context */
"svlcx\n" /* Save lower context */
"mov %%d15, %%a11\n" /* Save return address */
/* Store current stack pointer */
"mov.a %%a15, %%sp\n"
"mov.aa %0, %%a15\n"
/* Load next stack pointer */
"mov.aa %%a15, %1\n"
"mov.a %%sp, %%a15\n"
/* Restore lower context */
"rslcx\n"
"mov %%a11, %%d15\n" /* Restore return address */
"rfe\n" /* Return from exception */
:
: "m" (current_task_sp), "m" (next_task_sp)
: "a15", "d15", "memory"
);
}
/* System Call Handler */
IFX_INTERRUPT(syscall_handler, 0, SVC_PRIORITY) {
/* Get system call number */
uint32_t syscall_number;
__asm volatile (
"mov %0, %%d15\n" /* Get syscall number from D15 */
: "=r" (syscall_number)
);
/* Handle system calls */
switch (syscall_number) {
case 0: /* Context switch */
software_context_switch_isr();
break;
case 1: /* Yield */
scheduler_yield();
break;
case 2: /* Task exit */
task_delete(scheduler_get_current_task());
break;
default:
break;
}
}
/* Trap Handlers */
IFX_INTERRUPT(trap_handler, 0, 0) {
/* Get trap information */
uint32_t trap_class;
uint32_t trap_id;
__asm volatile (
"mov %0, %%d15\n" /* Trap class */
"mov %1, %%d14\n" /* Trap ID */
: "=r" (trap_class), "=r" (trap_id)
);
/* Call fault handler */
extern void fault_handler_process(uint32_t type, uint32_t address, uint32_t status);
fault_handler_process(trap_class, trap_id, 0);
/* Enter safe state */
while(1) {
/* Safe state - wait for watchdog */
IfxScuWdt_clearSafetyWatchdog(IfxScuWdt_getSafetyWatchdogPassword());
}
}
/* Enter Critical Section */
void port_disable_interrupts(void) {
IfxCpu_disableInterrupts();
}
/* Exit Critical Section */
void port_enable_interrupts(void) {
IfxCpu_enableInterrupts();
}
/* Get Current Exception Number */
uint32_t port_get_current_exception(void) {
uint32_t icr;
__asm volatile (
"mfcr %0, $ICR\n" /* Get Interrupt Control Register */
: "=r" (icr)
);
return (icr >> 16) & 0xFF; /* Extract current CPU priority */
}
@@ -0,0 +1,105 @@
/**
* @file port_asm.s
* @brief Infineon TriCore TC3xx assembly routines
*/
.section .text
.align 2
/* Global symbols */
.global current_task_sp
.global next_task_sp
.global port_context_switch
.global port_start_first_task
.global port_disable_interrupts
.global port_enable_interrupts
/* Variables */
.section .bss
.align 2
current_task_sp: .word 0
next_task_sp: .word 0
.section .text
/* Start First Task */
port_start_first_task:
/* Load task context */
mov.a a15, [next_task_sp]
ld.a a14, [a15] /* Load CSA pointer */
/* Set up context */
mtsv pcxi, a14 /* Set previous context */
ld.a sp, [a14+8] /* Load stack pointer */
ld.a a11, [a14+4] /* Load return address */
/* Restore context and start */
rslcx /* Restore lower context */
rfe /* Return from exception */
/* Context Switch */
port_context_switch:
/* Save current context */
svlcx /* Save lower context */
/* Store current stack pointer */
mov.a a15, sp
mov.aa [current_task_sp], a15
/* Load next stack pointer */
mov.aa a15, [next_task_sp]
mov.a sp, a15
/* Restore next context */
rslcx /* Restore lower context */
rfe /* Return from exception */
/* Disable Interrupts */
port_disable_interrupts:
disable /* Disable interrupts */
ret
/* Enable Interrupts */
port_enable_interrupts:
enable /* Enable interrupts */
ret
/* System Timer Interrupt */
stm_compare_match_isr:
/* Save context */
svlcx
/* Clear interrupt */
movh.a a15, 0xF000 /* STM base address */
lea a15, [a15]0x0010 /* STM interrupt clear register */
st.w [a15], 0x1 /* Clear compare match flag */
/* Update compare value */
movh.a a15, 0xF000
lea a15, [a15]0x0020 /* STM compare register */
ld.w d15, [a15]
movh.a a14, 0xF000
lea a14, [a14]0x0024 /* STM compare update register */
add d15, d15, 1000 /* Add 1ms */
st.w [a14], d15
/* Call kernel tick handler */
call kernel_tick_handler
/* Restore context */
rslcx
rfe
/* Trap Handler */
trap_handler:
/* Save trap information */
mov d15, d15 /* Trap class */
mov d14, d14 /* Trap ID */
/* Call fault handler */
call fault_handler_process
/* Enter safe state */
j .
.end
@@ -0,0 +1,52 @@
/**
* @file portmacro.h
* @brief Infineon TriCore TC3xx specific macros
*/
#ifndef PORTMACRO_H
#define PORTMACRO_H
#include <stdint.h>
#include "Ifx_Types.h"
#include "IfxCpu.h"
/* Data Types */
typedef uint32_t port_stack_type_t;
typedef uint32_t port_base_type_t;
/* Architecture Constants */
#define PORT_STACK_GROWTH_DIRECTION (-1)
#define PORT_BYTE_ALIGNMENT 64
/* Critical Section Macros */
#define portENTER_CRITICAL() IfxCpu_disableInterrupts()
#define portEXIT_CRITICAL() IfxCpu_enableInterrupts()
/* Interrupt Control */
#define portENABLE_INTERRUPTS() IfxCpu_enableInterrupts()
#define portDISABLE_INTERRUPTS() IfxCpu_disableInterrupts()
/* Context Switch */
#define portYIELD() __asm volatile("syscall 0")
#define portYIELD_FROM_ISR() __asm volatile("syscall 0")
/* Memory Barriers */
#define portMEMORY_BARRIER() __asm volatile("dsync")
#define portSYNC_BARRIER() __asm volatile("dsync")
#define portINSTRUCTION_BARRIER() __asm volatile("isync")
/* NOP */
#define portNOP() __asm volatile("nop")
/* CSA Management */
#define portALLOCATE_CSA() __port_allocate_csa()
#define portFREE_CSA(csa) __port_free_csa(csa)
/* Safety Features */
#define portENABLE_SAFETY_WATCHDOG(timeout) \
IfxScuWdt_enableSafetyWatchdog(IfxScuWdt_getSafetyWatchdogPassword(), timeout, timeout*2)
#define portSERVICE_WATCHDOG() \
IfxScuWdt_clearSafetyWatchdog(IfxScuWdt_getSafetyWatchdogPassword())
#endif /* PORTMACRO_H */
+260
View File
@@ -0,0 +1,260 @@
/**
* @file port.c
* @brief NXP S32K architecture specific port
* @note S32K is designed for automotive body and safety applications
*/
#include "kernel.h"
#include "task.h"
#include "scheduler.h"
#include "portmacro.h"
#include "S32K144.h"
#include "interrupt_manager.h"
/* Context storage */
uint32_t* current_task_sp = NULL;
uint32_t* next_task_sp = NULL;
/* LPIT configuration */
#define LPIT_CHANNEL 0
#define LPIT_TICK_PERIOD 1000 /* 1ms at 1MHz */
/* Interrupt priorities */
#define SYSTICK_PRIORITY 15
#define PENDSV_PRIORITY 15
#define SVC_PRIORITY 0
/* Initialize Architecture Port */
void port_init(void) {
/* Disable global interrupts */
__disable_irq();
/* Configure system clock */
/* Assuming 8MHz external crystal, PLL to 160MHz */
SCG->SPLLCSR = SCG_SPLLCSR_SPLLEN_MASK;
SCG->SPLLDIV = SCG_SPLLDIV_SPLLDIV1(1) | SCG_SPLLDIV_SPLLDIV2(1);
SCG->SPLLCFG = SCG_SPLLCFG_MULT(20); /* 8MHz * 20 = 160MHz */
/* Wait for PLL lock */
while(!(SCG->SPLLCSR & SCG_SPLLCSR_SPLLVLD_MASK));
/* Switch to PLL */
SCG->RCCR = SCG_RCCR_DIVCORE(1) | SCG_RCCR_DIVBUS(2) |
SCG_RCCR_DIVSLOW(4) | SCG_RCCR_SCS(6);
/* Enable clock to LPIT */
PCC->PCCn[PCC_LPIT0_INDEX] = PCC_PCCn_PCS(6) | PCC_PCCn_CGC_MASK;
/* Configure LPIT for system tick */
LPIT0->MCR = LPIT_MCR_M_CEN_MASK; /* Enable module */
/* Configure channel 0 */
LPIT0->TMR[LPIT_CHANNEL].TVAL = LPIT_TICK_PERIOD;
LPIT0->TMR[LPIT_CHANNEL].TCTRL =
LPIT_TMR_TCTRL_T_EN_MASK | /* Enable timer */
LPIT_TMR_TCTRL_MODE_MASK; /* 32-bit counter mode */
/* Enable LPIT interrupt */
LPIT0->MIER |= (1 << LPIT_CHANNEL);
/* Set interrupt priority */
NVIC_SetPriority(LPIT0_IRQn, SYSTICK_PRIORITY);
NVIC_EnableIRQ(LPIT0_IRQn);
/* Configure watchdog */
WDOG->CNT = 0x1000; /* 4s timeout */
WDOG->TOVAL = 0x1000;
WDOG->CS = WDOG_CS_EN_MASK | WDOG_CS_CLK(1) |
WDOG_CS_WIN_MASK | WDOG_CS_UPDATE_MASK;
/* Enable faults */
SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk |
SCB_SHCSR_BUSFAULTENA_Msk |
SCB_SHCSR_USGFAULTENA_Msk;
/* Enable global interrupts */
__enable_irq();
}
/* Start First Task */
void port_start_first_task(void) {
TaskHandle_t first_task = scheduler_get_current_task();
if (first_task == NULL) {
return;
}
/* Set PSP */
__set_PSP((uint32_t)first_task->stack_pointer);
/* Switch to PSP */
__set_CONTROL(0x02);
__ISB();
/* Restore context */
__asm volatile (
"LDMIA R0!, {R4-R11}\n"
"MSR PSP, R0\n"
"MOV LR, #0xFFFFFFFD\n"
"BX LR\n"
:
: "r" (first_task->stack_pointer)
);
}
/* Context Switch */
void port_context_switch(uint32_t* current_context, uint32_t* next_context) {
current_task_sp = current_context;
next_task_sp = next_context;
/* Trigger PendSV */
SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk;
/* Data synchronization barrier */
__DSB();
__ISB();
}
/* Initialize Task Stack */
uint32_t* port_initialize_task_stack(TaskFunction_t task_function,
void* parameters,
uint32_t* stack_top) {
uint32_t* stack_ptr = stack_top;
/* 8-byte alignment */
stack_ptr = (uint32_t*)((uint32_t)stack_ptr & ~0x7);
/* Exception frame */
*(--stack_ptr) = 0x01000000; /* xPSR */
*(--stack_ptr) = (uint32_t)task_function; /* PC */
*(--stack_ptr) = 0xFFFFFFFD; /* LR */
*(--stack_ptr) = 0x00000000; /* R12 */
*(--stack_ptr) = 0x00000003; /* R3 */
*(--stack_ptr) = 0x00000002; /* R2 */
*(--stack_ptr) = 0x00000001; /* R1 */
*(--stack_ptr) = (uint32_t)parameters; /* R0 */
/* Additional context */
*(--stack_ptr) = 0x0000000B; /* R11 */
*(--stack_ptr) = 0x0000000A; /* R10 */
*(--stack_ptr) = 0x00000009; /* R9 */
*(--stack_ptr) = 0x00000008; /* R8 */
*(--stack_ptr) = 0x00000007; /* R7 */
*(--stack_ptr) = 0x00000006; /* R6 */
*(--stack_ptr) = 0x00000005; /* R5 */
*(--stack_ptr) = 0x00000004; /* R4 */
return stack_ptr;
}
/* LPIT Interrupt Handler */
void LPIT0_IRQHandler(void) {
/* Clear interrupt flag */
LPIT0->MSR |= (1 << LPIT_CHANNEL);
/* Call kernel tick handler */
extern void kernel_tick_handler(void);
kernel_tick_handler();
/* Service watchdog */
WDOG->CNT = 0xB480; /* Refresh sequence */
WDOG->CNT = 0x4B80;
}
/* PendSV Handler */
__attribute__((naked)) void PendSV_Handler(void) {
__asm volatile (
"MRS R0, PSP\n"
"STMDB R0!, {R4-R11}\n"
"LDR R1, =current_task_sp\n"
"STR R0, [R1]\n"
"LDR R0, =next_task_sp\n"
"LDR R1, [R0]\n"
"LDMIA R1!, {R4-R11}\n"
"MSR PSP, R1\n"
"BX LR\n"
);
}
/* SVC Handler */
__attribute__((naked)) void SVC_Handler(void) {
__asm volatile (
"TST LR, #4\n"
"ITE EQ\n"
"MRSEQ R0, MSP\n"
"MRSNE R0, PSP\n"
"LDR R0, [R0, #24]\n"
"LDRB R0, [R0, #-2]\n"
"PUSH {LR}\n"
"BL svc_handler\n"
"POP {LR}\n"
"BX LR\n"
);
}
/* Fault Handlers */
void MemManage_Handler(void) {
uint32_t fault_address = SCB->MMFAR;
uint32_t fault_status = SCB->CFSR;
extern void fault_handler_process(uint32_t type, uint32_t address, uint32_t status);
fault_handler_process(2, fault_address, fault_status);
while(1) {
/* Safe state */
WDOG->CNT = 0xB480;
WDOG->CNT = 0x4B80;
}
}
void BusFault_Handler(void) {
uint32_t fault_address = SCB->BFAR;
uint32_t fault_status = SCB->CFSR;
extern void fault_handler_process(uint32_t type, uint32_t address, uint32_t status);
fault_handler_process(3, fault_address, fault_status);
while(1) {
WDOG->CNT = 0xB480;
WDOG->CNT = 0x4B80;
}
}
void UsageFault_Handler(void) {
uint32_t fault_status = SCB->CFSR;
extern void fault_handler_process(uint32_t type, uint32_t address, uint32_t status);
fault_handler_process(4, 0, fault_status);
while(1) {
WDOG->CNT = 0xB480;
WDOG->CNT = 0x4B80;
}
}
void HardFault_Handler(void) {
uint32_t fault_status = SCB->HFSR;
extern void fault_handler_process(uint32_t type, uint32_t address, uint32_t status);
fault_handler_process(1, 0, fault_status);
while(1) {
WDOG->CNT = 0xB480;
WDOG->CNT = 0x4B80;
}
}
/* Enter Critical Section */
void port_disable_interrupts(void) {
__disable_irq();
}
/* Exit Critical Section */
void port_enable_interrupts(void) {
__enable_irq();
}
/* Get Current Exception Number */
uint32_t port_get_current_exception(void) {
return (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) >> SCB_ICSR_VECTACTIVE_Pos;
}
+185
View File
@@ -0,0 +1,185 @@
/**
* @file port_asm.s
* @brief NXP S32K assembly routines
*/
.syntax unified
.thumb
.arch armv7e-m
.section .text
/* Global symbols */
.global current_task_sp
.global next_task_sp
.global port_context_switch
.global port_start_first_task
.global port_disable_interrupts
.global port_enable_interrupts
/* Variables */
.section .bss
.align 3
current_task_sp: .word 0
next_task_sp: .word 0
.section .text
.thumb_func
/* Start First Task */
port_start_first_task:
/* Load task stack pointer */
ldr r0, =next_task_sp
ldr r1, [r0]
/* Set PSP */
msr PSP, r1
/* Switch to PSP */
mov r0, #2
msr CONTROL, r0
isb
/* Restore context */
ldmia r1!, {r4-r11}
msr PSP, r1
mov lr, #0xFFFFFFFD
bx lr
/* PendSV Handler */
PendSV_Handler:
/* Save context */
mrs r0, PSP
stmdb r0!, {r4-r11}
ldr r1, =current_task_sp
str r0, [r1]
/* Load next context */
ldr r0, =next_task_sp
ldr r1, [r0]
ldmia r1!, {r4-r11}
msr PSP, r1
bx lr
/* SVC Handler */
SVC_Handler:
tst lr, #4
ite eq
mrseq r0, MSP
mrsne r0, PSP
ldr r0, [r0, #24]
ldrb r0, [r0, #-2]
push {lr}
bl svc_handler
pop {lr}
bx lr
/* Disable Interrupts */
port_disable_interrupts:
cpsid i
bx lr
/* Enable Interrupts */
port_enable_interrupts:
cpsie i
bx lr
/* LPIT Interrupt Handler */
LPIT0_IRQHandler:
/* Save context */
push {r4-r11, lr}
/* Clear interrupt flag */
ldr r0, =0x40037008 /* LPIT0->MSR */
movs r1, #1
str r1, [r0]
/* Call kernel tick handler */
bl kernel_tick_handler
/* Service watchdog */
ldr r0, =0x40052000 /* WDOG->CNT */
ldr r1, =0xB480
str r1, [r0]
ldr r1, =0x4B80
str r1, [r0]
/* Restore context */
pop {r4-r11, lr}
bx lr
/* Hard Fault Handler */
HardFault_Handler:
/* Save context */
mrs r0, PSP
stmdb r0!, {r4-r11}
/* Get fault status */
ldr r2, =0xE000ED2C /* HFSR */
ldr r2, [r2]
/* Call fault handler */
movs r0, #1
movs r1, #0
bl fault_handler_process
/* Safe state */
b .
/* Memory Management Fault */
MemManage_Handler:
/* Save context */
mrs r0, PSP
stmdb r0!, {r4-r11}
/* Get fault information */
ldr r1, =0xE000ED34 /* MMFAR */
ldr r1, [r1]
ldr r2, =0xE000ED28 /* CFSR */
ldr r2, [r2]
/* Call fault handler */
movs r0, #2
bl fault_handler_process
/* Safe state */
b .
/* Bus Fault Handler */
BusFault_Handler:
/* Save context */
mrs r0, PSP
stmdb r0!, {r4-r11}
/* Get fault information */
ldr r1, =0xE000ED38 /* BFAR */
ldr r1, [r1]
ldr r2, =0xE000ED28 /* CFSR */
ldr r2, [r2]
/* Call fault handler */
movs r0, #3
bl fault_handler_process
/* Safe state */
b .
/* Usage Fault Handler */
UsageFault_Handler:
/* Save context */
mrs r0, PSP
stmdb r0!, {r4-r11}
/* Get fault status */
ldr r2, =0xE000ED28 /* CFSR */
ldr r2, [r2]
/* Call fault handler */
movs r0, #4
movs r1, #0
bl fault_handler_process
/* Safe state */
b .
.end
+55
View File
@@ -0,0 +1,55 @@
/**
* @file portmacro.h
* @brief NXP S32K specific macros
*/
#ifndef PORTMACRO_H
#define PORTMACRO_H
#include <stdint.h>
#include "S32K144.h"
/* Data Types */
typedef uint32_t port_stack_type_t;
typedef uint32_t port_base_type_t;
/* Architecture Constants */
#define PORT_STACK_GROWTH_DIRECTION (-1)
#define PORT_BYTE_ALIGNMENT 8
#define PORT_MAX_SYSCALL_INTERRUPT_PRIORITY 0x50
/* Critical Section Macros */
#define portENTER_CRITICAL() __asm volatile("CPSID I" ::: "memory")
#define portEXIT_CRITICAL() __asm volatile("CPSIE I" ::: "memory")
/* Interrupt Control */
#define portENABLE_INTERRUPTS() __asm volatile("CPSIE I" ::: "memory")
#define portDISABLE_INTERRUPTS() __asm volatile("CPSID I" ::: "memory")
/* Context Switch */
#define portYIELD() SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk
#define portYIELD_FROM_ISR() SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk
/* Memory Barriers */
#define portMEMORY_BARRIER() __asm volatile("DMB" ::: "memory")
#define portSYNC_BARRIER() __asm volatile("DSB" ::: "memory")
#define portINSTRUCTION_BARRIER() __asm volatile("ISB" ::: "memory")
/* NOP */
#define portNOP() __asm volatile("NOP")
/* Watchdog Control */
#define portSERVICE_WATCHDOG() \
do { \
WDOG->CNT = 0xB480; \
WDOG->CNT = 0x4B80; \
} while(0)
/* Low Power Modes */
#define portENTER_SLEEP() __asm volatile("WFI")
#define portENTER_DEEP_SLEEP() __asm volatile("WFE")
/* Endian Definition */
#define portBYTE_ORDER LITTLE_ENDIAN
#endif /* PORTMACRO_H */
+237
View File
@@ -0,0 +1,237 @@
/**
* @file port.c
* @brief RISC-V RV32 architecture specific port
* @note RISC-V is emerging in automotive applications
*/
#include "kernel.h"
#include "task.h"
#include "scheduler.h"
#include "portmacro.h"
/* Context storage */
uint32_t* current_task_sp = NULL;
uint32_t* next_task_sp = NULL;
/* Machine Timer registers */
#define MTIME_ADDR 0x0200BFF8
#define MTIMECMP_ADDR 0x02004000
/* Initialize Architecture Port */
void port_init(void) {
/* Configure machine timer for 1ms interrupts */
volatile uint32_t* mtime = (uint32_t*)MTIME_ADDR;
volatile uint32_t* mtimecmp = (uint32_t*)MTIMECMP_ADDR;
uint32_t current_time = *mtime;
*mtimecmp = current_time + (SystemCoreClock / 1000);
/* Enable machine timer interrupt */
__asm volatile (
"li t0, 0x80\n" /* Machine Timer Interrupt Enable */
"csrs mie, t0\n"
);
/* Enable global interrupts */
__asm volatile (
"csrsi mstatus, 0x8\n" /* Machine Interrupt Enable */
);
}
/* Start First Task */
void port_start_first_task(void) {
TaskHandle_t first_task = scheduler_get_current_task();
if (first_task == NULL) {
return;
}
/* Load task stack pointer */
__asm volatile (
"mv sp, %0\n"
"ret\n"
:
: "r" (first_task->stack_pointer)
);
}
/* Context Switch */
void port_context_switch(uint32_t* current_context, uint32_t* next_context) {
current_task_sp = current_context;
next_task_sp = next_context;
/* Trigger software interrupt */
__asm volatile (
"li t0, 0x8\n" /* Machine Software Interrupt */
"csrs mip, t0\n"
);
}
/* Initialize Task Stack */
uint32_t* port_initialize_task_stack(TaskFunction_t task_function,
void* parameters,
uint32_t* stack_top) {
uint32_t* stack_ptr = stack_top;
/* Align to 16 bytes */
stack_ptr = (uint32_t*)((uint32_t)stack_ptr & ~0xF);
/* Initial stack frame */
*(--stack_ptr) = (uint32_t)parameters; /* a0 */
*(--stack_ptr) = 0; /* a1 */
*(--stack_ptr) = 0; /* a2 */
*(--stack_ptr) = 0; /* a3 */
*(--stack_ptr) = 0; /* a4 */
*(--stack_ptr) = 0; /* a5 */
*(--stack_ptr) = 0; /* a6 */
*(--stack_ptr) = 0; /* a7 */
*(--stack_ptr) = (uint32_t)task_function; /* ra */
*(--stack_ptr) = 0; /* t0 */
*(--stack_ptr) = 0; /* t1 */
*(--stack_ptr) = 0; /* t2 */
*(--stack_ptr) = 0; /* t3 */
*(--stack_ptr) = 0; /* t4 */
*(--stack_ptr) = 0; /* t5 */
*(--stack_ptr) = 0; /* t6 */
*(--stack_ptr) = 0; /* s0 */
*(--stack_ptr) = 0; /* s1 */
*(--stack_ptr) = 0; /* s2 */
*(--stack_ptr) = 0; /* s3 */
*(--stack_ptr) = 0; /* s4 */
*(--stack_ptr) = 0; /* s5 */
*(--stack_ptr) = 0; /* s6 */
*(--stack_ptr) = 0; /* s7 */
*(--stack_ptr) = 0; /* s8 */
*(--stack_ptr) = 0; /* s9 */
*(--stack_ptr) = 0; /* s10 */
*(--stack_ptr) = 0; /* s11 */
*(--stack_ptr) = 0; /* gp */
*(--stack_ptr) = 0; /* tp */
/* mstatus */
*(--stack_ptr) = 0x00001880; /* MPP = Machine mode */
return stack_ptr;
}
/* Machine Timer Interrupt Handler */
void machine_timer_interrupt_handler(void) {
/* Clear interrupt */
volatile uint32_t* mtimecmp = (uint32_t*)MTIMECMP_ADDR;
volatile uint32_t* mtime = (uint32_t*)MTIME_ADDR;
*mtimecmp = *mtime + (SystemCoreClock / 1000);
/* Call kernel tick handler */
extern void kernel_tick_handler(void);
kernel_tick_handler();
}
/* Machine Software Interrupt Handler */
void machine_software_interrupt_handler(void) {
/* Clear interrupt */
__asm volatile (
"li t0, 0x8\n"
"csrc mip, t0\n"
);
/* Perform context switch */
__asm volatile (
/* Save current context */
"addi sp, sp, -128\n"
"sw ra, 0(sp)\n"
"sw t0, 4(sp)\n"
"sw t1, 8(sp)\n"
"sw t2, 12(sp)\n"
"sw s0, 16(sp)\n"
"sw s1, 20(sp)\n"
"sw a0, 24(sp)\n"
"sw a1, 28(sp)\n"
"sw a2, 32(sp)\n"
"sw a3, 36(sp)\n"
"sw a4, 40(sp)\n"
"sw a5, 44(sp)\n"
"sw a6, 48(sp)\n"
"sw a7, 52(sp)\n"
"sw s2, 56(sp)\n"
"sw s3, 60(sp)\n"
"sw s4, 64(sp)\n"
"sw s5, 68(sp)\n"
"sw s6, 72(sp)\n"
"sw s7, 76(sp)\n"
"sw s8, 80(sp)\n"
"sw s9, 84(sp)\n"
"sw s10, 88(sp)\n"
"sw s11, 92(sp)\n"
"sw t3, 96(sp)\n"
"sw t4, 100(sp)\n"
"sw t5, 104(sp)\n"
"sw t6, 108(sp)\n"
"csrr t0, mstatus\n"
"sw t0, 112(sp)\n"
"csrr t0, mepc\n"
"sw t0, 116(sp)\n"
/* Save current stack pointer */
"la t0, current_task_sp\n"
"sw sp, 0(t0)\n"
/* Load next stack pointer */
"la t0, next_task_sp\n"
"lw sp, 0(t0)\n"
/* Restore next context */
"lw ra, 0(sp)\n"
"lw t0, 4(sp)\n"
"lw t1, 8(sp)\n"
"lw t2, 12(sp)\n"
"lw s0, 16(sp)\n"
"lw s1, 20(sp)\n"
"lw a0, 24(sp)\n"
"lw a1, 28(sp)\n"
"lw a2, 32(sp)\n"
"lw a3, 36(sp)\n"
"lw a4, 40(sp)\n"
"lw a5, 44(sp)\n"
"lw a6, 48(sp)\n"
"lw a7, 52(sp)\n"
"lw s2, 56(sp)\n"
"lw s3, 60(sp)\n"
"lw s4, 64(sp)\n"
"lw s5, 68(sp)\n"
"lw s6, 72(sp)\n"
"lw s7, 76(sp)\n"
"lw s8, 80(sp)\n"
"lw s9, 84(sp)\n"
"lw s10, 88(sp)\n"
"lw s11, 92(sp)\n"
"lw t3, 96(sp)\n"
"lw t4, 100(sp)\n"
"lw t5, 104(sp)\n"
"lw t6, 108(sp)\n"
"lw t0, 112(sp)\n"
"csrw mstatus, t0\n"
"lw t0, 116(sp)\n"
"csrw mepc, t0\n"
"addi sp, sp, 128\n"
/* Return from interrupt */
"mret\n"
);
}
/* Enter Critical Section */
void port_disable_interrupts(void) {
__asm volatile (
"csrci mstatus, 0x8\n" /* Clear Machine Interrupt Enable */
);
}
/* Exit Critical Section */
void port_enable_interrupts(void) {
__asm volatile (
"csrsi mstatus, 0x8\n" /* Set Machine Interrupt Enable */
);
}
+39
View File
@@ -0,0 +1,39 @@
/**
* @file portmacro.h
* @brief RISC-V RV32 specific macros
*/
#ifndef PORTMACRO_H
#define PORTMACRO_H
#include <stdint.h>
/* Data Types */
typedef uint32_t port_stack_type_t;
typedef uint32_t port_base_type_t;
/* Architecture Constants */
#define PORT_STACK_GROWTH_DIRECTION (-1)
#define PORT_BYTE_ALIGNMENT 16
/* Critical Section Macros */
#define portENTER_CRITICAL() __asm volatile("csrci mstatus, 0x8")
#define portEXIT_CRITICAL() __asm volatile("csrsi mstatus, 0x8")
/* Interrupt Control */
#define portENABLE_INTERRUPTS() __asm volatile("csrsi mstatus, 0x8")
#define portDISABLE_INTERRUPTS() __asm volatile("csrci mstatus, 0x8")
/* Context Switch */
#define portYIELD() __asm volatile("li t0, 0x8\ncsrs mip, t0")
#define portYIELD_FROM_ISR() __asm volatile("li t0, 0x8\ncsrs mip, t0")
/* Memory Barriers */
#define portMEMORY_BARRIER() __asm volatile("fence")
#define portSYNC_BARRIER() __asm volatile("fence")
#define portINSTRUCTION_BARRIER() __asm volatile("fence.i")
/* NOP */
#define portNOP() __asm volatile("nop")
#endif /* PORTMACRO_H */
+36
View File
@@ -0,0 +1,36 @@
/**
* @file isr.h
* @brief Interrupt Service Routine management
*/
#ifndef ISR_H
#define ISR_H
#include "kernel.h"
/* ISR Types */
typedef void (*ISRHandler_t)(void);
/* ISR Configuration */
typedef struct {
uint32_t irq_number;
ISRHandler_t handler;
uint8_t priority;
} ISRConfig_t;
/* ISR Functions */
KernelStatus_t isr_register(uint32_t irq_number, ISRHandler_t handler,
uint8_t priority);
KernelStatus_t isr_unregister(uint32_t irq_number);
KernelStatus_t isr_enable(uint32_t irq_number);
KernelStatus_t isr_disable(uint32_t irq_number);
KernelStatus_t isr_set_priority(uint32_t irq_number, uint8_t priority);
void isr_enter(void);
void isr_exit(void);
bool isr_is_in_context(void);
/* Critical Section Management */
void critical_section_enter(void);
void critical_section_exit(void);
#endif /* ISR_H */
+102
View File
@@ -0,0 +1,102 @@
/**
* @file kernel.h
* @brief Core kernel definitions and types for Automotive RTOS
* @author Automotive RTOS Team
* @version 1.0
*/
#ifndef KERNEL_H
#define KERNEL_H
#include <stdint.h>
#include <stdbool.h>
/* Kernel Version */
#define KERNEL_VERSION_MAJOR 1
#define KERNEL_VERSION_MINOR 0
#define KERNEL_VERSION_PATCH 0
/* Configuration Constants */
#define MAX_TASKS 32
#define MAX_PRIORITY_LEVELS 16
#define MAX_TASK_NAME_LENGTH 16
#define IDLE_TASK_PRIORITY (MAX_PRIORITY_LEVELS - 1)
/* Task States */
typedef enum {
TASK_SUSPENDED = 0,
TASK_READY = 1,
TASK_RUNNING = 2,
TASK_BLOCKED = 3,
TASK_TERMINATED = 4
} TaskState_t;
/* Task Priority Type */
typedef uint8_t TaskPriority_t;
/* Task Handle */
typedef struct TaskControlBlock* TaskHandle_t;
/* Task Function */
typedef void (*TaskFunction_t)(void* parameters);
/* Time Types */
typedef uint32_t TickType_t;
typedef uint32_t TimeOut_t;
/* Error Codes */
typedef enum {
KERNEL_OK = 0,
KERNEL_ERROR = -1,
KERNEL_INVALID_PARAMETER = -2,
KERNEL_OUT_OF_MEMORY = -3,
KERNEL_TASK_NOT_FOUND = -4,
KERNEL_PRIORITY_INVALID = -5,
KERNEL_TIMEOUT = -6,
KERNEL_RESOURCE_BUSY = -7
} KernelStatus_t;
/* Task Creation Parameters */
typedef struct {
const char* name;
TaskFunction_t function;
void* parameters;
uint32_t stack_size;
TaskPriority_t priority;
TickType_t period_ticks; /* 0 for aperiodic tasks */
} TaskConfig_t;
/* Task Statistics */
typedef struct {
uint32_t execution_count;
TickType_t last_execution_time;
TickType_t max_execution_time;
TickType_t total_execution_time;
uint32_t stack_high_water_mark;
uint32_t deadline_misses;
} TaskStatistics_t;
/* Kernel Core Functions */
KernelStatus_t kernel_init(void);
KernelStatus_t kernel_start(void);
void kernel_stop(void);
TickType_t kernel_get_tick_count(void);
KernelStatus_t kernel_delay(TickType_t ticks);
/* Task Management Functions */
TaskHandle_t task_create(const TaskConfig_t* config);
KernelStatus_t task_delete(TaskHandle_t task);
KernelStatus_t task_suspend(TaskHandle_t task);
KernelStatus_t task_resume(TaskHandle_t task);
KernelStatus_t task_set_priority(TaskHandle_t task, TaskPriority_t new_priority);
TaskPriority_t task_get_priority(TaskHandle_t task);
TaskState_t task_get_state(TaskHandle_t task);
KernelStatus_t task_get_statistics(TaskHandle_t task, TaskStatistics_t* stats);
/* Scheduler Control */
void scheduler_yield(void);
void scheduler_lock(void);
void scheduler_unlock(void);
TaskHandle_t scheduler_get_current_task(void);
#endif /* KERNEL_H */
+28
View File
@@ -0,0 +1,28 @@
/**
* @file mutex.h
* @brief Mutex with priority inheritance
*/
#ifndef MUTEX_H
#define MUTEX_H
#include "kernel.h"
/* Mutex Control Block */
typedef struct {
TaskHandle_t owner;
TaskPriority_t original_priority;
uint32_t lock_count;
TaskHandle_t* waiting_tasks;
uint32_t waiting_count;
bool recursive;
} Mutex_t;
/* Mutex Functions */
KernelStatus_t mutex_create(Mutex_t* mutex, bool recursive);
KernelStatus_t mutex_lock(Mutex_t* mutex, TimeOut_t timeout);
KernelStatus_t mutex_unlock(Mutex_t* mutex);
KernelStatus_t mutex_delete(Mutex_t* mutex);
TaskHandle_t mutex_get_owner(Mutex_t* mutex);
#endif /* MUTEX_H */
+35
View File
@@ -0,0 +1,35 @@
/**
* @file queue.h
* @brief Message queue for inter-task communication
*/
#ifndef QUEUE_H
#define QUEUE_H
#include "kernel.h"
/* Queue Control Block */
typedef struct {
void* buffer;
uint32_t item_size;
uint32_t max_items;
uint32_t current_items;
uint32_t head;
uint32_t tail;
TaskHandle_t* waiting_senders;
TaskHandle_t* waiting_receivers;
uint32_t waiting_sender_count;
uint32_t waiting_receiver_count;
} Queue_t;
/* Queue Functions */
KernelStatus_t queue_create(Queue_t* queue, void* buffer, uint32_t item_size,
uint32_t max_items);
KernelStatus_t queue_send(Queue_t* queue, const void* item, TimeOut_t timeout);
KernelStatus_t queue_receive(Queue_t* queue, void* item, TimeOut_t timeout);
KernelStatus_t queue_send_from_isr(Queue_t* queue, const void* item);
KernelStatus_t queue_receive_from_isr(Queue_t* queue, void* item);
uint32_t queue_get_count(Queue_t* queue);
KernelStatus_t queue_delete(Queue_t* queue);
#endif /* QUEUE_H */
+47
View File
@@ -0,0 +1,47 @@
/**
* @file scheduler.h
* @brief Priority-based preemptive scheduler
*/
#ifndef SCHEDULER_H
#define SCHEDULER_H
#include "kernel.h"
#include "task.h"
/* Scheduler Types */
typedef enum {
SCHEDULER_PRIORITY_PREEMPTIVE = 0,
SCHEDULER_ROUND_ROBIN = 1,
SCHEDULER_EDF = 2, /* Earliest Deadline First */
SCHEDULER_RATE_MONOTONIC = 3
} SchedulerType_t;
/* Scheduler Configuration */
typedef struct {
SchedulerType_t type;
TickType_t time_slice_ticks; /* For round-robin */
bool enable_deadline_monitoring;
} SchedulerConfig_t;
/* Scheduler Interface */
void scheduler_init(const SchedulerConfig_t* config);
void scheduler_start(void);
void scheduler_tick(void);
void scheduler_add_task(TaskHandle_t task);
void scheduler_remove_task(TaskHandle_t task);
void scheduler_update_task_state(TaskHandle_t task, TaskState_t new_state);
TaskHandle_t scheduler_select_next_task(void);
void scheduler_context_switch(TaskHandle_t next_task);
/* Scheduler Statistics */
typedef struct {
uint32_t context_switches;
uint32_t preemptions;
TickType_t max_scheduling_latency;
TickType_t total_idle_time;
} SchedulerStatistics_t;
void scheduler_get_statistics(SchedulerStatistics_t* stats);
#endif /* SCHEDULER_H */
+37
View File
@@ -0,0 +1,37 @@
/**
* @file semaphore.h
* @brief Semaphore synchronization primitive
*/
#ifndef SEMAPHORE_H
#define SEMAPHORE_H
#include "kernel.h"
/* Semaphore Types */
typedef enum {
SEMAPHORE_BINARY = 0,
SEMAPHORE_COUNTING = 1,
SEMAPHORE_MUTEX = 2
} SemaphoreType_t;
/* Semaphore Control Block */
typedef struct {
SemaphoreType_t type;
uint32_t count;
uint32_t max_count;
TaskHandle_t owner; /* For mutex */
uint8_t priority_ceiling;
TaskHandle_t* waiting_tasks;
uint32_t waiting_count;
} Semaphore_t;
/* Semaphore Functions */
KernelStatus_t semaphore_create(Semaphore_t* sem, SemaphoreType_t type,
uint32_t initial_count, uint32_t max_count);
KernelStatus_t semaphore_take(Semaphore_t* sem, TimeOut_t timeout);
KernelStatus_t semaphore_give(Semaphore_t* sem);
KernelStatus_t semaphore_delete(Semaphore_t* sem);
uint32_t semaphore_get_count(Semaphore_t* sem);
#endif /* SEMAPHORE_H */
+58
View File
@@ -0,0 +1,58 @@
/**
* @file task.h
* @brief Task management interface
*/
#ifndef TASK_H
#define TASK_H
#include "kernel.h"
/* Internal Task Control Block */
struct TaskControlBlock {
/* Task Identification */
char name[MAX_TASK_NAME_LENGTH];
TaskHandle_t self;
uint32_t task_id;
/* Task Function */
TaskFunction_t function;
void* parameters;
/* Stack Management */
uint32_t* stack_pointer;
uint32_t* stack_base;
uint32_t stack_size;
uint32_t stack_high_water_mark;
/* Scheduling Information */
TaskPriority_t priority;
TaskState_t state;
TickType_t period_ticks;
TickType_t last_wake_time;
TickType_t deadline_ticks;
/* Blocking Information */
TickType_t block_timeout;
void* blocked_on;
/* Statistics */
TaskStatistics_t statistics;
/* List Management */
struct TaskControlBlock* next;
struct TaskControlBlock* prev;
/* Architecture Specific */
uint32_t context[32]; /* CPU register context */
};
/* Internal Task Management Functions */
void task_init(void);
void task_switch_context(TaskHandle_t next_task);
TaskHandle_t task_get_idle_task(void);
void task_update_statistics(void);
void task_check_stack_overflow(void);
bool task_is_ready(TaskHandle_t task);
#endif /* TASK_H */

Some files were not shown because too many files have changed in this diff Show More