我从代码中实现了Blackfin BF561 coreB FreeRTOS:
http://www.freertos.org/index.html?http://interactive.freertos.org/forums/79366-analog-devices
我使用gcc转换为裸机作为elf可执行文件.
我很接近,但我有一个运行时错误,我无法解决.当调度程序启动并尝试触发第一个任务时,内存指针会丢失并且不会启动第一个堆栈,而是在第一个任务内启动一个函数,并在退出函数时丢失.
这是相应的调试日志:
COREB: end setup LED
COREB: handler declared
COREB: Initialise New TCB:NewTCB address: 3d01000
COREB: TopofStask: 0, pxTopOfStack = 3d0263c
COREB: pxTaskCode =3c033a0, pvParameters = 0
COREB: returned pxNewTCB->pxTopOfStack = 3d02588
COREB: task created:
COREB: top of stack: 3d02588
COREB: GenericListItem: 0
COREB: Event ListItem: 9
COREB: Priority: 1
COREB: start of stack: 3d02000
COREB: Task Name: BootTas
COREB: TCB number: 0
COREB: Task Tag: 0
COREB: Add the idle task at the …
Run Code Online (Sandbox Code Playgroud) 我可以在FreeRTOS上使用Java吗?
如果是这样,是否有任何好的URL可以帮助我开始?
我可以期待什么问题?
我在一个小型嵌入式系统上使用FreeRTOS(newlib),发现printf和family浪费了大量的堆栈空间.我有很多任务,而且我没有足够的ram来使每个大的堆栈足以支持printf()调用.为了解决这个问题,我正在创建一个"printf服务器"任务,它将拥有一个大堆栈并代表其他任务执行所有printf().
所以我的问题是,将va_list传输到另一个线程(任务)的正确方法是什么?以下示例生成垃圾参数.
关于这是如何工作的快速说法:task_printf()将其参数填充到静态变量中,然后发出server_task信号以执行实际打印.当server_task完成时,它会通知客户端继续.
// printf parameters
static va_list static_args;
static const char *static_format;
static int static_result;
// printf server task. Processes printf requests forever
void server_task(void *pvParameters)
{
while(1)
{
xSemaphoreTake(printf_start, portMAX_DELAY); // wait for start command
static_result = vprintf(static_format, static_args);
xSemaphoreGive(printf_finished); // give finish signal
}
}
// get server task to print something for us
int task_printf(const char *format, ...)
{
int result;
xSemaphoreTake(printf_mutex, portMAX_DELAY); // lock
va_start(static_args, format);
static_format = format;
xSemaphoreGive(printf_start); // give start signal
xSemaphoreTake(printf_finished, …
Run Code Online (Sandbox Code Playgroud) 我在STM32F107VC上使用FreeRTOS V6.1.1并且经常出现malloc错误.堆区域在链接器脚本中定义,但在几次分配后它仍然卡在pvPortMalloc()的这个循环中:
while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock != NULL ) )
{
pxPreviousBlock = pxBlock;
pxBlock = pxBlock->pxNextFreeBlock;
}
pxBlock: 0x20002300
pxPreviousBlock: 0x20002300
pxNewBlockLink: 0x00
xHeapHasBeenInitialised: 0x01
Run Code Online (Sandbox Code Playgroud)
链接器脚本:
/* Entry Point */
ENTRY(Reset_Handler)
/* Highest address of the user mode stack */
_estack = 0x20010000; /* end of 64K RAM */
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0; /* required amount of heap */
_Min_Stack_Size = …
Run Code Online (Sandbox Code Playgroud) 我目前正在开发我公司正在开发的消费电子产品的操作系统.我已经决定将freeRTOS作为我们操作系统的主干,并且正努力在操作系统中实现硬件功能.但是,我遇到了一个关于在freeRTOS中运行第三方应用程序的问题.
最初我认为任务是一个应用程序,基本上你有"myapplication.c"和"myapplication.h"包含所有应用程序必需的函数,代码将驻留在任务中的for(;;)循环中(作为一个主要的while循环).然后,当用户决定运行该应用程序时,会将一个函数指针传递给队列,然后我的app_launcher任务会使用第三方任务或应用程序创建新任务.
然而,这种方法的问题是操作系统已经被编译并驻留在微控制器上,并且可以根据用户的需要安装和删除应用程序......显然,应用程序需要从操作系统进行编译和执行.在标准的unix机器上,我会使用fork之类的东西来选择可执行文件并给它自己的进程.但是我在freeRTOS中找不到类似的功能..我的另一个想法是接近应用程序开发的脚本语言,但我不知道如何启动这些应用程序......
所以问题是,如何让freeRTOS从尚未加入操作系统的第三方开发人员那里运行应用程序?
我目前正在尝试将FreeRTOS移植到TI AM335x处理器,该处理器以在BeagleBones上使用而闻名.我能够启动,运行GPIO并设置比较匹配计时器以运行系统滴答.如果我禁用中断,我可以看到在定时器启动后的正确时间后如何设置中断.如果我启用了中断,我的应用程序会在相同的时间后死掉.如果我尝试生成一个任务,也就是调用SWI处理程序,应用程序也会死掉.这使我相信矢量表不可用或设置不正确.SWI和IRQ的ROM异常向量具有4030CE08h和4030CE18h的协议.TRM在RAM中再次执行一些分支,它说:
用户代码可以将任何异常重定向到自定义处理程序,方法是将其地址写入4030CE24h到4030CE3Ch的适当位置,或者覆盖4030CE04h到4030CE1Ch之间地址之间的分支(加载到PC)指令.
因此,我的vIRQHandler函数地址写入4030CE38h.人们希望这已经足够了,但遗憾的是没有.我怀疑我的boot.s文件有问题,但是我的程序集从来没有那么好,我很难理解代码.boot.s和项目的其余部分是从OMAP3端口启动的.靴子:
.section .startup,"ax"
.code 32
.align 0
b _start /* reset - _start */
ldr pc, _undf /* undefined - _undf */
ldr pc, _swi /* SWI - _swi */
ldr pc, _pabt /* program abort - _pabt */
ldr pc, _dabt /* data abort - _dabt */
nop /* reserved */
ldr pc, _irq /* IRQ - read the VIC */
ldr pc, _fiq /* FIQ - _fiq */
_undf: .word 0x4030CE24 /* undefined */
_swi: …
Run Code Online (Sandbox Code Playgroud) 使用RTOS(例如FreeRTOS)时,每个线程都有单独的堆栈空间。那么,ISR(中断服务程序)呢,它们在内存中是否有单独的堆栈?还是可以配置的?
如果它们没有用于存储在ISR中声明的局部变量的堆栈?
FreeRTOS队列周围的C++ wapper可以简化为:
template<typename T>
class Queue<T>
{
public:
bool push(const T& item)
{
return xQueueSendToBack(handle, &item, 0) == pdTRUE;
}
bool pop(T& target)
{
return xQueueReceive(handle, &target, 0) == pdTRUE;
}
private:
QueueHandle_t handle;
}
Run Code Online (Sandbox Code Playgroud)
xQueueSendToBack
各州的文件:
The item is queued by copy, not by reference.
不幸的是,它实际上是通过副本,因为它都以a结尾memcpy
,这是有道理的,因为它是一个C API.虽然这适用于普通旧数据,但是更复杂的项目(例如以下事件消息)会产生严重问题.
class ConnectionStatusEvent
{
public:
ConnectionStatusEvent() = default;
ConnectionStatusEvent(std::shared_ptr<ISocket> sock)
: sock(sock)
{
}
const std::shared_ptr<ISocket>& get_socket() const
{
return sock;
}
private:
const std::shared_ptr<ISocket> sock;
bool connected;
}; …
Run Code Online (Sandbox Code Playgroud) 使用ESP-IDF(ESP32 SDK)的ESP32应用程序与同一SPI总线上的两个SPI从站通信(ILI9341 TFT驱动程序,NRF24L01 + RF收发器).总的来说,它很棒.但是,从RF收发器接收的一些数据被截断,即只有前几个字节是正确的,其余的是垃圾.
问题或多或少是可重现的,并且只有在接收截断数据之前立即与其他从设备(TFT驱动器)进行SPI通信时才会出现问题.
有问题的SPI事务是一个全双工事务,它在接收10个字节时发送一个命令字节和10个哑字节.它使用VSPI总线和DMA通道1.如果出现问题,只有前几个字节是正确的,而最后2到6个字节是无效的(0或虚拟字节的值).
我挖掘了SDK代码(spi_master.c
),添加了调试代码,并在DMA的lldesc_t
结构中观察到了一个令人惊讶的值:
在事务开始时,它用length = 0x0c
和初始化size = 0x0c
.0x0c是12个字节,即10个字节四舍五入到下一个字.
在交易结束时,值为length = 0x07
和size = 0x0c
(长度可能略有不同).因此,事务只读取7个字节,然后以某种方式终止.或者更确切地说DMA操作终止.
代码非常简单:
uint8_t* buffer = heap_caps_malloc(32, MALLOC_CAP_DMA);
...
memset(buffer, CMD_NOP, len);
spi_transaction_t trx;
memset(&trx, 0, sizeof(spi_transaction_t));
trx.cmd = 0x61;
trx.tx_buffer = buffer;
trx.length = 8 * 10;
trx.rx_buffer = buffer;
trx.rxlength = 8 * 10;
esp_err_t ret = spi_device_transmit(spi_device, &trx);
Run Code Online (Sandbox Code Playgroud) 我有一个脚本可以计算出每个FreeRTOS任务中有多少可用堆栈空间。GDB的语言设置为auto
。当当前语言为时c
,脚本可以正常工作,但是当当前语言为时,脚本将失败ada
。
我,在班上Stacks
,
tcb_t = gdb.lookup_type("TCB_t")
int_t = gdb.lookup_type("int")
Run Code Online (Sandbox Code Playgroud)
过去曾:
找到{Ada任务控制块} .Common.Thread,
thread = atcb["common"]["thread"]
Run Code Online (Sandbox Code Playgroud)
转换为指向FreeRTOS任务控制块的指针,
tcb = thread.cast(Stacks.tcb_t.pointer()).dereference()
Run Code Online (Sandbox Code Playgroud)
找到堆栈的逻辑顶部
stk = tcb["pxStack"].cast(Stacks.int_t.pointer())
Run Code Online (Sandbox Code Playgroud)
现在,我需要在逻辑上向下循环堆栈,直到找到与初始化值不相等的条目为止,
free = 0
while stk[free] == 0xa5a5a5a5:
free = free + 1
Run Code Online (Sandbox Code Playgroud)
如果当前帧的语言是工作正常c
,但如果这是ada
我得到的
Python异常<class'gdb.error'>不是数组或字符串:Python命令中发生错误:不是数组或字符串
我已经将其追溯到表达式stk[free]
,该表达式使用当前语言的规则进行解释(在Ada中,数组索引使用括号,因此它将是stk(free)
,这当然是非法的,因为Python将其视为函数调用)。
我已经为此工作了
def invoke(self, arg, from_tty):
gdb.execute("set language c")
...
gdb.execute("set language auto")
Run Code Online (Sandbox Code Playgroud)
但是,如果不将语言重新设置为原来的语言,这似乎是错误的。
所以,