- 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/
每个讨论:On active slide, append input 虽然我还没有弄清楚这一点,但我感觉很接近。我只是被难住了。代码看起来是正确的..但我仍然收到错误。特别是“slider.ev.on
关闭。这个问题是off-topic .它目前不接受答案。 想改进这个问题吗? Update the question所以它是on-topic用于堆栈溢出。 关闭 11 年前。 Improve th
我正在努力实现双指缩放代码。 我只是检查了 WinJS 语义缩放实现并找到了有趣的代码片段。 适用于 JavaScript 1.0/js/ui.js 的 Windows 库 行号:30710、3072
自 2 月起,GlobalSign 只颁发 EV 代码签名证书。这意味着代码签名必须使用硬件 token (Safenet USB eTokens) 完成。 自从我不得不切换到 EV 代码签名后,我注
我最近在我的网站上安装了 EV SSL 证书,它是从 GlobalSign 购买的。我关注了https://www.globalsign.com/support/install/install_apa
我有两个包含(唯一)字符串的文件:第一个是 1.txt,有大约 1000,000 个唯一字符串,而 2.txt 有大约 10,000 个唯一字符串。我想删除 1.txt 中所有出现的 2.txt 字符
当我尝试通过 ev.preventDefault() 使用对象解构时,我在 Chrome 中收到以下错误: 未捕获的类型错误:非法调用 但是,当我使用 ev.preventDefault() 而不进行
在redis Async Context中,定义了struct ev: struct { void *data; void (*addRead)(void *privdata);
明日方舟SW-EV-4通关攻略 1.左侧单先锋开,上医疗朝右,右侧补上先锋,由于关卡的敌人魔抗比较高,中间靠下补上单体狙,中间靠上补上群狙,一律朝下,右侧补上医疗先锋换重装 2.接下来是背板,6
明日方舟SW-EV-3通关攻略 1.双先锋开,草丛补上狙击术士朝左,医疗朝右即可 2.8杀之后上路会有雷达兵,能照出你草丛的角色,同时也会刷一些术士,如果不想高台被打就下工具人切雷达兵,或者先锋
1、首先是要用练度最高的狙击挡门口(蓝毒最好精2一级 没有的话就精1六十级加一个强一点的单奶) 2、之后2个单法和一个辅助(最好用史都华德、紫兰、阿米驴)主打后面的飞机 3、等到飞机打完了,大锤
问题描述 明日方舟SW-EV-5突袭怎么通关 精选答案 1、开局先放蓝毒在右侧清兵 2、等左边大锤哥走过临光的位置,确保不会拉到仇恨,下临光 3、等费用能下小羊时,下小羊 4、等费用能下
当我有这样的事情时 ".mylabel click": function (el,ev){ //mycode in here } el 是什么意思? ev 是什么意思? 我尝试在 canjs 中搜索它
我的公司从赛门铁克购买了 EV 证书,用于我们生产的软件产品。具体称为:Symantec Class 3 Extended Validation Code Signing CA – G2。 我们使用
我有一个这样创建的文件句柄对象(为清楚起见略作编辑): sub TIEHANDLE { return $_[0] if ref($_[0]); my $class = shift;
使用 preventDefault 停止点击“a”标签以滚动回页面顶部。另一方面,如果我在 jQuery 中编码了 .preventDefault(),我的“a”标签将得不到任何响应。也许你们可以提供
我目前在一个小型网站上工作。为了让它看起来更合法和专业,我想在浏览栏(EV SSL 证书)中有一个带有我名字的绿色锁。为普通和 EV SSL 证书创建 2 个 .pem 文件。问题是:我不知道如何继续
我最近从 comodosslstore.com 为我的站点购买了 EV ssl 证书,该站点托管在 GCP 上并从 bluehost 购买了域,但现在我在验证我的身份时遇到了一些问题,并且在我的 ss
关闭。这个问题是off-topic .它目前不接受答案。 想改进这个问题吗? Update the question所以它是on-topic用于堆栈溢出。 关闭 10 年前。 Improve thi
考虑以下示例代码,它使用 TrustManager 记录传出连接是否使用了有效证书(但在所有情况下都接受连接): import java.security.*; import java.securit
我是一名优秀的程序员,十分优秀!