【基于vitis的freertos+lwip学习】(一)线程创建

为了学习更多知识,我创建了一个项目,在项目过程中分享一些自己的所学,所以会出现本文章无关的内容

vivado工程

vivado版本:2020.1
开发板:pynq z2
本实验用到PL端的led和按键,所以添加axi gpio ip;最终原理图如下:

不要在意iic等其他端口。

AXI GPIO简介

首先axi gpio是基于axi lite的, 在使用过程中类似于我们网上看到的很多自定义axi lite ip核差不多,就是对某个地址读写;
在这里插入图片描述
我们可以看到axi gpio的配置界面;
all inputs ,all outputs ,选择方向,这里建议不用在vivado中配置,可以在vitis中设置方向,更加灵活;
GPIO Width:设置gpio位宽;

还可以设置两个gpio通道,在这里注意的是在vitis中有gpio的id,虽然是两个通道,但是是同一个id,因为是同一个axi外设;

vitis工程

生成xsa文件后create new plantform project ,创建方法网上很多,这里就不再赘述了;
需要我们注意的是创建完成后打开plantform.spr
在这里插入图片描述
我们需要在board support package中modify BSP settings;
在这里插入图片描述
在lwip中第一个api_mode我们要选择socket api ,因为我们是基于lwip的,如果是纯freertos选择raw api就行;
然后创建app,选择freertos + lwip udp server;

创建gpio驱动

我创建了一个axi_gpio.c axi_gpio.h文件;
主要是三个函数gpio初始化,led写,按键读;

void axi_led_btns_init(void)
{
	xil_printf("LED and Buttens initializing...\r\n");
	int xStatus = XGpio_Initialize(&axiGpio_led_btns,XPAR_AXI_GPIO_0_DEVICE_ID);
	if(XST_SUCCESS != xStatus) {
		xil_printf("Failed to initialize LED or Buttens\r\n");
	}
	//set direction
	XGpio_SetDataDirection(&axiGpio_led_btns, LED_CHINAL, 0x0); //
	XGpio_SetDataDirection(&axiGpio_led_btns, BTNS_CHINAL, 0x1); //
}
void LED_write(u32 led_data)
{
	XGpio_DiscreteWrite(&axiGpio_led_btns, LED_CHINAL, led_data);
}
u32 Buttens_read(void)
{
	return XGpio_DiscreteRead(&axiGpio_led_btns, BTNS_CHINAL);
}

axiGPio_led_btns是我定义的结构体,在.h中
可以看到XGpio_Initialize函数中的ID只有一个;

XGpio axiGpio_led_btns;

LED_CHINAL、BTNS_CHINAL表示两个通道,也在.h中定义

#define LED_CHINAL 2U
#define BTNS_CHINAL 1U

其他函数也非常好理解,这里接不过多讲述;

任务创建

本实验两个任务,一个任务用于初始化gpio和创建另一个任务;另一个任务实现按键按下led亮;

INIT_TASK_HANDLE = sys_thread_new("init task", (void(*)(void*))init_task, 0,
				INIT_TASK_SIZE,INIT_TASK_PRIO);
	if (INIT_TASK_HANDLE)
			xil_printf("Init Task create succeed!\r\n");
		else
			xil_printf("Fail to create Init Task!\r\n");

INIT_TASK_HANDLE:线程句柄
创建方式和freertos基本相同,但是用到了sys_thread_new函数,这是socket编程和纯freertos不一样的地方;
我们看一下这个函数
在这里插入图片描述可以看到这个函数也是通过xTaskCreate实现区别如下:

一、它是一个包装器,所以如果你将你的lwip代码移植到其他操作系统,你不必改变你的代码;
二、sys_thread_new会把新创建的task的pid放入到一个timeoutlist的链表中。用socket系列函数的select不用这个函数创建会进入abort中断,具体原因请看select函数实现,其中sys_arch_timeouts的调用就是获取当前task的timeout,如果没有用sys_thread_new创建的话,这里就没有我用来调用select的当前task,所以就有了以后的abort中断了。
我也没有深入研究,具体可以参考下面链接
链接: link
链接: link
还有句柄不用TaskHandle_t 用sys_thread_t,包含于#include “netif/xadapter.h”

void init_task(void *pvParameters){
	taskENTER_CRITICAL();

	axi_gpio_init();
	LED_TASK_HANDLE = sys_thread_new("led task", (void(*)(void*))led_task, 0,
			LED_TASK_SIZE,LED_TASK_PRIO);
	if (LED_TASK_HANDLE)
		xil_printf("LED Task create succeed!\r\n");
	else
		xil_printf("Fail to create LED Task!\r\n");
	vTaskDelete(NULL);
	taskEXIT_CRITICAL();
}

我们在初始化任务中初始化axi gpio和创建led btns的任务

void led_task(void *p_arg){
	while(1){
		LED_write(Buttens_read());
		vTaskDelay(x50ms);
	}
}

这里不能直接用vTaskDelay(500);表示500ms延迟,时间不准;要用const TickType_t x500ms = pdMS_TO_TICKS( 500UL );先定义延迟时间,再使用vTaskDelay(x500ms);可以查看f纯reertos的helloword例程;
最后看一下init_task函数和led btns任务函数

总结

socket编程还是有些区别的,在使用过程中要注意;

参考

链接: link
链接: link

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一匹狼呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值