UCOS-III笔记2-信号量

本文介绍了UCOSIII操作系统中二值信号量的基础概念和运行机制,包括创建、释放和获取信号量的函数及其参数说明,并通过一个控制LED亮灭的实验,展示了如何在任务间通过信号量实现同步。实验中遇到了信号量创建位置不当和错误类型定义问题,通过调整解决了这些问题。最后,通过调整任务优先级确保了key_task能够正常执行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、基础概念

一般使用二值信号量,这边先不对计数信号量做讨论

二值信号量的运行机制

 最开始创建一个信号量的时候,系统会将其置0,即无效信号量,任务接收到这个无效信号量的时候会进入阻塞态;

之后在中断或者任务中释放有效信号量,任务接收到该有效信号量的时候会进入就绪态,从而达到唤醒任务的目的

二、创建、释放、接收信号量

1、创建信号量函数:

OSSemCreate (OS_SEM *p_sem, //信号量控制块指针
             CPU_CHAR *p_name, //信号量名称
             OS_SEM_CTR cnt, //资源数目或事件是否发生标志
             OS_ERR *p_err)  //返回错误类型

创建信号量之前需要先定义错误类型和信号量控制块,下面是具体创建过程

OS_ERR err;  //错误类型
OS_SEM my_sem;  //信号量控制块

OSSemCreate((OS_SEM*)&my_sem,
            (CPU_CHAR*)"my_sem",
            (OS_SEM_CTR)0,
            (OS_ERR*)&err);

2、释放信号量函数:

OSSemPost (OS_SEM *p_sem, //信号量控制块指针
           OS_OPT opt,     //选项
           OS_ERR *p_err)  //返回错误类型

选项可选择释放给单个任务或者所有任务:

#define  OS_OPT_POST_1      (OS_OPT)(0x0000u)  /* Post message to highest priority task waiting      */
#define  OS_OPT_POST_ALL       (OS_OPT)(0x0200u)  /* Broadcast message to ALL tasks waiting        

下面是具体释放过程:

OSSemPost(&my_sem,OS_OPT_POST_1,&err);

3、获取信号量函数:

OSSemPend (OS_SEM *p_sem, //信号量指针
           OS_TICK timeout,  //等待超时时间
           OS_OPT opt,  //选项
           CPU_TS *p_ts, //等到信号量时的时间戳
           OS_ERR *p_err) //返回错误类型

选项有两个,分别是等待不到对象进行阻塞和不进行阻塞

#define  OS_OPT_PEND_BLOCKING       (OS_OPT)(0x0000u)//阻塞
#define  OS_OPT_PEND_NON_BLOCKING   (OS_OPT)(0x8000u)//不阻塞

下面是具体获取过程

OSSemPend(&my_sem,4,OS_OPT_PEND_BLOCKING,NULL,&err);

三、进行实验

1、实验目的:key控制led的亮灭
2、实验过程:

必要的初始化:

void  BSP_Init (void)
{
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置优先级分组
	delay_init(168);//配置时钟
	
	
	GPIO_Config(GPIOF,GPIO_Pin_9,GPIO_Mode_OUT,GPIO_OType_PP,GPIO_PuPd_NOPULL);
	KEY0_Init();
}

main.c:

int main(void)
{	
  OS_ERR err;
	CPU_SR_ALLOC();

	
	BSP_Init();
	OSInit(&err);		//初始化UCOSIII  
	OS_CRITICAL_ENTER();		//进入临界区
	
	
	create_star_task(10); 
	
	OS_CRITICAL_EXIT();	//退出临界区	 
	OSStart(&err);  
	while(1);
  
}

起始任务:

static void star_task(void *p_arg)
{
	
	OS_ERR err;
	p_arg = p_arg;//防止编译器报警
	
	CPU_SR_ALLOC();	
	CPU_Init();//cpu初始化
	
                         
	
	OS_CRITICAL_ENTER();	//进入临界区
    /*  创建任务区  */
	creat_led_task(5);
  creat_key_task(4);  
	OS_CRITICAL_EXIT();		//退出临界区
	OS_TaskSuspend((OS_TCB*)&StarTaskTCB,&err);		//挂起开始任务	
    
}

key_task:

static OS_ERR err;  //错误类型
OS_SEM key_sem;  //信号量控制块


void key_task(void *p_arg)
{
	OSSemCreate((OS_SEM*)&key_sem,(CPU_CHAR*)"key_sem",(OS_SEM_CTR)0,(OS_ERR*)&err);//创建信号量
	for(;;)
	{
		if(Key_Scan()==RESET)
		{
			
			OSSemPost(&key_sem,OS_OPT_POST_1,&err);//释放信号量
			
		}
		delay_ms(4);
	}
}

led_task:

static void led_task(void *p_arg)
{
	for(;;)
	{
		OSSemPend(&key_sem,4,OS_OPT_PEND_BLOCKING,NULL,&err);
		if(err==OS_ERR_NONE)
		{
			GPIO_ToggleBits(GPIOF,GPIO_Pin_9);
		}

	}
	
	
}

3、遇到问题:

出现一堆报错:

解决方法:将创建信号量函数放在任务函数里解决

出现另一个报错:

 解决方法:将err定义static解决

key_task进不去:

将led_task的优先级和key_task的优先级设置成一样的了,一直在led_task中出不去,将key_task的优先级改高就解决了

<think>好的,我需要帮用户了解如何在Zynq-7000上下载并运行uC/OS-III。首先,用户可能对Zynq-7000和uC/OS-III不太熟悉,所以得先简要介绍一下这两个概念。 Zynq-7000是赛灵思的SoC,结合了ARM处理器和FPGA,常用于嵌入式系统。uC/OS-III是一个实时操作系统,适合资源受限的环境。用户的需求可能是在这个平台上进行嵌入式开发,所以需要指导他们如何获取和配置uC/OS-III。 接下来,用户提到“下载”,可能指获取uC/OS-III的源码。需要确认Micrium(现在被Silicon Labs收购)的官方来源。通常,官网或厂商提供的资源是首选。但需要注意许可问题,uC/OS-III是商业软件,可能需要购买许可证。如果用户有评估版的需求,可能需要注册或联系销售。 然后是开发环境的搭建。Xilinx的工具链,如Vivado和SDK,是必须的。用户需要创建硬件平台,配置Zynq的处理器系统,生成硬件描述文件。这部分可能需要指导用户如何导出到SDK,创建应用工程。 在SDK中,用户需要添加uC/OS-III的库文件。这里要说明如何将源码导入工程,并确保路径正确。可能还需要配置编译选项,比如处理器架构、优化等级等。 接着是代码的修改和适配。BSP部分可能需要调整,特别是启动代码和硬件初始化。用户可能需要根据Zynq的硬件配置来修改BSP中的外设驱动,比如定时器、中断控制器等。这部分容易出问题,需要详细说明。 编译和调试阶段,用户可能会遇到链接错误或运行时问题。需要提醒他们检查库文件的包含情况,以及内存映射是否正确。生成的可执行文件需要下载到目标板,可能通过JTAG或SD卡。需要根据具体的开发板说明步骤。 最后,验证系统是否正常运行,比如创建任务、信号量等,观察日志输出。如果出现问题,建议检查初始化代码和任务堆栈设置。 需要提醒用户注意许可问题,以及官方文档的重要性。如果有评估版,可以建议他们先尝试,再考虑购买。此外,社区和论坛的资源也可能有帮助。 可能用户没有提到的细节包括交叉编译器的配置、调试工具的使用,以及可能的硬件差异。需要确保步骤清晰,分点说明,避免使用过于专业的术语,但又要准确。同时,检查是否有过时的工具版本问题,比如Vitis取代了SDK,可能需要更新说明。 总结下来,回答的结构应该是先介绍概念,然后分步骤说明下载、配置、编译、下载到设备的过程,注意事项,以及验证方法。确保用户能一步步跟随,并了解可能遇到的问题和解决办法。</think>### 在Zynq-7000上部署μC/OS-III的步骤指南 #### 1. **准备工作** - **硬件需求** - Xilinx Zynq-7000系列开发板(如Zybo、ZedBoard等) - JTAG调试器(如Digilent USB-JTAG) - 安装好Vivado和Vitis(Xilinx新一代开发工具,替代旧版SDK) - **软件资源** - μC/OS-III源码需从Silicon Labs官网获取(需注册并确认许可证) - 下载地址:[Micrium官网](https://www.silabs.com/developers/micrium) --- #### 2. **创建硬件平台(Vivado步骤)** - 新建Vivado工程,选择Zynq-7000芯片型号(如XC7Z020) - 通过**Block Design**配置Zynq Processing System: - 启用ARM Cortex-A9双核 - 配置DDR内存控制器(与开发板型号匹配) - 启用UART、GPIO等必要外设 - 生成比特流并导出硬件描述文件(`.xsa`) --- #### 3. **在Vitis中配置μC/OS-III** - 启动Vitis,基于`.xsa`文件创建平台工程 - 新建应用工程(选择**Standalone**作为操作系统) - 添加μC/OS-III库文件: - 将下载的`Micrium/uCOS-III`源码复制到工程`src`目录 - 在工程属性中添加头文件路径(如`/uCOS-III/Ports/ARM/Cortex-A/Generic/GNU`) --- #### 4. **代码适配与修改** - **BSP适配** 修改`bsp.c`中的硬件初始化代码,确保与Zynq外设匹配: ```c void BSP_Init(void) { /* 初始化UART用于调试输出 */ XUartPs_Config *UartCfg = XUartPs_LookupConfig(XPAR_XUARTPS_0_DEVICE_ID); XUartPs_CfgInitialize(&UartInst, UartCfg, UartCfg->BaseAddress); } ``` - **链接脚本调整** 修改`lscript.ld`,确保内存分配与Zynq的DDR配置一致: ```ld MEMORY { DDR : ORIGIN = 0x00100000, LENGTH = 0x1FF00000 } ``` --- #### 5. **编译与下载** - 在Vitis中编译工程,生成ELF可执行文件 - 通过JTAG连接开发板,使用**Program FPGA**加载比特流 - 运行调试会话,观察串口输出(如TeraTerm或PuTTY) --- #### 6. **验证μC/OS-III运行** - 创建测试任务(如LED闪烁和串口打印): ```c void Task1(void *p_arg) { while (1) { XGpio_DiscreteWrite(&GpioInst, 1, 0x01); // LED亮 OSTimeDlyHMSM(0, 0, 1, 0); // 延时1秒 XGpio_DiscreteWrite(&GpioInst, 1, 0x00); // LED灭 OSTimeDlyHMSM(0, 0, 1, 0); } } ``` - 若串口输出`μC/OS-III Started`,表明系统运行正常 --- #### **注意事项** 1. **许可证问题** μC/OS-III为商业RTOS,需购买许可证或申请评估版(Silicon Labs提供有限期试用)。 2. **多核支持** Zynq-7000为双核Cortex-A9,若需双核运行μC/OS-III,需修改调度器适配SMP(非官方支持)。 3. **中断配置** 确保`os_cpu_a.S`中的中断向量表与Zynq的GIC(Generic Interrupt Controller)对齐。 --- #### **扩展资源** - Xilinx应用笔记:[APU与FPGA协同设计](https://www.xilinx.com/support/documentation/application_notes/xapp1234.pdf) - μC/OS-III官方手册:*Mastering μC/OS-III*(需从Silicon Labs下载)
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值