历史上的今天
今天是:2024年10月14日(星期一)
2018年10月14日 | Tiny4412中断控制器(GIC)之SGI软中断
2018-10-14 来源:eefocus
//对于多核可以参考三星官方提供的linux源码,uboot中只是用了单核。
//下面代码只是用一个cpu核,采用SGI中断方式自己发自己收。
#include "regs.h"
void enable_mmu(unsigned long ttb);
void init_ttb(unsigned long *ttb_base);
void mmap(unsigned long *ttb_base, unsigned long va, unsigned long pa);
void memset(char *buf, char ch, int size);
void memcpy(char *dst, char *src, int size);
void do_irq(unsigned long regs[]);
void (*printf)(char *, ...) = 0x43e11434;
void main(void)
{
unsigned long vector_base = 0xffff0000;
unsigned long tt_base = 0x73000000;
unsigned long *pdo_irq = 0x75000000;
extern unsigned long vectors_start, vectors_end;
memset(tt_base, 0x00, 16 * 1024);
mmap(tt_base, vector_base, 0x70000000);
enable_mmu(tt_base);
memcpy(vector_base, vectors_start, 0x100);
*pdo_irq = do_irq;
//让cpu开中断,cpu可以接收中断,要关闭cpu的中断用cpsid
//一条指令就可以完成对特殊功能寄存器的写操作,以前代码:
//mrs r0,cpsr
//bic r0,r0,#0x80 //清掉最高位
//msr cpsr,r0
__asm__ __volatile__ (
"cpsie i\n"
);
//---------------------------------比较通用的部分------------------------------
//使能中断信号,GIC可以给cpu发送中断,只用了cpu0
ICCICR_CPU0 = 1;
//门限寄存器,设置优先级,低于0xff的中断就不送了,Priority Unmask All Interrupt
//0xff最低,0最高,所有中断都想发送故设置为0xff,任何有一个优先级都比0xff高
ICCPMR_CPU0 = 0xff;
ICDDCR = 1; // 外设中断启不启用,把已经发生的外设中断转发给cpu,SGI软中断用不到
// 设置优先级,每个中断号占8位,0号中断对应ICDIPR0寄存器,the Zero is Highest priority
ICDIPR0_CPU0 = 0;
// 外设中断发生时发给哪个cpu,ARM最高支持8核,占该寄存器8位,也就是该寄存器中每个中断号占8位,
//0号中断就在ICDIPTR0寄存器当中,
// 如果给cpu0、cpu3两个发既要在ICDIPTR0_CPU0上写上也要在ICDIPTR0_CPU3上写入
//一个核对应一位,for CPU0, refer PG815
ICDIPTR0_CPU0 = 1;
// enable interrupt 0 --- SGI0 ,每个中断号占一位,0号中断在ICDISER0当中
ICDISER0_CPU0 = 1;
//--------------------------------------------------------------------------------
//使能SGI
//bit[0:3]:发送的中断号,0-3共4位一共可以发16个中断
//bit[16:23]:SGI软中断发生时要发给哪个cpu,8位,一核对应一位,最多8核
//bit[24:25]:01表示发送给ICDIPTR0_CPU0指定的cpu
// 00表示发送给bit[16:23]中指定的cpu
ICDSGIR = 0 | ( 1 << 16) | ( 0 << 24); // send SGI 0,不同的中断这部分不同
printf("send sgi.\n");
}
void do_irq(unsigned long regs[])
{
unsigned long vectorNum;
printf(" sgi 0.000\n");
//每个cpu都有一个对应的寄存器
//bit[9:0]:INTERRUPT_ID,中断的ID
//bit[12:10]:CPUID,表示谁发的,值是几就是几号cpu发的,不是位对应的关系
vectorNum = ICCIAR_CPU0;
unsigned cpu = (vectorNum >> 10) & 0x7;//CPU的ID
unsigned irq = vectorNum & 0x1FF; //中断号
printf(" SGI, irq: %d, cpu: %d\n", irq, cpu);
//SGI的清中断方式:清除中断号、cpu的ID(0号cpu不用清),不同的中断这部分不同
ICCEOIR_CPU0 = irq;
}
void enable_mmu(unsigned long ttb)
{
unsigned long c1_flags;
init_ttb(ttb);
c1_flags = 1 | (1 << 3) | ( 1 << 11) | ( 1 << 13) | (1 << 28);
__asm__ __volatile__ (
"mvn r0, #0 \n"
"mcr p15, 0, r0, c3, c0, 0\n"
"mcr p15, 0, %1, c2, c0, 0\n" //configure ttb
"mrc p15, 0, r0, c1, c0, 0\n"
"orr %0, r0, %0\n"
"mcr p15, 0, %0, c1, c0, 0\n" //enable mmu
:
: "r" (c1_flags), "r" (ttb)
: "r0"
);
}
void init_ttb(unsigned long *ttb_base)
{
unsigned long va, pa;
for (va = 0x00000000; va < 0x10000000; va += 0x100000) { //Others
pa = va;
ttb_base[ va >> 20] = (pa & 0xfff00000) | 2;
}
for (va = 0x10000000; va < 0x14000000; va += 0x100000) { //SFR
pa = va;
ttb_base[ va >> 20] = (pa & 0xfff00000) | 2;
}
for (va = 0x40000000; va < 0x80000000; va += 0x100000) { //DRAM
pa = va;
ttb_base[ va >> 20] = (pa & 0xfff00000) | 2;
}
}
void mmap(unsigned long *ttb_base, unsigned long va, unsigned long pa)
{
ttb_base[ va >> 20] = (pa & 0xfff00000) | 2;
}
void memset(char *buf, char ch, int size)
{
int i;
for (i = 0; i < size; i ++)
buf[i] = ch;
}
void memcpy(char *dst, char *src, int size)
{
int i;
for (i = 0; i < size; i ++)
dst[i] = src[i];
}
__asm__ (
"vectors:\n"
"b reset\n"
"b und\n"
"b swi\n"
"b pre_abt\n"
"b dat_abt\n"
".word 0\n"
"b irq\n"
"b fiq\n"
"reset:\n"
"und:\n"
"mov sp, #0x74000000\n"
"stmfd sp!, {r0-r12, lr}\n"
"mov r0, sp\n"
"mov r3, #0x74000000\n"
"ldr r3, [r3]\n"
"blx r3\n"
"mov sp, #0x74000000\n"
"ldmea sp, {r0-r12, pc}^\n"
"swi:\n"
"pre_abt:\n"
"dat_abt:\n"
"fiq:\n"
"irq:\n"
"mov sp, #0x75000000\n"
"sub lr, lr, #4 \n"
"stmfd sp!, {r0-r12, lr}\n"
"mov r0, sp\n"
"mov r3, #0x75000000\n"
"ldr r3, [r3]\n"
"blx r3\n"
"mov sp, #0x75000000\n"
"ldmea sp, {r0-r12, pc}^\n"
"EOV:\n"
"vectors_start:\n"
".word vectors\n"
"vectors_end:\n"
".word EOV\n"
);
===================================================================
Makefile文件:
default:
arm-linux-gcc -c test.c -o test.o
arm-linux-ld -Ttext=0x70003000 test.o -o test
arm-linux-objcopy -O binary test test.bin
clean:
rm -f test.o test test.bin *~
===================================================================
烧写测试参考:“Tiny4412从SD卡启动u-boot用linux的DNW烧写裸板程序”
tiny4412中断处理:
1、4412的中断和cortex-A8、arm11等大不一样,4412采用GIC中断控制器,在ARM公司的编号是PL390,GIC中断控制器由ARM公司统一提供,这样代码方便移植、通用。
2、因为cortex-A9是4核的处理器,产生一个中断以后该怎么分配?让哪一个核处理?
为了解决这个问题把中断分为3种类型:
①SPI:共享外设中断,该类中断4个核都可以处理;
②PPI:私有外设中断,只能送给指定的核;
③SGI:swi软中断异常用来完成系统调用,SGI软中断用来实现cpu核之间的通信,这个核发送SGI中断另外一个核来接收;
SPI、PPI、SGI在系统中都是统一编号的,从0-1019号,一共1020个中断,每个中断都分配一个号码,这个号码是唯一的,三星公司把GIC通用中断控制器集成进去的时候号码就确定了,可以查看芯片手册的“GIC Interrupt Table”表格中的ID号码,其中:
0-15号给SGI用的;
16-31号给PPI用的;
32-159剩下的都是SPI中断,一共一千多个,用组合器组合起来,号码只到159;
cpu有4个核,以上0-159是对应一个核的。
中断涉及到两类寄存器:ICC、ICD。ICC针对的是全局整体中断的配置,比如整个机器上的中断要不要开、优先级、哪个中断发生这些;ICD针对的是某一个中断,比如中断时高电平、低电平触发这类。
史海拾趣
|
北京时间9月1日消息 据国外媒体报道,谷歌CEO埃里克·施密特在接受彭博电视台采访时称,希望美国政府能批准谷歌与雅虎的合作]计划,使该计划能在今年10月开始实施。 据彭博电视台在科罗拉多州丹佛市进行的一次采访,美国政府正在审查两家公司的网 ...… 查看全部问答> |
|
我了解事物喜欢从底层根本去了解,而不是你说什么我照做就行了,我会形成一些探寻究竟的念头,也会产生很多疑问。 讨论之前当然要先看过某厂的datasheet,我看的是Micron。 按上面说,terminate和precharge都能掐断burst读或写。我也是第一次用Sd ...… 查看全部问答> |
|
对于计算机专业的人来说,英语四级很重要吗?现在很忙,根本顾及不了英语,而老师也把它说得很重要。当然,我忙是因为自己的专业,而不是去浪费时间。 对于已经在社会工作的前辈们,你们认为英语四级重要吗? & ...… 查看全部问答> |
|
在DownloadImage函数中,有如下的一段代码,我搞不明白这里为什么给地址赋的是接收长度,而不是地址呢? if (*(UINT32 *)(pCurDownloadFile->dwRegionStart + ROM_SIGNATURE_OFFSET) == ROM_SIGN ...… 查看全部问答> |
|
在stm8s_conf.h中有如下语句: /* Includes ------------------------------------------------------------------*/ #include "stm8s.h" 在stm8s.h中有如下语句: #ifdef USE_STDPERIPH_DRIVER #include "stm8s_conf.h" #endi ...… 查看全部问答> |
|
定时器A模拟串口发送时,DEMO里有这么一句: if (RXTXData & 0x01) //判断最低位是否为1 CCTL0 &= ~ OUTMO ...… 查看全部问答> |




