我想在不使用标准函数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) 我正在为Cortex-M3 cpu编写代码,我正在使用qemu-arm二进制执行单元测试.现在一切正常.但我想知道如果我能够测试整个系统使用qemu-system-arm?我的意思是,我想为qemu编写自定义"机器",我将在其中定义所需的内存映射,最后一些软件模仿所需的外设,是否有这样的模块的一些例子?我发现这方面的信息很少.我已经hw在qemu源代码树的目录中读了一些源代码,但它几乎都没有注释,我仍然不确定我是否理解如何将新机器添加到qemu以及如何将外围设备附加到地址空间?
我正在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++,知道我不执行动态内存分配对我来说很重要。但是,我想充分利用 STD 库。确定 STD 中的函数/类是否使用动态内存分配的最佳策略是什么?
到目前为止,我想出了这些选项:
如果您看到任何其他选项或有做类似事情的经验,请告诉我。
ps 目前我主要使用 ARM Cortex-Mx 芯片使用 GCC 进行编译。
更新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) 在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上实现类似功能的唯一方法是:
根据ldrex/strex函数的使用方式,禁用中断可能会合理地工作,但改变"load-exclusive"的语义似乎很糟糕,如果它被放弃会导致不良副作用.代码修补的想法似乎可以实现所需的语义,但它看起来很笨重.
(顺便说一句,附带问题:我想知道为什么M3上的STREX将成功/失败指示存储到寄存器而不是简单地设置一个标志?它的实际操作需要操作码中的四个额外位,要求有一个寄存器来保持成功/ failure指示,并要求使用"cmp r0,#0"来确定它是否成功.如果编译器没有将结果记录在寄存器中,那么编译器是否能够理智地处理STREX内在函数? ?进入寄存器需要两个简短的指示.)
我正在使用mbed的LPC 1768板(带有cortex M3 cpu),我正在尝试在这里实现一些功能,主要是从SD卡升级用户应用程序,我正在编写两个程序,首先是一个bootloader/nano-kernel,以及一个用户应用程序(helloworld将开始):
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)都是正确的并且位于正确的位置.
我相信我在这里遗漏了一些东西,是否有任何我应该关注的低级代码?我已经在线阅读了文档的音调,从我发现的例子中,他们以与我相同的方式跳转到用户代码...非常感谢任何帮助.
我准备在STM32处理器上为我的项目使用C开发Cortex-M内核的一些固件,并在网上搜索我发现了很多不同的编译器:Keil,IAR,Linaro,Yagarto和ARM嵌入式GNU工具处理器.
我想知道,这些可能影响我选择的编译器之间存在哪些功能差异?例如,作为发烧友,我不需要供应商的支持或帮助,目前对代码大小的限制是可以的.此外,易用性并不是主要关注点,因为我喜欢学习(目前我已经配置了Keil Lite和Eclipse以及GNU ARM配置和工作).
生成的代码在这些编译器之间的大小/速度方面是如此不同?有比较表吗?(我在网上发现只有陈旧的信息)
我正在使用STMicroelectronics的STM32F746NG微控制器.该器件基于ARM Cortex-M7架构.我花了很多时间来理解示例项目中的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) 我想计算在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)