You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
cbmc/codedetect/scripts/freertos-setup.sh

601 lines
16 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#!/bin/bash
# FreeRTOS环境设置脚本
# 用于设置CodeDetect项目中的FreeRTOS验证环境
set -e
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# 配置变量
FREERTOS_VERSION="10.4.6"
FREERTOS_SOURCE_URL="https://github.com/FreeRTOS/FreeRTOS-Kernel/archive/refs/tags/V${FREERTOS_VERSION}.tar.gz"
INSTALL_DIR="/opt/freertos"
CODEDETECT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
FREERTOS_CONFIG_DIR="${CODEDETECT_DIR}/config/freertos"
# 日志函数
log_info() {
echo -e "${BLUE}[INFO]${NC} $1"
}
log_success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
}
log_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
# 检查依赖
check_dependencies() {
log_info "检查系统依赖..."
local deps=("wget" "tar" "gcc" "make" "cmake" "python3" "pip3")
local missing_deps=()
for dep in "${deps[@]}"; do
if ! command -v "$dep" &> /dev/null; then
missing_deps+=("$dep")
fi
done
if [ ${#missing_deps[@]} -gt 0 ]; then
log_error "缺少以下依赖: ${missing_deps[*]}"
log_info "请安装缺少的依赖:"
echo " Ubuntu/Debian: sudo apt-get install ${missing_deps[*]}"
echo " CentOS/RHEL: sudo yum install ${missing_deps[*]}"
exit 1
fi
log_success "所有依赖已安装"
}
# 创建目录结构
create_directory_structure() {
log_info "创建目录结构..."
# 创建主安装目录
sudo mkdir -p "$INSTALL_DIR"
sudo chown "$USER:$USER" "$INSTALL_DIR"
# 创建FreeRTOS子目录
mkdir -p "$INSTALL_DIR/src"
mkdir -p "$INSTALL_DIR/include"
mkdir -p "$INSTALL_DIR/config"
mkdir -p "$INSTALL_DIR/examples"
# 创建CodeDetect配置目录
mkdir -p "$FREERTOS_CONFIG_DIR"
log_success "目录结构创建完成"
}
# 下载FreeRTOS源码
download_freertos() {
log_info "下载FreeRTOS源码 (版本: $FREERTOS_VERSION)..."
cd "$INSTALL_DIR/src"
if [ ! -f "FreeRTOS-Kernel-${FREERTOS_VERSION}.tar.gz" ]; then
wget "$FREERTOS_SOURCE_URL" -O "FreeRTOS-Kernel-${FREERTOS_VERSION}.tar.gz"
fi
# 解压源码
if [ ! -d "FreeRTOS-Kernel-${FREERTOS_VERSION}" ]; then
tar -xzf "FreeRTOS-Kernel-${FREERTOS_VERSION}.tar.gz"
fi
# 创建符号链接
ln -sf "FreeRTOS-Kernel-${FREERTOS_VERSION}" "freertos-kernel"
log_success "FreeRTOS源码下载完成"
}
# 安装FreeRTOS头文件
install_headers() {
log_info "安装FreeRTOS头文件..."
local kernel_dir="$INSTALL_DIR/src/freertos-kernel"
# 复制核心头文件
cp -r "$kernel_dir/include" "$INSTALL_DIR/"
# 复制便携层头文件选择x86_64作为示例
cp -r "$kernel_dir/portable/GCC/Linux" "$INSTALL_DIR/portable/"
# 创建include目录的符号链接
ln -sf "$INSTALL_DIR/include" "$INSTALL_DIR/freertos"
log_success "FreeRTOS头文件安装完成"
}
# 创建配置文件
create_config_files() {
log_info "创建FreeRTOS配置文件..."
# 创建基础FreeRTOSConfig.h
cat > "$FREERTOS_CONFIG_DIR/FreeRTOSConfig.h" << 'EOF'
#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H
/* 包含标准头文件 */
#include <stdint.h>
#include <stdlib.h>
/* 基础配置 */
#define configUSE_PREEMPTION 1
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
#define configUSE_TICKLESS_IDLE 0
#define configCPU_CLOCK_HZ ( ( uint32_t ) 16000000 )
#define configTICK_RATE_HZ ( ( TickType_t ) 1000 )
#define configMAX_PRIORITIES ( 5 )
#define configMINIMAL_STACK_SIZE ( ( uint16_t ) 128 )
#define configMAX_TASK_NAME_LEN ( 16 )
#define configUSE_16_BIT_TICKS 0
#define configIDLE_SHOULD_YIELD 1
#define configUSE_TASK_NOTIFICATIONS 1
#define configUSE_MUTEXES 1
#define configUSE_RECURSIVE_MUTEXES 1
#define configUSE_COUNTING_SEMAPHORES 1
#define configQUEUE_REGISTRY_SIZE 10
#define configUSE_QUEUE_SETS 0
#define configUSE_TIME_SLICING 1
#define configUSE_NEWLIB_REENTRANT 0
#define configENABLE_BACKWARD_COMPATIBILITY 0
#define configNUM_THREAD_LOCAL_STORAGE_POINTERS 5
/* 内存分配相关 */
#define configSUPPORT_STATIC_ALLOCATION 1
#define configSUPPORT_DYNAMIC_ALLOCATION 1
#define configTOTAL_HEAP_SIZE ( ( size_t ) 40960 )
#define configAPPLICATION_ALLOCATED_HEAP 0
/* 钩子函数相关 */
#define configUSE_IDLE_HOOK 0
#define configUSE_TICK_HOOK 0
#define configCHECK_FOR_STACK_OVERFLOW 2
#define configUSE_MALLOC_FAILED_HOOK 1
#define configUSE_DAEMON_TASK_STARTUP_HOOK 0
/* 运行时统计相关 */
#define configGENERATE_RUN_TIME_STATS 0
#define configUSE_TRACE_FACILITY 0
#define configUSE_STATS_FORMATTING_FUNCTIONS 0
/* 协程相关 */
#define configUSE_CO_ROUTINES 0
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
/* 软件定时器相关 */
#define configUSE_TIMERS 1
#define configTIMER_TASK_PRIORITY ( configMAX_PRIORITIES - 1 )
#define configTIMER_QUEUE_LENGTH 10
#define configTIMER_TASK_STACK_DEPTH ( configMINIMAL_STACK_SIZE * 2 )
/* 中断配置 */
#define configKERNEL_INTERRUPT_PRIORITY 0
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 0
#define configLIBRARY_KERNEL_INTERRUPT_PRIORITY 0
/* 定义和断言 */
#define configASSERT( x ) if ((x) == 0) {taskDISABLE_INTERRUPTS(); for( ;; );}
/* 可选函数定义 */
#define INCLUDE_vTaskPrioritySet 1
#define INCLUDE_uxTaskPriorityGet 1
#define INCLUDE_vTaskDelete 1
#define INCLUDE_vTaskCleanUpResources 0
#define INCLUDE_vTaskSuspend 1
#define INCLUDE_vTaskDelayUntil 1
#define INCLUDE_vTaskDelay 1
#define INCLUDE_xTaskGetSchedulerState 1
#define INCLUDE_xTimerPendFunctionCall 1
#define INCLUDE_xQueueGetMutexHolder 1
#define INCLUDE_uxTaskGetStackHighWaterMark 1
#define INCLUDE_eTaskGetState 1
#define INCLUDE_xTaskAbortDelay 1
#define INCLUDE_xTaskGetHandle 1
/* 映射函数到Linux环境 */
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()
#define portGET_RUN_TIME_COUNTER_VALUE() 0
/* 针对CBMC验证的特定配置 */
#ifdef CBMC_VERIFICATION
#define configASSERT( x ) if ((x) == 0) { __CPROVER_assert(0, "FreeRTOS config assertion failed"); }
#endif
#endif /* FREERTOS_CONFIG_H */
EOF
# 创建测试专用配置
cat > "$FREERTOS_CONFIG_DIR/FreeRTOSConfig_Test.h" << 'EOF'
#ifndef FREERTOS_CONFIG_TEST_H
#define FREERTOS_CONFIG_TEST_H
#include "FreeRTOSConfig.h"
/* 测试环境特定配置 */
#define configTOTAL_HEAP_SIZE ( ( size_t ) 8192 )
#define configMINIMAL_STACK_SIZE ( ( uint16_t ) 64 )
#define configMAX_PRIORITIES ( 3 )
#define configTICK_RATE_HZ ( ( TickType_t ) 100 )
/* CBMC验证优化 */
#ifdef CBMC_VERIFICATION
#define configMAX_TASK_NAME_LEN ( 8 )
#define configQUEUE_REGISTRY_SIZE 3
#define configTIMER_QUEUE_LENGTH 3
#endif
#endif /* FREERTOS_CONFIG_TEST_H */
EOF
# 创建CodeDetect集成配置
cat > "$FREERTOS_CONFIG_DIR/codedetect_freertos.yaml" << EOF
# FreeRTOS配置文件 - CodeDetect集成
freertos:
version: "$FREERTOS_VERSION"
install_path: "$INSTALL_DIR"
include_paths:
- "$INSTALL_DIR/include"
- "$INSTALL_DIR/portable/GCC/Linux"
config_files:
- "$FREERTOS_CONFIG_DIR/FreeRTOSConfig.h"
- "$FREERTOS_CONFIG_DIR/FreeRTOSConfig_Test.h"
# 验证参数
verification:
max_tasks: 10
max_queues: 5
max_semaphores: 5
max_timers: 3
heap_size: 8192
stack_size: 1024
# CBMC配置
cbmc:
include_paths:
- "$INSTALL_DIR/include"
- "$INSTALL_DIR/portable/GCC/Linux"
defines:
- "CBMC_VERIFICATION"
unwind_set:
task: 5
queue: 3
timer: 2
options:
- "--bounds-check"
- "--pointer-check"
- "--memory-leak-check"
- "--div-by-zero-check"
- "--float-div-by-zero-check"
# 编译配置
compilation:
c_flags: "-std=c99 -Wall -Wextra -I$INSTALL_DIR/include"
ld_flags: "-lpthread -lrt"
# 示例配置
examples:
task_verification:
source: "examples/freertos/task_verification_example.c"
config: "FreeRTOSConfig.h"
queue_verification:
source: "examples/freertos/queue_verification_example.c"
config: "FreeRTOSConfig.h"
EOF
log_success "配置文件创建完成"
}
# 创建示例构建脚本
create_build_scripts() {
log_info "创建构建脚本..."
# 创建主构建脚本
cat > "$INSTALL_DIR/build_freertos.sh" << 'EOF'
#!/bin/bash
# FreeRTOS构建脚本
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
FREERTOS_DIR="$SCRIPT_DIR/src/freertos-kernel"
PORTABLE_DIR="$SCRIPT_DIR/portable/GCC/Linux"
# 编译参数
CC="gcc"
CFLAGS="-std=c99 -Wall -Wextra -I$SCRIPT_DIR/include"
LDFLAGS="-lpthread -lrt"
# 创建构建目录
BUILD_DIR="$SCRIPT_DIR/build"
mkdir -p "$BUILD_DIR"
# 编译FreeRTOS核心
echo "编译FreeRTOS核心..."
$CC $CFLAGS -c \
"$FREERTOS_DIR/tasks.c" \
"$FREERTOS_DIR/queue.c" \
"$FREERTOS_DIR/timers.c" \
"$FREERTOS_DIR/event_groups.c" \
"$FREERTOS_DIR/list.c" \
"$PORTABLE_DIR/port.c" \
"$PORTABLE_DIR/../memory.c" \
-o "$BUILD_DIR/freertos.o"
# 创建静态库
echo "创建静态库..."
ar rcs "$BUILD_DIR/libfreertos.a" "$BUILD_DIR/freertos.o"
echo "FreeRTOS构建完成: $BUILD_DIR/libfreertos.a"
EOF
# 创建测试构建脚本
cat > "$INSTALL_DIR/test_example.sh" << 'EOF'
#!/bin/bash
# FreeRTOS示例测试脚本
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
BUILD_DIR="$SCRIPT_DIR/build"
CODEDETECT_DIR="$(cd "$SCRIPT_DIR/../.." && pwd)"
# 编译测试示例
echo "编译FreeRTOS测试示例..."
gcc -std=c99 -Wall -Wextra \
-I"$SCRIPT_DIR/include" \
-L"$BUILD_DIR" \
"$CODEDETECT_DIR/examples/freertos/task_verification_example.c" \
-lfreertos -lpthread -lrt \
-o "$BUILD_DIR/task_test"
gcc -std=c99 -Wall -Wextra \
-I"$SCRIPT_DIR/include" \
-L"$BUILD_DIR" \
"$CODEDETECT_DIR/examples/freertos/queue_verification_example.c" \
-lfreertos -lpthread -lrt \
-o "$BUILD_DIR/queue_test"
echo "示例编译完成:"
echo " 任务测试: $BUILD_DIR/task_test"
echo " 队列测试: $BUILD_DIR/queue_test"
EOF
# 使脚本可执行
chmod +x "$INSTALL_DIR/build_freertos.sh"
chmod +x "$INSTALL_DIR/test_example.sh"
log_success "构建脚本创建完成"
}
# 创建验证测试
create_verification_tests() {
log_info "创建验证测试..."
local test_dir="$INSTALL_DIR/tests"
mkdir -p "$test_dir"
# 创建基础验证测试
cat > "$test_dir/test_freertos_basic.c" << 'EOF'
#include "FreeRTOS.h"
#include "task.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void vTestTask(void *pvParameters) {
int counter = 0;
for (int i = 0; i < 10; i++) {
counter++;
vTaskDelay(pdMS_TO_TICKS(100));
}
printf("Test task completed: %d\n", counter);
vTaskDelete(NULL);
}
int main() {
printf("Starting FreeRTOS basic test...\n");
xTaskCreate(vTestTask, "Test", 128, NULL, 1, NULL);
vTaskStartScheduler();
return 0;
}
EOF
# 创建CBMC验证规范
cat > "$test_dir/cbmc_task_test.c" << 'EOF'
#include "FreeRTOS.h"
#include "task.h"
#include <assert.h>
void test_task_creation() {
TaskHandle_t xTaskHandle = NULL;
// 测试任务创建
BaseType_t xResult = xTaskCreate(
(TaskFunction_t)0, // 简化的任务函数
"TestTask",
configMINIMAL_STACK_SIZE,
NULL,
1,
&xTaskHandle
);
__CPROVER_assert(xResult == pdPASS, "Task creation should succeed");
__CPROVER_assert(xTaskHandle != NULL, "Task handle should not be NULL");
}
void test_task_parameters() {
// 测试任务参数边界
UBaseType_t uxPriority = configMAX_PRIORITIES - 1;
uint16_t usStackDepth = configMINIMAL_STACK_SIZE;
__CPROVER_assert(uxPriority < configMAX_PRIORITIES, "Priority should be valid");
__CPROVER_assert(usStackDepth >= configMINIMAL_STACK_SIZE, "Stack depth should be sufficient");
}
int main() {
test_task_creation();
test_task_parameters();
return 0;
}
EOF
log_success "验证测试创建完成"
}
# 设置环境变量
setup_environment() {
log_info "设置环境变量..."
local bashrc_file="$HOME/.bashrc"
local profile_file="$HOME/.profile"
# 检查是否已经设置
if ! grep -q "FREERTOS_HOME" "$bashrc_file" 2>/dev/null; then
cat >> "$bashrc_file" << EOF
# FreeRTOS环境变量
export FREERTOS_HOME="$INSTALL_DIR"
export FREERTOS_INCLUDE="$INSTALL_DIR/include"
export PATH="\$PATH:\$FREERTOS_HOME"
EOF
log_success "环境变量已添加到 ~/.bashrc"
else
log_warning "环境变量已存在"
fi
# 创建当前会话的环境变量
export FREERTOS_HOME="$INSTALL_DIR"
export FREERTOS_INCLUDE="$INSTALL_DIR/include"
export PATH="$PATH:$FREERTOS_HOME"
log_success "环境变量设置完成"
}
# 验证安装
verify_installation() {
log_info "验证FreeRTOS安装..."
# 检查目录结构
local required_dirs=(
"$INSTALL_DIR/include"
"$INSTALL_DIR/src/freertos-kernel"
"$INSTALL_DIR/portable"
"$FREERTOS_CONFIG_DIR"
)
for dir in "${required_dirs[@]}"; do
if [ ! -d "$dir" ]; then
log_error "目录不存在: $dir"
exit 1
fi
done
# 检查关键文件
local required_files=(
"$INSTALL_DIR/include/FreeRTOS.h"
"$INSTALL_DIR/include/task.h"
"$FREERTOS_CONFIG_DIR/FreeRTOSConfig.h"
"$INSTALL_DIR/build_freertos.sh"
)
for file in "${required_files[@]}"; do
if [ ! -f "$file" ]; then
log_error "文件不存在: $file"
exit 1
fi
done
# 测试编译
cd "$INSTALL_DIR"
if ! ./build_freertos.sh; then
log_error "FreeRTOS编译失败"
exit 1
fi
log_success "FreeRTOS安装验证完成"
}
# 显示使用说明
show_usage_info() {
echo ""
echo "======================================="
echo "FreeRTOS环境设置完成"
echo "======================================="
echo ""
echo "环境变量:"
echo " FREERTOS_HOME: $INSTALL_DIR"
echo " FREERTOS_INCLUDE: $INSTALL_DIR/include"
echo ""
echo "重要文件:"
echo " 配置文件: $FREERTOS_CONFIG_DIR/FreeRTOSConfig.h"
echo " 构建脚本: $INSTALL_DIR/build_freertos.sh"
echo " 测试脚本: $INSTALL_DIR/test_example.sh"
echo ""
echo "下一步操作:"
echo " 1. 重新启动终端或运行: source ~/.bashrc"
echo " 2. 编译FreeRTOS: cd $INSTALL_DIR && ./build_freertos.sh"
echo " 3. 运行测试示例: cd $INSTALL_DIR && ./test_example.sh"
echo " 4. 在CodeDetect中验证FreeRTOS代码"
echo ""
echo "CodeDetect集成:"
echo " 配置文件: $FREERTOS_CONFIG_DIR/codedetect_freertos.yaml"
echo " 示例代码: $CODEDETECT_DIR/examples/freertos/"
echo ""
}
# 主函数
main() {
echo "======================================="
echo "FreeRTOS环境设置脚本"
echo "======================================="
echo ""
# 检查是否已安装
if [ -f "$INSTALL_DIR/include/FreeRTOS.h" ]; then
log_warning "FreeRTOS已安装"
read -p "是否重新安装? (y/N): " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
log_info "安装已取消"
exit 0
fi
fi
# 执行安装步骤
check_dependencies
create_directory_structure
download_freertos
install_headers
create_config_files
create_build_scripts
create_verification_tests
setup_environment
verify_installation
show_usage_info
log_success "FreeRTOS环境设置完成"
}
# 脚本入口点
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
main "$@"
fi