- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
对于一个大学项目,我们的项目团队想要为 Lego Mindstorm EV3 平台编写一个裸机操作系统。尽管我们做了很多研究和测试,但我们遇到了一个无法解决的中断处理问题。
这是平台的详细信息:
CPU:ARM926EJ-S(ARMv5架构)
SoC:德州仪器 Sitara AM1808
SoC 简短文档:http://www.ti.com/lit/ds/symlink/am1808.pdf
SoC 技术引用手册:http://www.ti.com/lit/ug/spruh82a/spruh82a.pdf
以下是我们尝试做的事情以及我们如何尝试做的事情:
我们想要初始化一个定时器中断,它应该每毫秒触发一次,以获得系统滴答声。我们操作系统的各种其他组件(例如软件-I2C-管理等)都需要此刻度。由于我们的团队对裸机编程相当陌生,我们以 TexasInstruments 为例来初始化 SoC 的定时器中断和中断 Controller 。此示例是 StarterWare 的一部分,旨在在 AM1808 评估板上运行。由于 Lego Mindstorm EV3 使用相同的 SoC,它也应该适用于我们。请参阅以下源代码:
startup.S:我们程序的入口点(基于 TI 提供的源代码)
#include "hw_aintc.h"
#include "soc_AM1808.h"
.global Entry
.global _stack
.global _bss_start
.global _bss_end
.global start_boot
.global _Reset
.global IRQHandler
.global FIQHandler
.global AbortHandler
.global SWIHandler
.global UndefInstHandler
.global CPUAbortHandler
@************************ Internal Definitions ********************************
@
@ Define the stack sizes for different modes. The user/system mode will use
@ the rest of the total stack size
@
.set UND_STACK_SIZE, 0x8
.set ABT_STACK_SIZE, 0x8
.set FIQ_STACK_SIZE, 0x8
.set IRQ_STACK_SIZE, 0x500
.set SVC_STACK_SIZE, 0x8
@
@ to set the mode bits in CPSR for different modes
@
.set MODE_USR, 0x10
.set MODE_FIQ, 0x11
.set MODE_IRQ, 0x12
.set MODE_SVC, 0x13
.set MODE_ABT, 0x17
.set MODE_UND, 0x1B
.set MODE_SYS, 0x1F
.equ I_F_BIT, 0xC0
.equ ADDR_HIPVR1, SOC_AINTC_0_REGS + AINTC_HIPVR(0)
.equ ADDR_HIPVR2, SOC_AINTC_0_REGS + AINTC_HIPVR(1)
.equ MASK_SWI_NUM, 0xFF000000
@**************************** Code Seection ***********************************
.text
@
@ This code is assembled for ARM instructions
@
.code 32
@******************************************************************************
@
@******************************************************************************
@
@ The reset handler sets up the stack pointers for all the modes. The FIQ and
@ IRQ shall be disabled during this. Then, clearthe BSS sections, switch to the
@ main() function.
@
Entry:
@
@ Set up the Stack for Undefined mode
@
LDR r0, =_stack @ Read the stack address
MSR cpsr_c, #MODE_UND|I_F_BIT @ switch to undef mode
MOV sp,r0 @ write the stack pointer
SUB r0, r0, #UND_STACK_SIZE @ give stack space
@
@ Set up the Stack for abort mode
@
MSR cpsr_c, #MODE_ABT|I_F_BIT @ Change to abort mode
MOV sp, r0 @ write the stack pointer
SUB r0,r0, #ABT_STACK_SIZE @ give stack space
@
@ Set up the Stack for FIQ mode
@
MSR cpsr_c, #MODE_FIQ|I_F_BIT @ change to FIQ mode
MOV sp,r0 @ write the stack pointer
SUB r0,r0, #FIQ_STACK_SIZE @ give stack space
@
@ Set up the Stack for IRQ mode
@
MSR cpsr_c, #MODE_IRQ|I_F_BIT @ change to IRQ mode
MOV sp,r0 @ write the stack pointer
SUB r0,r0, #IRQ_STACK_SIZE @ give stack space
@
@ Set up the Stack for SVC mode
@
MSR cpsr_c, #MODE_SVC|I_F_BIT @ change to SVC mode
MOV sp,r0 @ write the stack pointer
SUB r0,r0, #SVC_STACK_SIZE @ give stack space
@
@ Set up the Stack for USer/System mode
@
MSR cpsr_c, #MODE_SYS|I_F_BIT @ change to system mode
MOV sp,r0 @ write the stack pointer
@
@ Clear the BSS section here
@
Clear_Bss_Section:
LDR r0, =_bss_start @ Start address of BSS
LDR r1, =(_bss_end - 0x04) @ End address of BSS
MOV r2, #0
Loop:
STR r2, [r0], #4 @ Clear one word in BSS
CMP r0, r1
BLE Loop @ Clear till BSS end
@
@ Enter the start_boot function. The execution still happens in system mode
@
Enter_main:
LDR r10,=start_boot @ Get the address of start_boot
MOV lr,pc @ Dummy return
BX r10 @ Branch to start_boot
@ Interrupt Handler from exceptionhandler.S (provided by TI) - Note: the following code
@ will not be reached since start_boot contains an endless loop at it's end
@******************************************************************************
@* Function Definition of SWI Handler
@******************************************************************************
@
@ The SWI Handler switches to system mode if the SWI number is 458752. If the
@ SWI number is different, no mode switching will be done. No other SWI are
@ handled here
@
SWIHandler:
STMFD r13!, {r0-r1, r14} @ Save context in SVC stack
LDR r0, [r14, #-4] @ R0 points to SWI instruction
BIC r0, r0, #MASK_SWI_NUM @ Get the SWI number
CMP r0, #458752
MRSEQ r1, spsr @ Copy SPSR
ORREQ r1, r1, #0x1F @ Change the mode to System
MSREQ spsr_cf, r1 @ Restore SPSR
LDMFD r13!, {r0-r1, pc}^ @ Restore registers from IRQ stack
@******************************************************************************
@* Function Definition of IRQ Handler
@******************************************************************************
@
@ The IRQ handler jumps to the ISR of highest priority pending IRQ. The address
@ is taken from the HIPVR2 register, which contains the ISR address of highest
@ pending IRQ. This handler doesnot support nesting.
@
IRQHandler:
STMFD r13!, {r0-r3, r12, r14} @ Save context in IRQ stack
LDR r0, =ADDR_HIPVR2 @ R0 points to address of HIPVR2
LDR r1, [r0] @ R1 contains address of ISR
ADD r14, pc, #0 @ Save return address in LR
LDR pc, [r1] @ Go to ISR (still in IRQ mode)
LDMFD r13!, {r0-r3, r12, r14} @ Restore registers from IRQ stack
SUBS pc, r14, #0x4 @ Return to program before IRQ
@******************************************************************************
@* Function Definition of FIQ Handler
@******************************************************************************
@
@ The FIQ Handler jumps to the ISR of the highest priority pending FIQ. The
@ address is taken from HIPVR1, which contains the ISR address of the highest
@ pending FIQ. This handler doesnot support nesting
@
FIQHandler:
@
@ Save the required context in FIQ stack.
@
STMFD r13!, {r0-r3, r12, r14} @ Save context in FIQ stack
LDR r0, =ADDR_HIPVR1 @ R0 points to address of HIPVR1
LDR r1, [r0] @ R1 contains address of ISR
ADD r14, pc, #0 @ Save return address in LR
LDR pc, [r1] @ Go to ISR (still in FIQ mode)
LDMFD r13!, {r0-r3, r12, r14} @ Restore registers from FIQ stack
SUBS pc, r14, #0x4 @ Return to program state before FIQ
@******************************************************************************
@* Function Definition of Abort/Undef Handler
@******************************************************************************
@
@ The Abort handler goes to the C handler of abort mode. Note that the undefined
@ instruction is not handled separately.
@ if nothing is done in the abort mode, the execution enters infinite loop.
@
AbortHandler:
UndefInstHandler:
@
@ Disable all the interrupts
@
MRS r0, cpsr @ Read from CPSR
ORR r0, r0, #0xC0 @ Clear the IRQ and FIQ bits
MSR cpsr, r0 @ Write to CPSR
ADD r14, pc, #0 @ Store the return address
LDR pc, =CPUAbortHandler @ Go to C handler
#include <stdio.h>
#include <stdlib.h>
#include <systick.h>
#include <mytypes.h>
#include "cpu.h"
extern void Entry(void);
extern void UndefInstHandler(void);
extern void SWIHandler(void);
extern void AbortHandler(void);
extern void IRQHandler(void);
extern void FIQHandler(void);
// This is our own IRQ-Handler - it is not called either, we just wanted to check if the assembler code was the source of the problem
void irqHandler(void) {
unsigned int* isr_pointer = *(unsigned int *)*((unsigned int*)0xFFFEF604);
printf("ISR Handler called: %#10x\n", isr_pointer);
typedef void func(void);
func* f = (func*) isr_pointer;
f();
}
void c_entry() {
unsigned int counter = 1;
systick_init();
U32 localSystick = systick_get_ms();
// printf will write debug output to a UART port connected to a PC
printf("Current tick: %u (%u)\n", localSystick, counter);
do {
++counter;
localSystick = systick_get_ms();
printf("Current tick: %u (%u)\n", localSystick, counter);
} while (1);
}
// Code from Startup.c (TI example)
#include "hw_syscfg0_AM1808.h"
#include "hw_syscfg1_AM1808.h"
#include "hw_pllc_AM1808.h"
#include "hw_ddr2_mddr.h"
#include "soc_AM1808.h"
#include "evmAM1808.h"
#include "hw_types.h"
#include "psc.h"
#define E_PASS 0
#define E_FAIL -1
static void CopyVectorTable(void);
void BootAbort(void);
static unsigned int const vecTbl[16]=
{
// Primary vector Table entries
(unsigned int)Entry,
(unsigned int)UndefInstHandler,
(unsigned int)SWIHandler,
(unsigned int)AbortHandler,
(unsigned int)AbortHandler,
0xE59FF010,
(unsigned int)IRQHandler,
(unsigned int)FIQHandler,
// Secondary Vector Table entires
(unsigned int)Entry,
(unsigned int)UndefInstHandler,
(unsigned int)SWIHandler,
(unsigned int)AbortHandler,
(unsigned int)AbortHandler,
0xE59FF010,
(unsigned int)IRQHandler,
(unsigned int)FIQHandler
};
/**
* \brief Boot strap function which enables the PLL(s) and PSC(s) for basic
* module(s)
*
* \param none
*
* \return None.
*
* This function is the first function that needs to be called in a system.
* This should be set as the entry point in the linker script if loading the
* elf binary via a debugger, on the target. This function never returns, but
* gives control to the application entry point
**/
unsigned int start_boot(void)
{
printf("start_boot called\n");
SysCfgRegistersLock();
/* Disable write-protection for registers of SYSCFG module. */
SysCfgRegistersUnlock();
/* Initialize the vector table with opcodes */
CopyVectorTable();
c_entry();
while(1);
}
static void CopyVectorTable(void)
{
printf("CopyVectorTable called\n");
// According to the AM1808 Technical Reference Manual (Page 88), the vector table has to be located at 0xFFFF0000
unsigned int *dest = (unsigned int *)0xFFFF0000;
unsigned int *src = (unsigned int *)vecTbl;
unsigned int count;
for(count = 0; count < sizeof(vecTbl)/sizeof(vecTbl[0]); count++)
{
dest[count] = src[count];
}
}
void BootAbort(void)
{
printf("BootAbort called");
while (1);
}
/*
* This provides a 1000Hz tick for the system.
*
* We're using the AMT1808 Hardware Timer 2
*
* See also: timerCounter.c in TI/examples/evmAM1808/timer
*/
#include "soc_AM1808.h"
#include "hw_syscfg0_AM1808.h"
#include "interrupt.h"
#include "timer.h"
#include "evmAM1808.h"
#include "cpu.h"
#include "systick.h"
#include <stdio.h>
#define TMR_PERIOD_LSB32 (0x07FFFFFF)
#define TMR_PERIOD_MSB32 (0x0)
static volatile U32 systick_ms;
/* ISR, called 1000 times per second */
void
systick_isr_C(void)
{
/* Disable the timer interrupt */
TimerIntDisable(SOC_TMR_2_REGS, TMR_INT_TMR12_NON_CAPT_MODE);
printf("ISR called");
/* Clear the interrupt statusIntChannelSet(SYS_INT_TIMR2_ALL, 0); in AINTC */
IntSystemStatusClear(SYS_INT_TIMR2_ALL);
TimerIntStatusClear(SOC_TMR_2_REGS, TMR_INT_TMR12_NON_CAPT_MODE);
++systick_ms;
/* Enable the timer interrupt */
TimerIntEnable(SOC_TMR_2_REGS, TMR_INT_TMR12_NON_CAPT_MODE);
}
U32
systick_get_ms(void)
{
return systick_ms;
}
void
systick_init(void)
{
/* Setup timer for 64 bit mode */
/* Configuration of Timer */
TimerConfigure(SOC_TMR_2_REGS, TMR_CFG_64BIT_CLK_INT);
/* Set the 64 bit timer period */
TimerPeriodSet(SOC_TMR_2_REGS, TMR_TIMER12, TMR_PERIOD_LSB32);
TimerPeriodSet(SOC_TMR_2_REGS, TMR_TIMER34, TMR_PERIOD_MSB32);
/* Set up the ARM Interrupt Controller for generating timer interrupt */
/* Initialize AINTC and register timer interrupt */
IntAINTCInit();
/* Register the Timer ISR */
IntRegister(SYS_INT_TIMR2_ALL, systick_isr_C);
/* Set the channel number for Timer interrupt, it will map to IRQ */
IntChannelSet(SYS_INT_TIMR2_ALL, 2);
/* Enable IRQ for ARM (in CPSR)*/
IntMasterIRQEnable();
/* Enable AINTC interrupts in GER */
IntGlobalEnable();
/* Enable IRQ in AINTC */
IntIRQEnable();
/* Enable timer interrupts in AINTC */
IntSystemEnable(SYS_INT_TIMR2_ALL);
/* Enable the timer interrupt */
TimerIntEnable(SOC_TMR_2_REGS, TMR_INT_TMR12_NON_CAPT_MODE);
/* Start the timer */
TimerEnable(SOC_TMR_2_REGS, TMR_TIMER12, TMR_ENABLE_CONT);
// Deactivate interrupts on CPU - for test purposes
//IntMasterIRQDisable();
}
unsigned int* isr_pointer = *(unsigned int *)*((unsigned int*)0xFFFEF604);
if (isr_pointer != 0) {
irqHandler();
}
最佳答案
经过更多的研究和实验,我们能够解决这个问题。
如果有人对解决方案感兴趣,这就是导致问题的原因:
问题一:
中断向量未正确初始化。与 TexasInstruments 示例相反,向量不应包含中断处理程序的地址。相反,它应该包含机器代码操作。将程序计数器更改为正确地址的任何操作都有效,例如B ...(分支)或 LDR pc,...(加载程序计数器)。
这是解决此问题的新代码:
在启动.S中:
ExceptionHandler:
B Entry
B ExceptionHandler
B ExceptionHandler
B ExceptionHandler
B ExceptionHandler
B ExceptionHandler
B IRQHandler
B ExceptionHandler
/* Copy the vector table to it's destination at 0xFFFF0000 - this address is specified in the board's manual. */
static void CopyVectorTable(void)
{
unsigned int *dest = (unsigned int *)0xFFFF0000;
/* The address of the assembler exception vector */
unsigned int *addrExceptionHandler = (unsigned int *)ExceptionHandler;
int i;
/* We only set vector 1 to 7 and leave the Reset vector in peace */
/* Important: don't set the address of the vectors - we need to write the operation (i.e. the machine code) to that location */
for (i = 1; i < 8; ++i) {
dest[i] = addrExceptionHandler[i];
}
/* This code is required in order for the branch instructions (B ...) to work */
for (; i < 2048; ++i) {
dest[i] = addrExceptionHandler[i];
}
}
IRQHandler:
STMFD r13!, {r0-r3, r12, r14} @ Save context in IRQ stack
ADD r14, pc, #0 @ Save return address in LR
@ For whatever reason, we are unable to get the correct address of the ISR in this assembler code
@ So we just call our C handler which has a static address in RAM and let it handle the interrupt
@LDR pc, =systick_isr_C @ Works as well, but is not dynamic - we could only handle 1 interrupt
LDR pc, =irqHandler
LDMFD r13!, {r0-r3, r12, r14} @ Restore registers from IRQ stack
SUBS pc, r14, #0x4 @ Return to program before IRQ
关于interrupt - Lego Mindstorm EV3 上的裸机中断处理(TexasInstruments Sitara AM1808 SoC),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33420591/
#include int main() { int i; for( i = 0; i< 10 ; i++ ) { printf("test1 &d", i);
我有一个连接到远程服务器以查询数据的 C# 程序。数据很大,所以查询大约需要 2 分钟才能完成。在这 2 分钟的时间内,互联网中断了。这导致作业无法完成,程序卡在获取数据例程中。 它建立了连接,但在选
语句 1: [2,4,6,7,8].each do |i| (i % 2 == 0) || (puts "Not even" && break) puts i end 声明 2: [2
我想知道 C++ 是否有任何处理中断的方法。我希望一个程序将信息存储在文本文件中,而另一个程序根据文本文件中的内容打印一条语句。由于我希望它尽可能准确,因此我需要在更新程序更新文件时中断打印程序。 最
我正在尝试终止一个线程,但它不会中断或停止。所有这些都是名为 Webots 的软件 Controller 的一部分。我用它来模拟多机器人系统。在每个机器人的 Controller 中,我启动了一个线程
中断10h可以使用的服务有很多, 我想问一下关于其中两个我很困惑的问题 首先是, AH = 06H SCROLL UP WINDOW AH = 07H SCROLL DOWN WINDOW 在 D
我有一个基本的 SQL 问题,如果有两个事件连接,"A"和 "B"到 SQL 服务器,假设两者之间发生死锁,那么为了避免死锁,SQL 服务器将回滚其中一个连接“A”或“B”的交易。假设 SQL Ser
我有一个 mapkit/ View ,它工作正常 - 但我滚动并在 2 - 10 次移动后我的应用程序崩溃了......而且这只是一个“中断”。 这是我的代码的一部分。我认为这是后台线程和数组释放/覆
有什么办法可以做到,比如 C/C# ? 例如(C#风格) for (int i = 0; i Seq.tryFind (fun i -> printfn "%d" i i=66) 在实践中,
我的问题是Haskell如何与系统交互。 例如,IO如何发生? 我对IO monad不感兴趣。或者如何使Haskell打印字符串或读取文件。 我对Haskell和底层操作系统之间的层(如果是这样的话)
你能确认下一个break是否取消了内部for循环吗? for (out in 1:n_old){ id_velho <- old_table_df$id[out] for
我有一个程序可以进行一些数据分析,并且有几百行长。 在程序的早期,我想做一些质量控制,如果没有足够的数据,我希望程序终止并返回到 R 控制台。否则,我希望执行其余代码。 我尝试过break、brows
我有一个 if 语句,用于检查我的对象(向导)是否命中了项目。如果他这样做了,巫师的大小将会改变,他应该能够在与障碍物的 1 次碰撞中幸存。 现在我陷入了“在 1 个障碍物碰撞中幸存”,因为在我的碰撞
我正在尝试使用迭代器来显示很多内容。我不断收到“break;”错误线。它说这是一个无法访问的声明。如有任何帮助,我们将不胜感激。 public Lot getLot(int number) {
我正在创建一个应用程序,我需要在其中处理可能非常庞大且可能需要一些时间的数据。 现在我阅读了很多关于 IntentService 的资料,实际上我已经将它实现为处理 REST 调用的通信类,但现在我试
我有一个自定义的 UITableViewCell。该单元具有三个标签。最左边的“金额”标签具有以下约束。 在单元格的右侧,我有另一个标签,“Label Dollar Amount”。它具有以下约束:
我有以下不和谐嵌入: message.reply({ content: '', embed: { color: 11416728, author
JavaScript 不是我最擅长的技能,但我会尽力解释,所以就这样吧。我有人在我的网站上创建了一个幻灯片菜单,我也使用 jplayer 音乐播放器。 现在一切正常,直到我在顶部添加此脚本。由于某种原
我已经在 Ubuntu 上安装了 android studio,有一个带有损坏图像的 API,我也尝试过重新安装。我应该怎么做才能克服这个问题。 删除它后,它没有在 sdk 管理器中显示 提前致谢。
假设我的站点上有大约 10 个 css 文件。我想把它们合二为一。但是当我组合它们时(只是“连接”文件,以便将它们包含到 html 中),我的样式/布局中断了。这不是路径问题或其他问题,只是选择器无法
我是一名优秀的程序员,十分优秀!