突然发觉threadx的队列使用有很大的局限性
看到threadx所有的例程都是TX_1_ULONG发送4个字节为一个消息包。如果想把一个总共20字节的结构体做为一个消息包一次性发送,用TX_4_ULONG不够,一次发不完;用TX_8_ULONG一发就死了,死掉的原因是queue内部复制结构体数据时超范围了。。。。
个人觉得threadX的队列用起来真不如FreeRTOS的方便。
20个字节,算下来也就5个字,你用TX_8_ULONG不就多了3个字? ;P,其他操作系统一次最多只能发送 4 字节。大容量消息,可以发送指针就可以了。 数据量大发地址,效率更高 结构体数据内部有读和写之分,多个任务可以修改结构体的数据和读写权限,,,每个消息都是一个独立的数据包,tx_queue_receive端收到消息就处理,用指针感觉不太方便。 如果习惯了FreeRTOS那种玩法,使用ThreadX, uCOS-III,RTX等RTOS的消息队列确实会不顺手,以ThreadX为例,他的消息队列是数据的复制粘贴,FreeRTOS也是,区别的地方是ThreadX限制了最大复制粘贴数,因为数据量多了之后,复制粘贴比较耽误时间。
针对楼主的情况,其实用其它RTOS实现也非常简单。以ThreadX为例,他有个内存池的动态内存管理,你要做的是消息队列发送前申请你需要的动态内存并填充数据,然后传递地址即可。接收端获取数据地址后,提取数据,释放动态内存。其实FreeRTOS消息队列就是这种玩法实现的。 freertos随便发,的确还是很好用的。 那是编程人员自己的应用场景比较轻量化,懒省事这么做,没啥毛病。 一旦你开始追求效率,‘’零拷贝‘’的需求,你就有了。然后,你必然导向硬汉大哥给你的建议。 硬汉的建议给了我另一种解决问题的思路,值得一试,谢谢!各个系统的区别还是挺大的,要想玩转它,还得像硬汉那样整明白系统的原理才行。 表面上的使用方便,是以背后的复杂性为代价的。 eric2013 发表于 2023-6-5 00:09
如果习惯了FreeRTOS那种玩法,使用ThreadX, uCOS-III,RTX等RTOS的消息队列确实会不顺手,以ThreadX为例, ...
发送端申请内存,接收端释放内存;
有demo吗 最近发现threadx最新版本的队列发送源代码跟以前旧版的不一样了,貌似改进了。 xiaomeng 发表于 2023-12-3 18:58
发送端申请内存,接收端释放内存;
有demo吗
调用那个动态申请API,申请个空间给消息队列使用即可 天马行空 发表于 2023-12-4 09:28
最近发现threadx最新版本的队列发送源代码跟以前旧版的不一样了,貌似改进了。
最新的6.3.0 ? 改天我试试。 eric2013 发表于 2023-6-5 00:09
如果习惯了FreeRTOS那种玩法,使用ThreadX, uCOS-III,RTX等RTOS的消息队列确实会不顺手,以ThreadX为例, ...
正儿八经用法{:8:} FreeRTOS里的xQueueOverwrite()和xQueuePeek()这种覆写功能也很好,ThreadX里没有,我用全局变量加互斥信号实现了,还有其他好的方法吗? nnqtdf 发表于 2024-2-21 15:30
FreeRTOS里的xQueueOverwrite()和xQueuePeek()这种覆写功能也很好,ThreadX里没有,我用全局变量加互斥信号 ...
threadx/utility/rtos_compatibility_layers/FreeRTOS/tx_freertos.c at master · eclipse-threadx/threadx (github.com)
BaseType_t xQueueOverwrite(QueueHandle_t xQueue,
const void * pvItemToQueue)
{
TX_INTERRUPT_SAVE_AREA;
UINT ret;
UINT read_post;
uint8_t *p_write_temp;
configASSERT(xQueue != NULL);
configASSERT(pvItemToQueue != NULL);
read_post = 0u;
TX_DISABLE;
if(xQueue->read_sem.tx_semaphore_count != 0u) {
// Go back one message.
p_write_temp = xQueue->p_write;
if(p_write_temp == xQueue->p_mem) {
p_write_temp = (xQueue->p_mem + (xQueue->msg_size * (xQueue->queue_length - 1u)));
} else {
p_write_temp -= xQueue->msg_size;
}
memcpy(p_write_temp, pvItemToQueue, xQueue->msg_size);
} else {
memcpy(xQueue->p_write, pvItemToQueue, xQueue->msg_size);
if(xQueue->p_write >= (xQueue->p_mem + (xQueue->msg_size * (xQueue->queue_length - 1u)))) {
xQueue->p_write = xQueue->p_mem;
} else {
xQueue->p_write += xQueue->msg_size;
}
read_post = 1u;
}
TX_RESTORE;
if(read_post == 1u) {
// Signal that there is an additional message available on the queue.
ret = tx_semaphore_put(&xQueue->read_sem);
if(ret != TX_SUCCESS) {
TX_FREERTOS_ASSERT_FAIL();
return pdFALSE;
}
}
return pdPASS;
}
BaseType_t xQueuePeek(QueueHandle_t xQueue,
void *pvBuffer,
TickType_t xTicksToWait)
{
TX_INTERRUPT_SAVE_AREA;
UINT timeout;
UINT ret;
configASSERT(xQueue != NULL);
configASSERT(pvBuffer != NULL);
if(xTicksToWait ==portMAX_DELAY) {
timeout = TX_WAIT_FOREVER;
} else {
timeout = (UINT)xTicksToWait;
}
// Wait for a message to be available on the queue.
ret = tx_semaphore_get(&xQueue->read_sem, timeout);
if(ret != TX_SUCCESS) {
return pdFAIL;
}
// Retrieve the message.
TX_DISABLE;
_tx_thread_preempt_disable++;
memcpy(pvBuffer, xQueue->p_read, xQueue->msg_size);
// Restore the original space on the queue.
ret = tx_semaphore_put(&xQueue->read_sem);
if(ret != TX_SUCCESS) {
TX_FREERTOS_ASSERT_FAIL();
return pdFALSE;
}
_tx_thread_preempt_disable--;
TX_RESTORE;
return pdPASS;
}
eric2013 发表于 2024-2-22 09:20
threadx/utility/rtos_compatibility_layers/FreeRTOS/tx_freertos.c at master · eclipse-threadx/thre ...
{:8:}{:8:}{:8:}
页:
[1]