小编Cor*_*uzu的帖子

ARM:启动/唤醒/启动其他CPU内核/ AP并传递执行起始地址?

在过去的3-4天里,我一直在用这个来敲打我的脑袋,我找不到DECENT解释性文件(来自ARM或非官方的)来帮助我.我有一块ODROID-XU板(big.LITTLE 2 x Cortex-A15 + 2 x Cortex-A7)板,我正在尝试更多地了解ARM架构.在我的"试验"代码中,我现在已经到了我想从其WFI(等待中断)状态唤醒其他核心的阶段.

我仍然试图找到的缺失信息是:

1.获取内存映射GIC的基地址时,我明白我需要读取CBAR; 但没有任何文档解释如何安排CBAR中的位(2个PERIPHBASE值)来获取最终的GIC基址

2.通过GICD_SGIR寄存器发送SGI时,我应该选择0到15之间的中断ID?有关系吗?

3.通过GICD_SGIR寄存器发送SGI时,如何告知其他内核何处开始执行

4. U-BOOT引导加载程序加载我的代码的事实如何影响这个上下文?

的Cortex-A系列程序员指南3.0版(这里找到:链接)规定在以下部分22.5.2(在Linux中SMP开机,页271):

当主核心启动时,辅助核心将使用WFI指令保持待机状态.它(主核心)将为辅助核心提供启动地址,并使用处理器间中断(IPI)唤醒它们,这意味着通过GIC发信号通知SGI

Linux如何做到这一点?文档-S没有提供有关" 它将为辅助核心提供启动地址 "的任何其他详细信息.

我的挫折感越来越大,我会非常感谢你的答案.非常感谢你提前!

额外细节

我使用的文档:

  • ARMv7-A&R架构参考手册
  • Cortex-A15 TRM(技术参考手册)
  • Cortex-A15 MPCore TRM
  • Cortex-A系列程序员指南v3.0
  • GICv2架构规范

我现在做了什么:

  • UBOOT将我加载到0x40008000; 我已经设置了翻译表(TTB),相应地写了TTBR0和TTBCR并将0x40008000映射到0x8000_0000(2GB),所以我也启用了MMU
  • 设置我自己的异常处理程序
  • 我在串口上有Printf功能(ODROID-XU上的UART2)

以上所有似乎都能正常工作.

我现在要做的是:

  • 获取GIC基地址=>在我读CBAR的那一刻,我简单地用(和)它的值与0xFFFF8000并使用它作为GIC基地址,虽然我几乎可以肯定这是不对的
  • 通过写入值为0x1的GICD_CTLR,启用GIC分配器(偏离GIC基地址偏移0x1000?)
  • 使用以下参数构造SGI:Group = 0,ID = 0,TargetListFilter ="除了我以外的所有CPU"并通过GICD_SGIR GIC寄存器发送(写入)
  • 由于我没有传递其他内核的任何执行起始地址,所以这一切都没有发生

.... UPDATE ....

我已经开始查看Linux内核和QEMU源代码以寻找答案.这是我发现的(如果我错了,请纠正我):

  • 当给电路板加电时,ALL THE CORES从复位向量开始执行
  • 软件(固件)组件上的次级铁心和一些其他的代码,将作为这些二次铁芯和初级芯之间的协议中,当后者希望再次唤醒他们执行WFI
  • 例如, …

arm multiprocessing cpu-cores wakeup cortex-a

16
推荐指数
1
解决办法
7671
查看次数

GCC:如何告诉GCC将'main'函数放在.text段的开头?

我刚刚开始学习一些ARM编程,但我遇到了一个有点恼人的问题.我用来编译源代码的工具链是Sourcery CodeBench Lite 2013.05-23(可以在这里找到:https://sourcery.mentor.com/GNUToolchain/release2449 )

我需要的是告诉GCC或LD或OBJCOPY将'main'函数的编译字节码放在.text段的开头.

有没有办法实现这个目标?(也许通过链接器脚本?)

谢谢

gcc program-entry-point ld linker-scripts objcopy

6
推荐指数
2
解决办法
5469
查看次数

COM对象方法不在CoInitialize-d和创建对象的线程上执行

我正在开发一个UI应用程序,在此过程中创建一个COM对象.问题是,我想完全在另一个线程上"移动"这个COM对象.

我这样做是:

  • 创建我要将对象移动到的新线程(使用CreateThread API)
  • 进入这个线程后,我正在调用PeekMessage为它设置一个消息队列
  • 调用CoInitialize,CoCreateInstance来创建COM对象,QueryInterface来获取我想要的接口
  • 最后,我在接口上调用一个方法,该方法显示一个MessageBox,其中包含GetCurrentThreadId()返回的值(我可以访问对象所在的COM库的VB6代码).

问题是,正如此消息框所示,对象方法仍然在原始UI线程上执行,而不是在我创建的线程上执行并完成所有这些步骤.还有一点需要注意,在调用接口方法之后,我还在其中设置了一个经典的消息循环.

我怎样才能改变这种行为并实现我想要的目标?(也就是说,我希望源自我新创建的线程的COM对象调用在IT上执行,而不是在原始应用程序线程上执行)

这里有一些伪代码使它更清晰:

void myMainUIMethod(){
  MessageBox(GetCurrentThreadId()); // displays 1
  CreateThread(&myCOMObjectThreadProc);
}
void myCOMObjectThreadProc(){
  MessageBox(GetCurrentThreadId()); // displays 2
  CoInitialize(NULL);
  myObject = CoCreateInstance(myObjectsCLSID);
  myObjectInterface = myObject->QueryInterface(myObjectInterfaceCLSID);
  myObjectInterface->showThreadIDMessageBox(); // this would be the COM object method call
}

And, in the VB6 code of the object, here's the pseudo-definition of showThreadIDMessageBox.
Public Sub showThreadIDMessageBox()
  Call MessageBox(GetCurrentThreadId()) //displays 1, I want it to display 2
End Sub
Run Code Online (Sandbox Code Playgroud)

在创建新线程之前,我已经通过CoUninitalizing在主线程上实现了我想要的.但为什么会这样呢?如果COM在我创建新线程之前在主线上初始化,可能由于某种原因它必须是..我不希望应用程序稍后崩溃,因为我必须在创建新线程之前调用CoUninitialize.这里有一些伪代码,它说明了首先调用CoInitialize的线程将是STA对象选择的线程.

void myMainUIMethod(){
  MessageBox(GetCurrentThreadId()); // displays 1
  CoUninitialize(); // uninitialize …
Run Code Online (Sandbox Code Playgroud)

com methods multithreading invoke

4
推荐指数
1
解决办法
4394
查看次数

C++单身人士:这个解决方案有多好?优点/缺点,替代方案

我正在开发一个C++项目,它有多个必须是单例的类,它们之间存在依赖关系(初始化顺序很重要).

我想出了这个解决方案:

  1. 我想成为单身人士的所有类都有受保护的构造函数,例如:
class MySingleton1
{
protected:
    MySingleton1();
}
Run Code Online (Sandbox Code Playgroud)
  1. 有一个源文件singleton_factory.cpp包含一个实例化的类Singletons,它派生自我想成为单例的所有类,如下所示:
#include "MySingleton1.hpp"
#include "MySingleton2.hpp"

class Singletons : public MySingleton1, public MySingleton2 {}
static Singletons s_singletons;
Run Code Online (Sandbox Code Playgroud)
  1. 仍然在singleton_factory.cpp中,对于每个单例类型,还实现了getSingleton函数的化:
template<>
MySingleton1& getSingleton()
{
    return s_singletons;
}

template<>
MySingleton2& getSingleton()
{
    return s_singletons;
}
Run Code Online (Sandbox Code Playgroud)
  1. 的特getSingleton将是"藏"的通用模板变形下,在singleton_factory.hpp:
template <class TSingleton>
TSingleton& getSingleton();
Run Code Online (Sandbox Code Playgroud)

好处:

  • 低耦合:

    • Singleton类不需要"知道"Singletons类,唯一需要在受保护的限定符下隐藏它们的构造函数(这甚至不是强制性的,只是好的做法).实际上知道Singletons类的唯一代码是singleton_factory.cpp
    • 具体实例的瘦依赖:想要使用类型T的单例的代码只需要包含类型为T的头和skinny singleton_factory.hpp
  • 可以通过 …

c++ singleton design-patterns

4
推荐指数
1
解决办法
172
查看次数

强制 GCC 在调用函数之前将参数压入堆栈(使用 PUSH 指令)

我已经开始在 GCC/G++ 下开发一个小型 16 位操作系统。我正在使用 GCC 交叉编译器,它是在 Cygwin 下编译的,我将 asm(".code16gcc\n") 作为每个 .CPP 文件的第一行,使用 Intel ASM 语法和命令行来编译和链接.CPP 文件如下所示:

G++: i586-elf-g++ -c $(CPP_FILE) -o $(OBJECT_OUTPUT) -nostdinc -ffreestanding -nostdlib -fno-builtin -fno-rtti -fno-exceptions -fpermissive -masm=intel

LD: i586-elf-ld -T $(LD_SCRIPT) $(OBJECT_OUTPUT) -o $(BINARY_OUTPUT)
Run Code Online (Sandbox Code Playgroud)

我目前面临的问题是GCC 将函数调用代码翻译成汇编的方式。

更具体地说,GCC 不使用 PUSH 指令来传递参数,而是“计算”参数相对于 ESP 的偏移量,然后使用 MOV 指令手动写入堆栈。

这对我来说没有好处,因为我依赖汇编代码中的 PUSH 指令。为了更清楚地说明我的问题,请使用以下两个函数:

void f2(int x);

void f1(){
    int arg = 8;
    asm("mov eax, 5");  // note: super hacky unsafe use of GNU C inline asm
    asm("push eax");    // Writing registers without …
Run Code Online (Sandbox Code Playgroud)

x86 gcc arguments inline-assembly stack-memory

1
推荐指数
1
解决办法
6353
查看次数