您的位置:首页 > 其它

一个sio.c的实现及遇到的多任务执行问题

2018-02-26 23:18 309 查看
https://sourceforge.net/p/cadcdev/lwip/ci/491e00038f26dc5d775f120aa49519a066819ebf/tree/kos/sio.c

/* KallistiOS ##version##

sio.c
Copyright (C)2004 Dan Potter
*/

#include <dc/scif.h>
#include <kos/thread.h>
#include <lwip/lwip.h>
#include "lwip/sio.h"

/*
This implements the serial I/O interface for lwIP to use PPP for serial
connections. This hooks straight to dbgio right now but could easily
be swapped over to use the modem stuff.
*/

static volatile int sio_abort = 0;

sio_fd_t sio_open(u8_t foo) {
int i;

sio_abort = 0;

// Clear out anything in the buffer already
i = 0;
while (scif_read() != -1)
i++;
if (i)
printf("sio: cleared %d initial chars\n", i);

return NULL;
}

void sio_send(u8_t ch, sio_fd_t foo) {
scif_write(ch);
scif_flush();
}

u8_t sio_recv(sio_fd_t foo) {
int ch;

do {
ch = scif_read();
if (ch == -1)
thd_sleep(10);
} while (ch == -1 && !sio_abort);

sio_abort = 0;
return ch;
}

// I *think* this is right, but sio_* seems to be totally
// undocumented like so many things in lwIP.
u32_t sio_read(sio_fd_t foo, u8_t *outbuf, u32_t bufmax) {
int i, ch;

for (i=0; i<bufmax && !sio_abort; i++) {
ch = scif_read();
if (ch == -1) {
if (i == 0) {
thd_sleep(10);
i--;
continue;
} else
break;
}
outbuf[i] = ch;
}

sio_abort = 0;
return i;
}

// Ditto on the comment for sio_read.
u32_t sio_write(sio_fd_t foo, u8_t *buf, u32_t buflen) {
int i;

for (i=0; i<buflen && !sio_abort; i++)
scif_write(buf[i]);
scif_flush();

sio_abort = 0;
return buflen;
}

void sio_read_abort(sio_fd_t foo) {
sio_abort = 1;
printf("sio_read_abort called\n");
while (sio_abort)
thd_sleep(10);
}


上面这个实现似乎没有实现block

下面的实现,一开始while死循环处没有加Delay(1);,结果,其它任务根本起不来,

后来,加了一个Delay(1);之后,其它任务就能起来了。

即使没有Delay(1);,任务调度不是也应该能调度其它任务吗???

/**
* Reads from the serial device.
*
* @param fd serial device handle
* @param data pointer to data buffer for receiving
* @param len maximum length (in bytes) of data to receive
* @return number of bytes actually received - may be 0 if aborted by sio_read_abort
*
* @note This function will block until data can be received. The blocking
* can be cancelled by calling sio_read_abort().
*/
u32_t sio_read(sio_fd_t fd, u8_t *data, u32_t len)
{
if(len >= 1)
{
if(fd.UartNo == 1)
{
while(USART_GetITStatus(USART1, USART_IT_RXNE) == RESET) {Delay(1);}
{
*data =(u8)USART_ReceiveData(USART1);
return 1;
}
}
else if(fd.UartNo == 3)
{
while(USART_GetITStatus(USART3, USART_IT_RXNE) == RESET)
{
*data =(u8)USART_ReceiveData(USART3);
return 1;
}
}
else if(fd.UartNo == 5)
{
while(USART_GetITStatus(UART5, USART_IT_RXNE) == RESET)
{
*data =(u8)USART_ReceiveData(UART5);
return 1;
}
}
else if(fd.UartNo == 6)
{
while(USART_GetITStatus(USART6, USART_IT_RXNE) == RESET)
{
*data =(u8)USART_ReceiveData(USART6);
return 1;
}
}
}
return 0;
}


另外,上面没有实现多字节读取,读取len个,也没有实现abort,可以参考最开始的例子。

目前系统中所有任务的优先级分配如下,空闲任务优先级为0,最大优先级是8:

Main_task 1

ToggleLed4 2

tcpip task 6

udp task 5

eth input 7

slip input 7

slip接收任务如下:

#if SLIP_USE_RX_THREAD
/**
* The SLIP input thread.
*
* Feed the IP layer with incoming packets
*
* @param nf the lwip network interface structure for this slipif
*/
static void
slipif_loop_thread(void *nf)
{
u8_t c;
struct netif *netif = (struct netif *)nf;
struct slipif_priv *priv = (struct slipif_priv *)netif->state;

while (1) {
if (sio_tryread(priv->sd, &c, 1) > 0) {
slipif_rxbyte_input(netif, c);
}
}
}
#endif /* SLIP_USE_RX_THREAD */


slip接收任务是死循环,没有自动结束,而且优先级是最高的7,因此,slip任务会一直运行,其它任务都无法打断(led、udp任务无法执行)。

在read的while中加Delay(1);可以,而且,这里的Delay(1)得是用的操作系统的delay,如下:

/**
* @brief  Inserts a delay time.
* @param  nCount: number of Ticks to delay.
* @retval None
*/
void Delay(uint32_t nCount)
{
vTaskDelay(nCount);
}


vTaskDelay就是FreeRTOS操作系统自带的延时函数。因为,操作系统在执行该任务的delay过程中,会去执行其它任务,因此,其它低优先级任务得以继续执行。

如果delay这里用for 100次的这种方式,仍然是不行的,操作系统仍然不能切换到其它任务。

关于vTaskDelay可以看这篇博文http://blog.csdn.net/zhzht19861011/article/details/51705148

需要对整个系统的不同任务、优先级好好了解清楚。

对于高优先级任务,需要执行完就立刻挂起或阻塞,以让其它低优先级任务得以执行。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐