我永远不会相信自己可以在2017年处于这个位置,但是我有一个目标系统(LPC2138),尽管我有很多尝试,但尽管我有很多尝试,但尽管我有很多尝试。由于各种原因,我确实需要使用它,所以这只是与之相处的问题。该应用程序是"中断友好的",带有几个异步I/O流(SPI,UART)加上计时器信号。我有利的一件事是,与我的实时要求相比,处理器非常快,所以我有很多备用的咕unt声。
我坚持使用的方法是在一个大调查的循环中完成整个事情,其中包括3个FIFOS来处理I/O。快速浏览一下似乎可行,有人根据经验有任何评论吗?
中断问题并非微不足道,100%与平台兼容的Hello World片段直接在网络上直接工作,当它们运行系统以炒状态崩溃时。如果确实有一个明确的专家修复,某人知道的地方,那么将不胜感激。
不知道您的应用程序和目标平台,我无法给您一个确定的答案!
,但是,您根据经验要求评论。这里是: - )
-
您提到实时要求。没有中断的情况下工作实际上可以帮助您!当我们进行具有艰难实时要求的项目时,我们没有使用中断。假设我们正在处理传入的数据流,并且完全有20个单词来处理一个单词,否则我们会错过下一个单词,而在处理一个单词的中间,我们被打断了。砰!失去了下一个。因此,我们进行了很多民意调查。在不同的应用程序中,设计决策可能会有所不同,使用中断来处理至关重要的工作,但以非真实时间代码为代价。当时我从事的商店中的理念非常反干扰。
-
投票可能会"浪费"一些资源(并不是真正浪费,因为您必须这样做:-))。但是您提到您的处理器足够快。如果您可以满足您的速度要求,请享受投票。在很多方面,它比中断更容易处理。您的程序可以更好地控制。
-
fifos很好。他们软化了您的实时要求。
-
我根本不知道您的HW设计,但是如果您在那里有逻辑芯片和灵活的HW工程师(好的,那是矛盾的:-)),您可以路由一些输入等通过HW并使用HW逻辑来处理您的某些简单要求,并为您提供一个界面,以使编写程序更容易(例如,可以针对您的特定需求进行某种优化的FIFO,或者是为您提供的登记册一口气等)
所以,去吧!您将学习一种全新的方法,甚至具有一些优势。
不知道您被卡住了,我们需要更多信息,但是也许很小的骨骼会确认您至少在做这几件事。您之前是否做过ARM7或第一次是ARM7,或者您精通ARM7/ARM世界,但不能让中断工作?
start.s
.globl _start
_start:
.globl _start
_start:
ldr pc,reset_handler
ldr pc,undefined_handler
ldr pc,swi_handler
ldr pc,prefetch_handler
ldr pc,data_handler
ldr pc,unused_handler
ldr pc,irq_handler
ldr pc,fiq_handler
reset_handler: .word reset
undefined_handler: .word hang
swi_handler: .word hang
prefetch_handler: .word hang
data_handler: .word hang
unused_handler: .word hang
irq_handler: .word irq
fiq_handler: .word hang
reset:
;@ (PSR_IRQ_MODE|PSR_FIQ_DIS|PSR_IRQ_DIS)
mov r0,#0xD2
msr cpsr_c,r0
ldr sp,=0x40002000
;@ (PSR_FIQ_MODE|PSR_FIQ_DIS|PSR_IRQ_DIS)
mov r0,#0xD1
msr cpsr_c,r0
ldr sp,=0x40003000
;@ (PSR_SVC_MODE|PSR_FIQ_DIS|PSR_IRQ_DIS)
mov r0,#0xD3
msr cpsr_c,r0
ldr sp,=0x40004000
bl notmain
hang: b hang
.globl PUT32
PUT32:
str r1,[r0]
bx lr
.globl GET32
GET32:
ldr r0,[r0]
bx lr
.globl dummy
dummy:
bx lr
.globl enable_irq
enable_irq:
mrs r0,cpsr
bic r0,r0,#0x80
msr cpsr_c,r0
bx lr
irq:
push {r0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,lr}
bl c_irq_handler
pop {r0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,lr}
subs pc,lr,#4
是的,这是太多的寄存器...只需要挥发性的编译器覆盖其他寄存器。
notmain:
void c_irq_handler ( void )
{
}
void notmain ( void )
{
unsigned int ra;
for(ra=0;ra<100;ra++) dummy(ra);
}
flash.ld
MEMORY
{
rom : ORIGIN = 0x00000000, LENGTH = 0x1000
ram : ORIGIN = 0x40000000, LENGTH = 0x1000
}
SECTIONS
{
.text : { *(.text*) } > rom
.bss : { *(.bss*) } > ram
}
猜猜我不需要.bss
构建
arm-none-eabi-as start.s -o start.o
arm-none-eabi-gcc -O2 -c notmain.c -o notmain.o
arm-none-eabi-ld -T flash.ld start.o notmain.o -o so.elf
arm-none-eabi-objdump -D so.elf > so.list
arm-none-eabi-objcopy so.elf -O binary so.bin
始终检查您的so.list
他们有一种有趣的方法来确定您是否有闪光灯或是否应该倾倒到启动程序
有效用户代码的标准:保留的手臂中断向量 位置(0x0000 0014)应包含2的补充 剩余中断向量的检查和签名。这会导致校验和 在所有向量的中,为0。
我还没有这样做,可以手工做到这一点,也可以让程序进行编程。
将其更改为此
ldr pc,reset_handler
ldr pc,undefined_handler
ldr pc,swi_handler
ldr pc,prefetch_handler
ldr pc,data_handler
.word 0xb8a06f58 @ldr pc,unused_handler
ldr pc,irq_handler
ldr pc,fiq_handler
应该很好。
如果这对小学完全没有用,那么让我知道将删除这个答案。
notmain.c
void PUT32 ( unsigned int, unsigned int );
unsigned int GET32 ( unsigned int );
void enable_irq ( void );
#define T0IR 0xE0004000
#define T0TCR 0xE0004004
#define T0PC 0xE0004010
#define T0MCR 0xE0004014
#define T0TC 0xE0004008
#define T0MCR0 0xE0004018
void c_irq_handler ( void )
{
PUT32(T0IR,1);
}
void notmain ( void )
{
PUT32(T0TCR,2);
PUT32(T0TCR,0);
PUT32(T0TC,0);
PUT32(T0MCR0,0x100000);
PUT32(T0MCR,0x1); //3);
PUT32(T0TCR,1);
while(1)
{
if(GET32(T0IR&1)) break;
}
PUT32(T0IR,1);
PUT32(T0TCR,2);
PUT32(T0TCR,0);
PUT32(T0TC,0);
PUT32(T0MCR0,0x100000);
PUT32(T0MCR,0x1); //3);
PUT32(T0IR,1);
enable_irq();
PUT32(T0TCR,1);
while(1) continue;
}
刚从手册中敲出了这一点,没有检查是否有计时器启用时钟等。就我个人而言,我首先要抬起gpio,眨眼,带有大型计数器循环
for(ra=0;ra<0x20000;ra++) dummy(ra);
然后在以轮询模式下使用计时器(只需将其自由运行)根据此时间眨眼就可以找出时钟速度,从而导致UART,获得UART,UP,UP,拥有一个琐碎的例程用于打印数据
void hexstring ( unsigned int d )
{
//unsigned int ra;
unsigned int rb;
unsigned int rc;
rb=32;
while(1)
{
rb-=4;
rc=(d>>rb)&0xF;
if(rc>9) rc+=0x37; else rc+=0x30;
uart_send(rc);
if(rb==0) break;
}
uart_send(0x0D);
uart_send(0x0A);
}
八进制甚至更容易
然后终于中断的东西,像上面一样进行代码,我会在计时器中进行轮询和打印各种寄存器,看看该中断寄存器是否首先在投票模式下(第二,第三,第四...没有)。使处理器中断(一段时间不要这样做)。
一旦我可以在外围级别看到它,有些人不起作用,但假设这样做。然后在这种情况下有一个VIC,我假设此寄存器
VICRawIntr 0xFFFFF008
如果主张计时器中断并已发射,也应断言。确认它是(出现的位4)确认当中断在周围清除时会消失。
vicintSelect重置为零是IRQ,这就是我们想要的,现在不需要触摸它。
我假设在Vicintenable中设置了位4
然后再次进行投票事件,以查看发生了什么。
现在,我希望看到Vicirqstatus中的中断节目(仍然完全轮询还不能使IRQ能够到达处理器),并在周围清除时消失,或者弄清楚如果清除周围中断的情况如何清除它
现在是时候将IRQ授予处理器了,我个人会将一个字节推入UART,以看到它弹出了。或轻拂LED或其他内容。
从理论上讲,我们只是清除围栏并返回以安全地返回应用程序。
我遵循相同的过程,无论它是MCU或全尺寸的处理器,等等。中断可能是噩梦,而您编写的代码越多,而无需测试越可能失败。有时每次测试需要一行代码。YMMV。
再次,如果这完全没有用,则将删除。我认为我有一个/大约2148,但没有2138,并且不会仅订购一个只是为了编写/测试工作代码。由于此ARMV7TDDMI出现,并且在当前的ARMV8上变得更加痛苦,因此一直使用ARM。Pi-Zero等很有趣,因为它们是像这支ARM7的旧学校...
我认为计时器将更容易从中打断。另一个可能是GPIO PIN,尽管我认为这是更多的工作,但会在引脚之间绑上一个跳线,使一个输出一个输出一个带有中间边缘检测的输入,如果此芯片使用该芯片,则使用输出GPIO来更改输入状态一种干净的方式,并仔细阅读观察中断的整个投票过程,并确认您可以每次在每一层中删除中断。然后在核心的边缘上敲打,然后最终让它进入核心。