标签: cortex-m

在不使用标准功能的情况下在C中生成正弦信号

我想在不使用标准函数sin()的情况下在C中生成正弦信号,以触发LED亮度的正弦形状变化.我的基本想法是使用具有40个点和插值的查找表.

这是我的第一个方法:

const int sine_table[40] = {0, 5125, 10125, 14876, 19260, 23170, 26509, 29196,
31163, 32364, 32767,  32364, 31163, 29196, 26509, 23170, 19260, 14876, 10125,
5125, 0, -5126, -10126,-14877, -19261, -23171, -26510, -29197, -31164, -32365,
-32768, -32365, -31164, -29197, -26510, -23171, -19261, -14877, -10126, -5126};

int i = 0;
int x1 = 0;
int x2 = 0;
float y = 0;

float sin1(float phase)
{
    x1 = (int) phase % 41;
    x2 = x1 + 1;
    y = (sine_table[x2] - …
Run Code Online (Sandbox Code Playgroud)

c embedded cortex-m

28
推荐指数
8
解决办法
6292
查看次数

如何使用自定义外设和内存映射创建QEMU ARM计算机?

我正在为Cortex-M3 cpu编写代码,我正在使用qemu-arm二进制执行单元测试.现在一切正常.但我想知道如果我能够测试整个系统使用qemu-system-arm?我的意思是,我想为qemu编写自定义"机器",我将在其中定义所需的内存映射,最后一些软件模仿所需的外设,是否有这样的模块的一些例子?我发现这方面的信息很少.我已经hw在qemu源代码树的目录中读了一些源代码,但它几乎都没有注释,我仍然不确定我是否理解如何将新机器添加到qemu以及如何将外围设备附加到地址空间?

arm qemu cortex-m

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

在字对齐处理器上使用未对齐数据的最快方法?

我正在ARM Cortex M0上做一个项目,它不支持未对齐(4字节)访问,我正在尝试优化未对齐数据的操作速度.

我将蓝牙低功耗访问地址(48位)作为6字节数组存储在一些作为数据包缓冲区的打包结构中.由于打包,BLE地址不一定从字对齐的地址开始,并且在优化我对这些地址的访问功能时遇到了一些复杂问题.

第一种也是最明显的方法是对数组中每个字节单独运行的for循环.例如,检查两个地址是否相同可以这样做:

uint8_t ble_adv_addr_is_equal(uint8_t* addr1, uint8_t* addr2)
{
  for (uint32_t i = 0; i < 6; ++i)
  {
    if (addr1[i] != addr2[i])
      return 0;
  }
  return 1;
}
Run Code Online (Sandbox Code Playgroud)

我在我的项目中做了很多比较,我想看看是否可以从这个功能中挤出更多的速度.我意识到对于对齐的地址,我可以将它们转换为uint64_t,并与应用的48位掩码进行比较,即

((uint64_t)&addr1[0] & 0xFFFFFFFFFFFF) == ((uint64_t)&addr2[0] & 0xFFFFFFFFFFFF)
Run Code Online (Sandbox Code Playgroud)

可以对写入进行类似的操作,并且它适用于对齐版本.但是,由于我的地址并不总是字对齐(甚至是半字),所以我必须做一些额外的技巧来完成这项工作.

首先,我想出了编译器宏的未经优化的噩梦:

#define ADDR_ALIGNED(_addr) (uint64_t)(((*((uint64_t*)(((uint32_t)_addr) & ~0x03)) >> (8*(((uint32_t)_addr) & 0x03))) & 0x000000FFFFFFFF)\
                                    | (((*((uint64_t*)(((uint32_t)_addr+4) & ~0x03))) << (32-8*(((uint32_t)_addr) & 0x03)))) & 0x00FFFF00000000)
Run Code Online (Sandbox Code Playgroud)

它基本上将整个地址移位到前一个字对齐的存储器位置,而不管偏移量.例如:

    0       1       2       3
|-------|-------|-------|-------|
|.......|.......|.......|<ADDR0>|
|<ADDR1>|<ADDR2>|<ADDR3>|<ADDR4>|
|<ADDR5>|.......|.......|.......|
Run Code Online (Sandbox Code Playgroud)

    0       1       2       3
|-------|-------|-------|-------|
|<ADDR0>|<ADDR1>|<ADDR2>|<ADDR3>|
|<ADDR4>|<ADDR5>|.......|.......|
|.......|.......|.......|.......| …
Run Code Online (Sandbox Code Playgroud)

c arm memory-alignment micro-optimization cortex-m

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

STD 中的动态内存分配

经常使用微控制器和 C++,知道我不执行动态内存分配对我来说很重要。但是,我想充分利用 STD 库。确定 STD 中的函数/类是否使用动态内存分配的最佳策略是什么?

到目前为止,我想出了这些选项:

  1. 阅读并理解 STD 代码。这当然是可能的,但老实说,这不是最容易阅读的代码,而且代码很多。
  2. 阅读代码的一种变体可能是让脚本搜索内存分配并突出显示这些部分以使其更易于阅读。这仍然需要弄清楚在哪里使用分配内存的函数,等等。
  3. 只是测试我想使用的内容并使用调试器观察内存。到目前为止,我一直在使用这种方法,但这是一种反应式方法。我想在设计代码时事先知道我可以从 STD 中使用什么。还有什么可以说在某些(边缘)情况下分配了内存。这些可能不会出现在这个有限的测试中。
  4. 最后,可以做的是定期扫描生成的汇编代码以进行内存分配。我怀疑这可以编写脚本并包含在工具链中,但这又是一种反应式方法。

如果您看到任何其他选项或有做类似事情的经验,请告诉我。

ps 目前我主要使用 ARM Cortex-Mx 芯片使用 GCC 进行编译。

c++ embedded arm std cortex-m

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

gnu arm cortex m4上的C++异常处理程序,带有freertos

更新2016-12 此行为现​​在还有一个最小的示例:https://community.nxp.com/message/862676


我正在使用ARM Cortex M4和freertos使用freescales自由Kinetis IDE(gnu arm工具链).问题是

try {
    throw 4; // old scenario also not working: throw std::runtime_error("wut");
} catch (...) {
}
Run Code Online (Sandbox Code Playgroud)

在try处理程序之后导致暂停的CPU和代码,或者在catch处理程序中(当添加一些代码时)不会执行.

可以在这里找到汇编:https://gist.github.com/Superlokkus/3c4201893b4c51e154e2a0afdf78fef0

我认为这会导致SVC中断,我很抱歉我弄错了,Freertos欺骗了我,因为当我扔东西时它会在DefaultISR中停止.

throw indeeds跳转到 __cxa_throw然后从那里跳到___Unwind_RaiseException __gnu_Unwind_RaiseException __cxa_begin_catch> <_ZSt9terminatev> 所以它看起来像是std::terminate被调用,但是catch all块不应该允许这个.或者我的假设是错误的,这种行为是因为gcc C++运行时异常支持是一个总是调用终止的存根?!

更新2016-09:因为我看到rand()尝试使用malloc(),我还定义了一个工作的malloc()/ freeRTOS函数和etvoilà:__ cxa_allocate_exception使用malloc(我想知道工具链是如何期望我处理bad_alloc的情况).所以现在,它仍然崩溃,但在异常分配后(我认为):执行路径是:

(throwing function after exception allocation)
__cxa_throw
   ...                        //(some intructions in __cxa_throw)
   __cxa_begin_catch  //I guess something went wrong here
    _ZSt9terminatev // Immediately after __cxa_begin_catch
        _ZN10__cxxabiv111__terminateEPFvvE:
         00016dfc: push {r3, lr}
         00016dfe: blx r0  //Goes …
Run Code Online (Sandbox Code Playgroud)

c++ embedded arm freertos cortex-m

12
推荐指数
3
解决办法
1653
查看次数

在Cortex-M0中模拟LDREX/STREX(加载/存储独占)

在Cortex-M3指令集中,存在一系列LDREX/STREX指令,这样,如果使用LDREX指令读取某个位置,则只有在已知地址未被触及的情况下,以下STREX指令才能写入该地址.通常,效果是如果自LDREX以来没有发生中断(ARM术语中的"异常"),则STREX将成功,否则失败.

在Cortex M0中模拟这种行为最实用的方法是什么?我想为M3编写C代码并将其移植到M0.在M3上,人们可以说:

__inline void do_inc(unsigned int *dat)
{
  while(__strex(__ldrex(dat)+1,dat)) {}
}

执行原子增量.我能想到在Cortex-M0上实现类似功能的唯一方法是:

  1. 让"ldrex"禁用异常并让"strex"和"clrex"重新启用它们,并要求每次"ldrex"必须很快跟随"strex"或"clrex".
  2. 让"ldrex","strex"和"clrex"成为RAM中的一个非常小的例程,其中一条"ldrex"指令被修补为"str r1,[r2]"或"mov r0,#1".让"ldrex"例程将"str"指令插入"strex"例程,然后将"clrex"例程插入"mov r0,#1".拥有可能使"ldrex"序列调用"clrex"无效的所有异常.

根据ldrex/strex函数的使用方式,禁用中断可能会合理地工作,但改变"load-exclusive"的语义似乎很糟糕,如果它被放弃会导致不良副作用.代码修补的想法似乎可以实现所需的语义,但它看起来很笨重.

(顺便说一句,附带问题:我想知道为什么M3上的STREX将成功/失败指示存储到寄存器而不是简单地设置一个标志?它的实际操作需要操作码中的四个额外位,要求有一个寄存器来保持成功/ failure指示,并要求使用"cmp r0,#0"来确定它是否成功.如果编译器没有将结果记录在寄存器中,那么编译器是否能够理智地处理STREX内在函数? ?进入寄存器需要两个简短的指示.)

assembly arm atomic cortex-m

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

Cortex M3的Bootloader

我正在使用mbed的LPC 1768板(带有cortex M3 cpu),我正在尝试在这里实现一些功能,主要是从SD卡升级用户应用程序,我正在编写两个程序,首先是一个bootloader/nano-kernel,以及一个用户应用程序(helloworld将开始):

  • 在0x00地址运行的Bootloader/nano-kernel,它会进行一些检查并最终获取SD卡上的二进制文件
  • Bootloader/nano-kernel会将这个二进制文件复制到地址0x9000(以后可能需要更改,但bootloader/nano-kernel不使用此空间,所以应该没问题)
  • Bootloader跳转到0x9000 + 4的用户应用程序

Sd卡很容易锻炼,我遇到了跳跃部分的问题.这是跳跃函数的代码.

void run(void) {

  void (*user_code_entry)(void);

  unsigned *p;   
  SCB->VTOR = (USER_FLASH_START & 0x1FFFFF80);

  // Load contents of second word of user flash - the reset handler address
  // in the applications vector table
  p = (unsigned *)(USER_FLASH_START +4); // USER_FLASH_START is 0x9000

  user_code_entry = (void (*)(void))p;

  // Jump to user application
  user_code_entry();
Run Code Online (Sandbox Code Playgroud)

}

所以我编译了(我使用Keil uvision4)用户应用程序将起始地址更改为0x9000.如果我编程我的电路板(使用flashmagictool),然后手动跳转(仍使用flashmagictool)到0x9004(0x9000 + 4),用户应用程序将运行,所以我相信编译工作正常,因此用户应用程序可以在0x9000运行.

但是,如果我运行bootloader/nano-kernel,这个没有跳转到用户应用程序,不幸的是因为我无法调试,我不知道发生了什么...我也试过不使用SD副本部分,所以我首先编程引导加载程序,基本上只是跳转到0x9004.然后我编写将位于0x9000的用户应用程序.如果我重启电路板,bootloader会运行,但不会跳转到用户应用程序.我检查了内存,似乎两个程序(bootloader + user-app)都是正确的并且位于正确的位置.

我相信我在这里遗漏了一些东西,是否有任何我应该关注的低级代码?我已经在线阅读了文档的音调,从我发现的例子中,他们以与我相同的方式跳转到用户代码...非常感谢任何帮助.

c arm bootloader keil cortex-m

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

ARM Cortex-M编译器的差异

我准备在STM32处理器上为我的项目使用C开发Cortex-M内核的一些固件,并在网上搜索我发现了很多不同的编译器:Keil,IAR,Linaro,Yagarto和ARM嵌入式GNU工具处理器.

我想知道,这些可能影响我选择的编译器之间存在哪些功能差异?例如,作为发烧友,我不需要供应商的支持或帮助,目前对代码大小的限制是可以的.此外,易用性并不是主要关注点,因为我喜欢学习(目前我已经配置了Keil Lite和Eclipse以及GNU ARM配置和工作).

生成的代码在这些编译器之间的大小/速度方面是如此不同?有比较表吗?(我在网上发现只有陈旧的信息)

gcc arm stm32 keil cortex-m

11
推荐指数
2
解决办法
5930
查看次数

了解ARM Cortex-M微控制器的linkerscript

我正在使用STMicroelectronics的STM32F746NG微控制器.该器件基于ARM Cortex-M7架构.我花了很多时间来理解示例项目中的linkerscript.我想出了基础知识,但我仍然无法掌握它的大部分内容.请帮我理解这些部分.

启动linkerscript

linkerscript开头如下:

/* Entry Point */
ENTRY(Reset_Handler) /* The function named 'Reset_Handler' is defined */
                     /* in the 'startup.s' assembly file.             */

/* Highest address of the user mode stack */
/* Remember: the stack points downwards */
_estack = 0x20050000;    /* End of RAM */

/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0x200;  /* Required amount of heap  */
_Min_Stack_Size = 0x400; /* Required amount of stack */ …
Run Code Online (Sandbox Code Playgroud)

linker arm linker-scripts newlib cortex-m

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

每个周期的ARM M4指令(IPC)计数器

我想计算在ARM cortex-M4(或cortex-M3)处理器上执行的每个循环的指令数.

它需要的是:我想要分析的代码的指令数量(在运行时执行)和代码执行的周期数.

1 - 周期数

使用循环计数器非常简单直接.

volatile unsigned int *DWT_CYCCNT  ;
volatile unsigned int *DWT_CONTROL ;
volatile unsigned int *SCB_DEMCR   ;

void reset_timer(){
    DWT_CYCCNT   = (int *)0xE0001004; //address of the register
    DWT_CONTROL  = (int *)0xE0001000; //address of the register
    SCB_DEMCR    = (int *)0xE000EDFC; //address of the register
    *SCB_DEMCR   = *SCB_DEMCR | 0x01000000;
    *DWT_CYCCNT  = 0; // reset the counter
    *DWT_CONTROL = 0; 
}

void start_timer(){
    *DWT_CONTROL = *DWT_CONTROL | 1 ; // enable the counter …
Run Code Online (Sandbox Code Playgroud)

c arm performancecounter cortex-m3 cortex-m

10
推荐指数
2
解决办法
5534
查看次数