我正在开发一种使用网守任务来访问共享资源的设计.我现在的基本设计是网守任务正在接收的单个队列以及将请求放入其中的多个任务.
这是一个内存有限的系统,我正在使用FreeRTOS(Cortex M3端口).
问题如下:异步处理这些请求非常简单.请求任务将其请求排队并进行业务,轮询,处理或等待其他事件.为了同步处理这些请求,我需要一种机制让请求任务阻塞,这样一旦处理了请求,网守就可以唤醒调用该请求的任务.
我能想到的最简单的设计是在每个请求中包含一个信号量,但考虑到内存限制和FreeRTOS中信号量的相当大的大小,这是不切实际的.
我想到的是使用任务挂起和任务恢复功能来手动阻止任务,将句柄传递给网守,当请求完成时,它可以恢复任务.暂停/恢复有一些问题,我真的想避免它们.单个恢复调用将唤醒任务,无论其被多少次被其他调用暂停,这可能会产生不良行为.
一些简单的伪C来演示suspend/resume方法.
void gatekeeper_blocking_request(void)
{
put_request_in_queue(request);
task_suspend(this_task);
}
void gatekeeper_request_complete_callback(request)
{
task_resume(request->task);
}
Run Code Online (Sandbox Code Playgroud)
我计划在此期间使用的解决方法是使用异步调用并在每个请求任务中完全实现阻塞.当操作完成时,网守将执行提供的回调,然后可以发布到任务的主队列或特定信号量,或任何需要的信号.对请求进行阻塞调用本质上是一个便利功能,因此每个请求任务都不需要实现此功能.
Pseudo-C用于演示特定于任务的阻塞,但这需要在每个任务中实现.
void requesting_task(void)
{
while(1)
{
gatekeeper_async_request(callback);
pend_on_sempahore(sem);
}
}
void callback(request)
{
post_to_semaphore(sem);
}
Run Code Online (Sandbox Code Playgroud)
也许最好的解决方案就是不在网守和API中实现阻塞,并强制每个任务来处理它.但是,这将增加每个任务流程的复杂性,我希望我能避免它.在大多数情况下,所有调用都将阻止,直到操作完成.
是否有一些我缺少的构造,或者甚至只是一个更好的术语来解决这类问题?在我的搜索中,我没有遇到过这样的事情.
附加说明 - 网守任务的两个原因:
需要大堆栈空间.网守可以拥有一个只需要所有内存的堆栈,而不是将这个要求添加到每个任务中.
资源并不总是可以在CPU中访问.它不仅可以同步CPU中的任务,还可以同步CPU外部的任务.
在 Tiva(Texas Instruments Cortex M4F ARM)TM4C129XNCZAD 上,I2C 接口有问题。我通过端口 K 启用了 I2C 模块 4 上的主设备和通过端口 B 的 I2C 模块 6 上的从设备。我已将两个 I2C 模块互连。使用德州仪器驱动程序库,我尝试使用 I2C_MASTER_CMD_SINGLE_SEND 命令发送 1 个字节。我花了很多时间让它工作,但 SCK 线保持低逻辑电平。我完全遵循了 TivaWare™ Peripheral Driver Library USER'S GUIDE,但通信不起作用。有没有人有一些经验?
有我的代码:
#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_i2c.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/gpio.h"
#include "driverlib/i2c.h"
#include "driverlib/pin_map.h"
#include "driverlib/sysctl.h"
#include "inc/tm4c129xnczad.h"
#define SLAVE_ADDRESS 0x3C
void delay (void)
{
volatile uint32_t ui32Loop;
for(ui32Loop = 0; ui32Loop < 200000; ui32Loop++);
}
volatile uint32_t result;
int main (void)
{ …Run Code Online (Sandbox Code Playgroud) 所以我试着通过查看这里的程序集来编写一些C代码:
pushl %ebp
movl %esp, %ebp
movl 12(%ebp), %eax
addl 8(%ebp), %eax
movzbl (%eax), %eax
movsbl %al,%eax
popl %ebp
ret
Run Code Online (Sandbox Code Playgroud)
我看到我有两个变量,它们被加在一起,然后当看到函数开始调用movzbl和movesbl时我迷路了.这里发生了什么?
在一个为Microsoft x64汇编器编写的简单程序中,我想在SSE寄存器(例如xmm0)和通用寄存器(例如rcx)之间移动64位值,如<MASM中的Intel语法>:
mov xmm0, rcx
...
mov rcx, xmm0
Run Code Online (Sandbox Code Playgroud)
这两行分别从生成以下错误消息ml64.exe:
但是,显然有可能在x64中完成此简单任务。例如,以下是一个可运行的x64程序,我可以使用GCC <AT&T语法使用GCC 4.8.2>汇编并运行该程序:
.text
.globl main
main:
movl $1, %ecx
movq %rcx, %xmm0
movq %xmm0, %rax
ret
Run Code Online (Sandbox Code Playgroud)
不出所料,该程序的返回值为1,其objdump输出为main():
1004010d0: b9 01 00 00 00 mov $0x1,%ecx
1004010d5: 66 48 0f 6e c1 movq %rcx,%xmm0
1004010da: 66 48 0f 7e c0 movq %xmm0,%rax
1004010df: c3 retq
Run Code Online (Sandbox Code Playgroud)
所以我的问题是,鉴于ml64.exe产生上述错误,我该如何在MASM中完成此操作?