小住住
小住住 - 认证专家

注册于 5 years ago

回答
7
文章
1
关注者
0

看来这个软件包用的人还是挺多的。有问题我们一起优化一下。

自己简单实现了一个,供大家参考:
queue.c

#include "queue.h"
#include <malloc.h>
#include <memory.h>

#define MAXQSIZE 100
#define MSG_MAX_SIZE 2048

typedef struct queueElement
{
    unsigned char msg[MSG_MAX_SIZE];
    int msg_size;
}queueElementT;

struct queueCDT{
    queueElementT *data;
    int front;
    int rear;

};

queueADT newQueue(void)
{
    queueADT queue;
    queue = (queueADT)malloc(sizeof (struct queueCDT));
    queue->data = (queueElementT *)malloc(MAXQSIZE * sizeof(queueElementT));
    queue->front = 0;
    queue->rear = 0;
    return queue;
}
void freeQueue(queueADT queue)
{
    free(queue->data);
    free(queue);
}

bool inQueue(queueADT queue, unsigned char *msg, int msg_len)
{
    if (queueIsFull(queue))
    {
        return ERROR_QUEUE_FULL;
    }
    memcpy(queue->data[queue->rear].msg,msg, msg_len);
    queue->data[queue->rear].msg_size = msg_len;
    queue->rear = (queue->rear + 1) % MAXQSIZE;
    return true;
}

bool outQueue(queueADT queue, unsigned char *msg, int *msg_len)
{
    if (queueIsEmpty(queue))
    {
        return ERROR_QUEUE_EMPTY;
    }
    memcpy(msg, queue->data[queue->front].msg, queue->data[queue->front].msg_size);
    *msg_len = queue->data[queue->front].msg_size;
     queue->front = (queue->front + 1) % MAXQSIZE;

    return true;
}

bool queueIsEmpty(queueADT queue)
{
    return (queue->rear == queue->front);
}
//当front 在rear 的下一个位置 就视为队列已满 
bool queueIsFull(queueADT queue)
{
    return ((queue->rear + 1) % MAXQSIZE == queue->front);
}

size_t getQueueLength(queueADT queue)
{
    return (queue->rear -queue->front + MAXQSIZE) % MAXQSIZE;
}

queue.h

#pragma once
#include <stdbool.h>
#include <stddef.h>

#define ERROR_QUEUE_FULL   400 + 1
#define ERROR_QUEUE_EMPTY  400 + 2
// struct queueElement
// {
//     unsigned char data_msg[MSG_MAX_SIZE];
//     int data_msg_size;
// };
// typedef queueElement queueElementT;
//typedef int queueElementT;
typedef struct queueCDT *queueADT;

queueADT newQueue(void);
void freeQueue(queueADT queue);
bool inQueue(queueADT queue, unsigned char *msg , int msg_len);
bool outQueue(queueADT queue, unsigned char *msg, int *msg_len);
//bool queuelIsEmpty(queueADT queue);
bool queueIsEmpty(queueADT queue);

bool queueIsFull(queueADT queue);
size_t getQueueLength(queueADT queue);

queuetest.c

#include <stdio.h>



#include "queue.h"
//一个线程 塞数据  一个线程  取数据 
int main (int argc, int *argv[])
{
    queueADT queue;
    unsigned char data1[512] = {0};
    int data1_len = 512;
    unsigned char data2[128] = {0};
    int data2_len = 128;
    unsigned char data3[256] = {0};
    int data3_len = 256;
    unsigned char temp_data[1024] = {0};
    int temp_len = 0;
    int temp,i;
    int queue_len = 0;
    queue = newQueue();
    for (i = 0; i < 100; i++)
    {
        data1[i] = i;
    }
    for (i = 0; i< 100; i++)
    {
        data2[i] = i + 100;
    }
    for (i = 0; i< 100; i++)
    {
        data3[i] =  i + 100 + 100;
    }
    inQueue(queue, data1, 100);
    inQueue(queue, data2, 90);
    inQueue(queue, data3, 50);
    queue_len = getQueueLength(queue);
    printf("the queue len is %d\n", queue_len);
    outQueue(queue, temp_data, &temp_len);
    printf("the output queue len is %d\n", temp_len);
    for (i = 0; i < temp_len; i++)
    {
        printf("%d ", temp_data[i]);
    }
    printf("\n");

    outQueue(queue, temp_data, &temp_len);
    printf("the output2 queue len is %d\n", temp_len);
    for (i = 0; i < temp_len; i++)
    {
        printf("%d ", temp_data[i]);
    }
    printf("\n");

    outQueue(queue, temp_data, &temp_len);
    printf("the output3 queue len is %d\n", temp_len);
    for (i = 0; i < temp_len; i++)
    {
        printf("%d ", temp_data[i]);
    }
    printf("\n");
    
    queue_len = getQueueLength(queue);
    printf("the queue len is %d\n", queue_len);   



    freeQueue(queue);
    return 0;

}

image.png

11.png
支持NFS 网络文件系统

`int mnt_init(void)
{

rt_thread_delay(RT_TICK_PER_SECOND);

//  if (dfs_mount("sd0", "/", "elm", 0, 0) == 0)
// {
//     rt_kprintf("file system initialization done!\n");
// }
if(dfs_mount(RT_NFS_HOST_EXPORT,"/","nfs", 0, 0) == 0)
{
    rt_kprintf("file system initialization done!\n");
}

return 0;

}
INIT_ENV_EXPORT(mnt_init);`
例子确实比较少,我在qemu a9 上 这样处理,发现不行。
12.png

在qemu 下编译是正常的。具体可以说说你的环境。
12.png

shell.c 中有 一处 finsh_getchar(),

 while (1)
    {
        ch = finsh_getchar();
        if (ch < 0)
        {
            continue;
        }
        

主要就是实现这里,可以点进去看看具体实现了没有。

根据上面思路简单写了个例子:

#include <rtthread.h>
#include <dfs_posix.h> /* 当需要使用文件操作时,需要包含这个头文件 */

// 函数说明:stat()用来将参数file_name 所指的文件状态, 复制到参数buf 所指的结构中。

// 下面是struct stat 内各参数的说明:
// struct stat
// {
//     dev_t st_dev; //device 文件的设备编号
//     ino_t st_ino; //inode 文件的i-node
//     mode_t st_mode; //protection 文件的类型和存取的权限
//     nlink_t st_nlink; //number of hard links 连到该文件的硬连接数目, 刚建立的文件值为1.
//     uid_t st_uid; //user ID of owner 文件所有者的用户识别码
//     gid_t st_gid; //group ID of owner 文件所有者的组识别码
//     dev_t st_rdev; //device type 若此文件为装置设备文件, 则为其设备编号
//     off_t st_size; //total size, in bytes 文件大小, 以字节计算
//     unsigned long st_blksize; //blocksize for filesystem I/O 文件系统的I/O 缓冲区大小.
//     unsigned long st_blocks; //number of blocks allocated 占用文件区块的个数, 每一区块大小为512 个字节.
//     time_t st_atime; //time of lastaccess 文件最近一次被存取或被执行的时间, 一般只有在用mknod、utime、read、write 与tructate 时改变.
//     time_t st_mtime; //time of last modification 文件最后一次被修改的时间, 一般只有在用mknod、utime 和write 时才会改变
//     time_t st_ctime; //time of last change i-node 最近一次被更改的时间, 此参数会在文件所有者、组、权限被更改时更新
// };
typedef struct latest_modify_info
{
    time_t modify_time;
    char   *file_name;
}MODIFY_INFO;
static void readdir_sample(void)
{
    DIR *dirp;
    struct dirent *d;
    rt_uint32_t eventlog_count = 0;
    struct stat buf;
    struct stat buf_latest;
    //time_t modify_time;
    MODIFY_INFO  latest_info;
    latest_info.modify_time = 0;
    int ret;
    /* 打开/dir_test 目录*/
    dirp = opendir("/");
    if (dirp == RT_NULL)
    {
        rt_kprintf("open directory error!\n");
    }
    else
    {
        /* 读取目录*/
        while ((d = readdir(dirp)) != RT_NULL)
        {
            if (rt_strncmp(d->d_name,"eventlog",7) == 0)
            {
                eventlog_count ++;
                rt_kprintf("found %s\n", d->d_name);
                ret = stat(d->d_name,&buf);
                if (ret == 0)
                {
                    if(latest_info.modify_time < buf.st_mtime)
                    {
                        latest_info.modify_time = buf.st_mtime;
                        //strcpy(latest_info.file_name,d->d_name);
                        latest_info.file_name = d->d_name;
                    }
                }
                else
                    rt_kprintf("text.txt file not fonud\n");
            }
      
        }
        rt_kprintf("the eventlog_count is %d\n", eventlog_count);
        rt_kprintf("the lastes eventlog is %s\n", latest_info.file_name);
        /* 关闭目录 */
        closedir(dirp);
    }
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(readdir_sample, readdir sample);

微信截图_20200704195258.png

注意事项:一个事件的话,也需要 RT_EVENT_FLAG_OR ,
if (rt_event_recv(&event, EVENT_FLAG_SSI_RECV_OVER, RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR,
RT_WAITING_FOREVER,&e) == RT_EOK)

aozima 发表于 2020-5-25 22:09
既然是从机,那收不收不由你,则是由主机决定。


嗯。主要想解决得就是增加SPI 得吞吐量,需要高速传输。

线程先向串口的 FIFO 中写入数据,当 FIFO 满时,线程主动挂起。串口控制器持续地从 FIFO 中取出数据并以配置的波特率(例如 115200bps)发送出去。当 FIFO 中所有数据都发送完成时,将向处理器触发一个中断;当中断服务程序得到执行时,可以唤醒这个线程。这里举例的是 FIFO 类型的设备,在现实中也有 DMA 类型的设备,原理类似。
对于低速设备来说,运用这种模式非常好,因为在串口外设把 FIFO 中的数据发送出去前,处理器可以运行其他的线程,这样就提高了系统的整体运行效率(甚至对于分时系统来说,这样的设计也是非常必要)。但是对于一些高速设备,例如传输速度达到 10Mbps 的时候,假设一次发送的数据量是 32 字节,我们可以计算出发送这样一段数据量需要的时间是:(32 X 8) X 1/10Mbps = 25us。当数据需要持续传输时,系统将在 25us 后触发一个中断以唤醒上层线程继续下次传递。假设系统的线程切换时间是 8us(通常实时操作系统的线程上下文切换时间只有几个 us),那么当整个系统运行时,对于数据带宽利用率将只有 25/(25+8) =75.8%。但是采用轮询模式,数据带宽的利用率则可能达到 100%。这个也是大家普遍认为实时系统中数据吞吐量不足的缘故,系统开销消耗在了线程切换上(有些实时系统甚至会如本章前面说的,采用底半处理,分级的中断处理方式,相当于又拉长中断到发送线程的时间开销,效率会更进一步下降)。
通过上述的计算过程,我们可以看出其中的一些关键因素:发送数据量越小,发送速度越快,对于数据吞吐量的影响也将越大。归根结底,取决于系统中产生中断的频度如何。当一个实时系统想要提升数据吞吐量时,可以考虑的几种方式:
1)增加每次数据量发送的长度,每次尽量让外设尽量多地发送数据;
2)必要情况下更改中断模式为轮询模式。同时为了解决轮询方式一直抢占处理机,其他低优先级线程得不到运行的情况,可以把轮询线程的优先级适当降低。

JQRR_7669 发表于 2020-5-27 11:19
不行,空闲线程会得不到执行,对一些系统功能会有影响


是的。主要问题 是 比他优先级低的线程 就无法得到运行。

我夏了夏天 发表于 2020-5-25 11:29
把 env 目录下的 packages/packages 目录删掉,重新 pkgs --upgrade 就可以了


我直接把所有的删了,重新下载新版本。:lol

发布
问题