🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] # 背景说明 在做开发的时候,涉及到了双核cpu两个之间的通信,根据自己项目的实际需求,可以简单的认为`cpu0`是`cpu1`的上位机,也就是所`cpu0`只需要向`cpu1`发送少量的信息,而且操作频率不高,`cpu1`可能会向`cpu0`发送很多数据,根据`zynq7021`的内部架构,决定使用`OCM`实现,如果一个`cpu`写数据另一个`cpu`读数据,同时操作可能会出错,因此我将OCM划出256个字节作为内存共享区,并设计了`FIFO`的缓冲。**在最初,使用结构体的方法来设计队列,会因为内存对齐,导致很多空间会被浪费掉**,于是在实现命令发送的FIFO缓冲时,采用了循环队列来实现,但这里由于要共享,因此实现时使用指针来操作,并且规避可使用结构体,通过自己划分字节来组成想要的类型数据的存储字节,项目中设计的命令占用了5个字节,组成结构如下: |1字节 | 2-5 字节| |--------|----------| |命令|int型数据| # 循环队列 使用循环队列可以节省本来就很拮据的OCM空间的使用,使得使用空间的效率更高。</br> ![](https://img.kancloud.cn/96/1d/961d05812a244e3e5bc46bd0cf38f420_733x422.png) **满空判断** * 队满:Q.front == (Q.rear + 1) % MAXSIZE * 队空:Q.front == Q.rear c实现: ```c #include <stdio.h> #include <malloc.h> #define MAXSIZE 100 //最大队列长度 #define OK 1 #define ERROR 0 typedef int ElemType; typedef int Status; typedef struct { ElemType *base; //队列空间 int front; //队头指针 int rear; //队尾指针,若队尾不为空,则指向队尾元素的下一个位置 }SqQueue; //初始化循环队列 Status initQueue(SqQueue &Q) { Q.base = (ElemType *) malloc(MAXSIZE * sizeof(ElemType)); //申请空间 Q.front = Q.rear = 0; //队空 return OK; } //入队 Status enQueue(SqQueue &Q, ElemType e) { if ((Q.rear + 1) % MAXSIZE == Q.front) return ERROR; //队满,无法添加 Q.base[Q.rear] = e; //插入元素 Q.rear = (Q.rear + 1) % MAXSIZE; //队尾指针+1 return OK; } //出队 Status deQueue(SqQueue &Q, ElemType &e) { if (Q.front == Q.rear) return ERROR; //队空,无法删除 e = Q.base[Q.front]; Q.front = (Q.front + 1) % MAXSIZE; //队头指针+1 return OK; } //返回队列长度 Status length(SqQueue &Q) { return (Q.rear - Q.front + MAXSIZE) % MAXSIZE; } ``` # 自定义数据,强制转换为所需数据格式 在zynq平台的sdk上,提供了io操作函数,可以直接操作内存中数据: * Xil_Out8 * Xil_Out16 * Xil_Out32 * Xil_In8 * Xil_In16 * Xil_In32 使用上述函数访问内存,对其结果直接强制转换就可以了!