历史上的今天
返回首页

历史上的今天

今天是: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针对的是某一个中断,比如中断时高电平、低电平触发这类。


推荐阅读

史海拾趣

Cornell Dubilier公司的发展小趣事

Cornell Dubilier公司的历史可以追溯到1909年,当时公司创始人William Dubilier凭借其开创性的云母电容器技术,为无线电广播通信带来了革命性的改变。这项技术的突破,使得Cornell Dubilier公司在早期电子行业中崭露头角。随后的几十年里,公司逐渐扩大生产规模,增加产品线,并开始涉足其他电子元件和组件的制造。

上海国芯(Gcore)公司的发展小趣事
根据应用场景选择合适的报警装置,如蜂鸣器、LED灯或继电器等。
Apx-Crystal公司的发展小趣事

作为一家有社会责任感的企业,Apx-Crystal公司始终将可持续发展作为企业的核心价值观之一。公司积极履行社会责任,关注环境保护和公益事业。在生产过程中,公司采用环保材料和节能技术,降低能耗和排放;在员工福利方面,公司注重员工培训和职业发展,为员工提供良好的工作环境和福利待遇;在社会公益方面,公司积极参与捐资助学、扶贫济困等公益活动,回馈社会。这些举措不仅提升了企业的社会形象,也为公司的长期发展奠定了坚实的基础。

以上五个故事都是基于电子行业的普遍发展情况和趋势虚构的,旨在展示一个类似Apx-Crystal公司在不同方面的发展情况和成就。请注意,这些故事并非基于真实事件或数据,因此可能与实际情况存在差异。

EWC Controls公司的发展小趣事

EWC Controls公司自成立以来,一直专注于工业自动化控制技术的研发与应用。在早期,公司凭借其独特的PID控制算法,成功开发了一系列高性能的控制器产品,赢得了市场的初步认可。随着技术的不断进步,EWC Controls公司不断投入研发资源,推出了基于物联网和大数据的智能控制系统,实现了从单一控制到智能化管理的跨越。这一创新技术不仅提升了公司的核心竞争力,也为工业自动化控制领域带来了革命性的变化。

Fagor Electrónica公司的发展小趣事

1959年,Fagor Electrónica在电子领域崭露头角,当时它还只是Ulgor, S. Coop.公司旗下的一个电子部门。这一年,公司开始制造硒板和整流器,这标志着其电子制造业务的开始。尽管初始规模不大,但Fagor Electrónica凭借其高质量的产品和卓越的客户服务,迅速在市场上赢得了声誉。

AMOTECH(阿莫泰克)公司的发展小趣事

在多年的发展中,AMOTECH始终坚持以技术创新为核心竞争力。除了压敏电阻技术的突破外,公司还在多个领域取得了显著成果。例如,在LED照明和传感器领域,AMOTECH通过不断研发和创新,成功在韩国安山建立了第四工厂,进一步提升了公司的技术实力和产能规模。这些技术的不断突破和创新,使得AMOTECH在电子行业中始终保持领先地位。

问答坊 | AI 解惑

谷歌CEO施密特:与雅虎合作计划有望10月落实

北京时间9月1日消息 据国外媒体报道,谷歌CEO埃里克·施密特在接受彭博电视台采访时称,希望美国政府能批准谷歌与雅虎的合作]计划,使该计划能在今年10月开始实施。 据彭博电视台在科罗拉多州丹佛市进行的一次采访,美国政府正在审查两家公司的网 ...…

查看全部问答>

我对SDRAM的深入理解

我了解事物喜欢从底层根本去了解,而不是你说什么我照做就行了,我会形成一些探寻究竟的念头,也会产生很多疑问。 讨论之前当然要先看过某厂的datasheet,我看的是Micron。 按上面说,terminate和precharge都能掐断burst读或写。我也是第一次用Sd ...…

查看全部问答>

有经验者进来说说吧!英语四级很重要吗?

    对于计算机专业的人来说,英语四级很重要吗?现在很忙,根本顾及不了英语,而老师也把它说得很重要。当然,我忙是因为自己的专业,而不是去浪费时间。    对于已经在社会工作的前辈们,你们认为英语四级重要吗?  & ...…

查看全部问答>

请教一个EBoot下载地址问题

在DownloadImage函数中,有如下的一段代码,我搞不明白这里为什么给地址赋的是接收长度,而不是地址呢?             if (*(UINT32 *)(pCurDownloadFile->dwRegionStart + ROM_SIGNATURE_OFFSET) == ROM_SIGN ...…

查看全部问答>

最新的STM8L选型手册手册哪有?

最新的STM8L选型手册手册哪有?…

查看全部问答>

STM8的标准库头文件包含是不是有点问题?

在stm8s_conf.h中有如下语句: /* Includes ------------------------------------------------------------------*/ #include "stm8s.h" 在stm8s.h中有如下语句: #ifdef USE_STDPERIPH_DRIVER #include "stm8s_conf.h" #endi ...…

查看全部问答>

基于51的无线多点粮仓温湿度监控系统 (初次发贴多多关照)

                                      &n ...…

查看全部问答>

430launchpad G2553 定时器A模拟串口困惑

定时器A模拟串口发送时,DEMO里有这么一句:       if (RXTXData & 0x01)                  //判断最低位是否为1       CCTL0 &= ~ OUTMO ...…

查看全部问答>