历史上的今天
返回首页

历史上的今天

今天是:2024年10月11日(星期五)

正在发生

2018年10月11日 | OK6410裸机之串口发送中断

2018-10-11 来源:eefocus

start.S源码:

.globl _start

_start:

    // 0 地址 

    b reset                                                 // 复位时,cpu跳到0地址 

    ldr pc, =undefined_instruction         // cpu遇到不能识别的指令时 

    ldr pc, _vector_swi                              // 当执行swi指令时, 进入swi模 式 

    b halt     @ldr    pc, _prefetch_abort // 预取中止异常 

    b halt     @ldr    pc, _data_abort       // 数据访问异常 

    b halt     @ldr    pc, _not_used          // 没用到 

    ldr    pc, _irq                                       // 0x18 中断异常 

    b halt     @ldr    pc, _fiq                     // 快中断异常 

_irq :

    .word vector_irq

_vector_swi:

    .word vector_swi

        

vector_swi:

    // 1. 保存现场 

    ldr sp, =0x56000000

    stmdb sp!, {r0-r12, lr}  // lr就是swi的下一条指令地址 

    // 2. 处理异常 

    mrs r0, cpsr

    ldr r1, =swi_str

    bl print_cpsr

    // 3. 恢复现场 

    ldmia sp!, {r0-r12, pc}^ // ^表示把spsr恢复到cpsr 

    

swi_str:

    .word 0x00697773        // swi 

    

undefined_instruction:

    // 1. 保存现场 

    ldr sp, =0x55000000

    stmdb sp!, {r0-r12, lr}

    // 2. 处理异常 

    mrs r0, cpsr

    ldr r1, =und_str

    bl print_cpsr

    // 3. 恢复现场 

    ldmia sp!, {r0-r12, pc}^  // ^表示把spsr恢复到cpsr 

und_str:

    .word 0x00646e75          // und 

usr_str:

    .word 0x00727375          // usr 

vector_irq:

    // 1. 保存现场 

    ldr sp, =0x54000000

    sub lr, lr, #4

    stmdb sp!, {r0-r12, lr}     // lr就是swi的下一条指令地址 

    // 2. 处理异常 

    bl do_irq

    

    // 3. 恢复现场 

    ldmia sp!, {r0-r12, pc}^  // ^表示把spsr恢复到cpsr 

reset:

// 硬件相关的设置 

    // Peri port setup 

    ldr r0, =0x70000000

    orr r0, r0, #0x13

    mcr p15,0,r0,c15,c2,4       @ 256M(0x70000000-0x7fffffff)

    

// 关看门狗 

// 往WTCON(0x7E004000)写0 

    

    ldr r0, =0x7E004000

    mov r1, #0

    str r1, [r0]

    

    // 设置栈 

    ldr sp, =8*1024

    // 设置时钟 

    bl clock_init

    bl ddr_init

    bl init_uart

    //把片内内存中程序的代码段、数据段复制到它的链接地址去   

    adr r0, _start            // 获得_start指令当前所在的地址 : 0

    ldr r1, =_start           // _start的链接地址 0x51000000 

    

    ldr r2, =bss_start      // bss段的起始链接地址 

    

    sub r2, r2, r1

    

    cmp r0,r1

    beq clean_bss

    

    bl copy2ddr

    cmp r0, #0

    bne halt

        

// 清BSS 

// 把BSS段对应的内存清零 

clean_bss:

    ldr r0, =bss_start

    ldr r1, =bss_end

    mov r3, #0

    cmp r0, r1

    ldreq pc, =on_ddr

clean_loop:

    str r3, [r0], #4

    cmp r0, r1    

    bne clean_loop        

    ldr pc, =on_ddr

on_ddr:    

    bl irq_init

    mrs r0, cpsr

    bic    r0,r0,#0x9f  // 清cpsr的I位,M4~M0 

    orr    r0,r0,#0x10

    msr    cpsr,r0       // 进入user mode 

    ldr sp, =0x57000000

    ldr r1, =usr_str

    bl print_cpsr

    

    swi 0

    // cpu进入svc模式

    // 把之前的cpsr保存到spsr_svc 

    // 切换到r13_svc, r14_svc

    // 把swi的下一条指令存到r14(lr)_svc

    // 跳到地址8

              

    bl hello

undef:

    .word 0xff000000

    // cpu进入Undefined模式

    // 把之前的cpsr保存到spsr_und 

    // 切换到r13_und, r14_und

    // 把下一条指令存到r14(lr)_und

    // 跳到地址4               

    

swi_ret:

    bl main

halt:

    b halt    

=====================================================================

irq.c源码:

#define GPNCON     (*((volatile unsigned long *)0x7F008830))

#define GPNDAT     (*((volatile unsigned long *)0x7F008834))

#define EINT0CON0  (*((volatile unsigned long *)0x7F008900))

#define EINT0MASK  (*((volatile unsigned long *)0x7F008920))

#define EINT0PEND  (*((volatile unsigned long *)0x7F008924))

#define PRIORITY    (*((volatile unsigned long *)0x7F008280))

#define SERVICE     (*((volatile unsigned long *)0x7F008284))

#define SERVICEPEND (*((volatile unsigned long *)0x7F008288))

#define VIC0IRQSTATUS  (*((volatile unsigned long *)0x71200000))

#define VIC0FIQSTATUS  (*((volatile unsigned long *)0x71200004))

#define VIC0RAWINTR    (*((volatile unsigned long *)0x71200008))

#define VIC0INTSELECT  (*((volatile unsigned long *)0x7120000c))

#define VIC0INTENABLE  (*((volatile unsigned long *)0x71200010))

#define VIC0INTENCLEAR (*((volatile unsigned long *)0x71200014))

#define VIC0PROTECTION (*((volatile unsigned long *)0x71200020))

#define VIC0SWPRIORITYMASK (*((volatile unsigned long *)0x71200024))

#define VIC0PRIORITYDAISY  (*((volatile unsigned long *)0x71200028))

#define VIC0VECTADDR0      (*((volatile unsigned long *)0x71200100))

#define VIC0VECTADDR1      (*((volatile unsigned long *)0x71200104))

#define VIC0ADDRESS        (*((volatile unsigned long *)0x71200f00))

#define VIC1IRQSTATUS      (*((volatile unsigned long *)0x71300000))

#define VIC1VECTADDR5      (*((volatile unsigned long *)0x71300114))

#define VIC1INTENABLE      (*((volatile unsigned long *)0x71300010))

#define VIC1ADDRESS        (*((volatile unsigned long *)0x71300f00))

void eint0_3_irq(void)

{

    int i;

    

    printf("eint0_3_irq\n\r");  // K1~K4 

    for (i = 0; i < 4; i ++)

    {

        if (EINT0PEND & (1<

        {

            if (GPNDAT & (1<

            {

                printf("K%d released\n\r", i+1);

            }

            else

            {

                printf("K%d pressed\n\r", i+1);

            }

        }

    }

}

void eint4_11_irq(void)

{

    int i;

    printf("eint4_11_irq\n\r"); // K5~K6 

    for (i = 4; i < 6; i ++)

    {

        if (EINT0PEND & (1<

        {

            if (GPNDAT & (1<

            {

                printf("K%d released\n\r", i+1);

            }

            else

            {

                printf("K%d pressed\n\r", i+1);

            }

        }

    }

}

void irq_init(void)

{

    key_irq_init();

    uart_irq_init();

}

void uart_irq(void)

{

    // 调用具体的中断处理函数 

    do_uart_irq();

    // 清中断 

    VIC1ADDRESS = 0;

}

void uart_irq_init(void)

{

    VIC1INTENABLE |= (1<<5); // bit5: int_uart0  

    VIC1VECTADDR5 = uart_irq;

}

void key_irq_init(void)

{

    // 配置GPIO引脚为中断引脚 

    // GPN0~5 设为中断引脚 

    GPNCON &= ~(0xfff);

    GPNCON |= 0xaaa;

    // 设置中断触发方式为: 双边沿触发 

    EINT0CON0 &= ~(0xfff);

    EINT0CON0 |= 0x777;

    // 使能中断 

    EINT0MASK &= ~(0x3f);

    // 在中断控制器里使能这些中断 

    VIC0INTENABLE |= (0x3); // bit0: eint0~3, bit1: eint4~11  

    VIC0VECTADDR0 = eint0_3_irq;

    VIC0VECTADDR1 = eint4_11_irq;

    // 设置优先级 

}

void do_irq(void)

{

    int i = 0;

    void (*the_isr)(void);

    if (VIC0IRQSTATUS)

    {

        the_isr = VIC0ADDRESS;

            

        // 2.1 分辨是哪个中断 

        // 2.2 调用它的处理函数     

        // 2.3 清中断     

        the_isr();

        

        EINT0PEND   = 0x3f;  // 清中断 

        VIC0ADDRESS = 0;

    }

    else if (VIC1IRQSTATUS)

    {

        the_isr = VIC1ADDRESS;

            

        // 2.1 分辨是哪个中断 

        // 2.2 调用它的处理函数     

        // 2.3 清中断     

        the_isr();

    }

}

===================================================================

uart.c源码:

#define ULCON0     (*((volatile unsigned long *)0x7F005000))

#define UCON0      (*((volatile unsigned long *)0x7F005004))

#define UFCON0     (*((volatile unsigned long *)0x7F005008))

#define UMCON0     (*((volatile unsigned long *)0x7F00500C))

#define UTRSTAT0   (*((volatile unsigned long *)0x7F005010))

#define UFSTAT0    (*((volatile unsigned long *)0x7F005018))

#define UTXH0      (*((volatile unsigned char *)0x7F005020))

#define URXH0      (*((volatile unsigned char *)0x7F005024))

#define UBRDIV0    (*((volatile unsigned short *)0x7F005028))

#define UDIVSLOT0  (*((volatile unsigned short *)0x7F00502C))

#define UINTP0     (*((volatile unsigned long *)0x7F005030))

#define UINTM0     (*((volatile unsigned long *)0x7F005038))

#define GPACON     (*((volatile unsigned long *)0x7F008000))

#define ENABLE_FIFO 1

static delay(void)

{

    volatile int i = 10;

    while (i--);

}

void uart_tx_int_enable(void)

{

    UINTM0 &= ~(1<<2);    

}

void uart_tx_int_disable(void)

{

    UINTM0 |= (1<<2);    

}

void init_uart(void)

{

    GPACON &= ~0xff;

    GPACON |= 0x22;

    

    // ULCON0 

    ULCON0 = 0x3;                 // 数据位:8, 无较验, 停止位: 1, 8n1 

    UCON0  = 0x5 | (1<<9);   // 使能UART发送、接收, tx interrupt request type = level 

#ifdef ENABLE_FIFO

    UFCON0 = 0x07 | (1<<6); // FIFO enable, tx fifo trigger level = 16 bytes     

#else

    UFCON0 = 0x00;               // FIFO disable 

#endif

    UMCON0 = 0;

    

    // 波特率 

    // DIV_VAL = (PCLK / (bps x 16 ) ) - 1 

    // bps = 57600

    // DIV_VAL = (66500000 / (115200 x 16 ) ) - 1 

    //         = 35.08

     

    UBRDIV0   = 35;

    // x/16 = 0.08

    // x = 1

     

    UDIVSLOT0 = 0x1;

}

unsigned char getc(void)

{

#ifdef ENABLE_FIFO

    while ((UFSTAT0 & 0x7f) == 0)delay();

#else    

    while ((UTRSTAT0 & (1<<0)) == 0);

#endif

    

    return URXH0;

}

int getc_nowait(unsigned char *pChar)

{

#ifdef ENABLE_FIFO

    if ((UFSTAT0 & 0x7f) == 0)

#else

    if ((UTRSTAT0 & (1<<0)) == 0)

#endif        

    {

        return -1;

    }

    else

    {    

        *pChar = URXH0;

        return 0;

    }

}

#define TX_BUF_LEN   2048

static unsigned char txbuf[2047];

static unsigned int r_idx = 0;

static unsigned int w_idx = 0;

static int isFull(void)

{

    if ((w_idx + 1) % TX_BUF_LEN == r_idx)

        return 1;

    else

        return 0;

}

static int isEmpty(void)

{

    return (w_idx == r_idx);

}

static int putData(unsigned char data)

{

    if (isFull())

        return -1;

    else

    {

        txbuf[w_idx] = data;

        w_idx = (w_idx + 1) % TX_BUF_LEN;

        return 0;

    }

}

static int getData(unsigned char *pdata)

{

    if (isEmpty())

    {

        return -1;

    }

    else

    {

        *pdata = txbuf[r_idx];

        r_idx = (r_idx + 1) % TX_BUF_LEN;

        return 0;

    }

}

void putc(char c)

{

    putData(c);    // 把数据放到缓冲区里去 

    // 如果"uart 发送中断"未使能的话,使能"uart 发送中断" 

    uart_tx_int_enable();

}

void do_uart_irq(void)

{

    int i;

    int cnt;

    unsigned char c;

    

    if (UINTP0 & (1<<2))

    {

        // 对于发送中断 

         if (isEmpty())

         {

             // 禁止中断 

            uart_tx_int_disable();

         }

         else

         {

             // 从环型缓冲区里取出数据, 放到TX FIFO里去 

            cnt = (UFSTAT0 >> 8) & 0x3f;

            cnt = 64 - cnt;

            for (i = 0; i < cnt; i++)

            {

                if (getData(&c) == 0)

                {

                    UTXH0 = c;

                }

                else

                {

                    break;

                }

            }

         }

    }

    else if (UINTP0 & (1<<0))

    {

        // 对于接收中断, 从RX FIFO里取出数据 

    }

    // 清中断 

    UINTP0 = 0xf;

}

====================================================================

Makefile文件:

CC      = arm-linux-gcc

LD      = arm-linux-ld

AR      = arm-linux-ar

OBJCOPY = arm-linux-objcopy

OBJDUMP = arm-linux-objdump

INCLUDEDIR     := $(shell pwd)/include

CFLAGS             := -Wall -Os -fno-builtin-printf  -fno-builtin-putc   //避免putc函数名冲突

CPPFLAGS        := -nostdinc -I$(INCLUDEDIR)

export     CC AR LD OBJCOPY OBJDUMP INCLUDEDIR CFLAGS CPPFLAGS 

objs := start.o sdram.o nand.o clock.o uart.o irq.o  main.o lib/libc.a

uart.bin: $(objs)

    ${LD} -Tuart.lds -o uart.elf $^

    ${OBJCOPY} -O binary -S uart.elf $@

    ${OBJDUMP} -D uart.elf > uart.dis

.PHONY : lib/libc.a

lib/libc.a:

    cd lib; make; cd ..

    

%.o:%.c

    ${CC} $(CPPFLAGS) $(CFLAGS) -c -o $@ $<

%.o:%.S

    ${CC} $(CPPFLAGS) $(CFLAGS) -c -o $@ $<

clean:

    make  clean -C lib

    rm -f uart.bin uart.elf uart.dis *.o

    

=====================================================================

uart.lds链接文件:

SECTIONS {

    . = 0x50000000;

    

    .text : {

            start.o

            clock.o

            sdram.o

            nand.o

            * (.text)

    }

    . = ALIGN(4);

    .rodata : {

            * (.rodata)

    }

    . = ALIGN(4);

    .data : {

            * (.data)

    }

    . = ALIGN(4);

    bss_start = .;

    .bss  : { *(.bss)  *(COMMON) }

    bss_end = .;

}


推荐阅读

史海拾趣

正泰公司的发展小趣事

随着工业4.0时代的到来,正泰公司积极推进智能制造转型。以海宁工厂为例,正泰通过引入自动化生产线和信息化管理系统,提高了生产效率和产品质量。同时,公司还加大了对智能制造技术的研发和应用力度,推动生产过程的数字化、网络化、智能化。这一转型不仅提升了公司的生产效率和市场竞争力,也为公司的未来发展奠定了坚实的基础。

以上五个故事只是正泰公司发展过程中的冰山一角,但它们充分展示了正泰公司在电子行业中不断创新、追求卓越的精神风貌和坚定决心。

ABLIC公司的发展小趣事

2020年4月,ABLIC成为MinebeaMitsumi集团的一员。这一合作对于ABLIC来说具有重要意义。MinebeaMitsumi集团作为一家在电子元器件领域具有强大实力的企业,为ABLIC提供了更广阔的发展空间和资源支持。通过融入MinebeaMitsumi集团的“八矛战略”,ABLIC的模拟半导体业务得到了进一步提升,其在集团内部的地位也愈发重要。

BVLED公司的发展小趣事

随着市场的不断变化和竞争的加剧,BVLED公司意识到只有不断创新才能在行业中立足。于是,公司加大了对研发的投入,引进了一批高素质的研发人才,并与多家高校和研究机构建立了合作关系。通过不断的实验和改进,公司成功推出了一系列具有创新性的LED产品,如智能调光LED灯、高显色指数LED灯等,这些产品在市场上获得了广泛的认可。

Digital公司的发展小趣事

DIALIGHT公司的故事始于1938年的纽约布鲁克林,当时该公司专注于为飞机生产仪表板灯。随着技术的不断进步和市场的变化,公司在1971年,即LED推出仅一年后,推出了他们的第一个LED产品。这一举措标志着DIALIGHT正式从传统的飞机仪表板灯制造转向LED照明技术的研发和应用。从此,DIALIGHT彻底改变了LED的用途,将其广泛应用于世界各地的交通控制、指示灯、结构塔和工业场所,为全球提供了优质的照明解决方案。

Block USA Inc.公司的发展小趣事

在支付与金融服务领域取得成功后,Block USA Inc.还尝试了跨界合作,推出了音乐软件TIDAL。这一举措旨在通过提供高品质的音乐体验,吸引更多年轻用户群体,并进一步扩大Block的品牌影响力。虽然音乐市场竞争激烈,但TIDAL凭借其独特的音乐资源和用户体验,逐渐在市场中占据了一席之地。

Circuit Technology Inc公司的发展小趣事

Circuit Technology Inc(以下简称CTI)自创立之初,便致力于电路技术的研发与创新。在成立初期,公司凭借其独特的电路设计技术,成功开发出一款高效能、低成本的电路板,迅速在行业内崭露头角。随着技术的不断完善和市场的逐步认可,CTI的产品逐渐占据了市场份额,公司规模也逐渐扩大。为了进一步拓展市场,CTI积极与国内外知名企业合作,共同开发新产品,不断提升自身的技术水平和市场竞争力。

问答坊 | AI 解惑

IQMath中文手册.rar

IQMath中文手册.rar…

查看全部问答>

WINCE 中断处理的迷惑

我用的是sangsun2440,号称是WINCE5.0 BSP的开发板.现因处理一按键(对应EINT19)中断.陷入迷惑. BSP里面的OEMinit函数如下: void OEMInit()   {         volatile IOPreg *s2440IOP = (IOPreg *)IOP_BASE;   ...…

查看全部问答>

版主主120MHz的STM32出来没有?

                                 如题…

查看全部问答>

Writing outside flash memory at address 0x0

不能下载程序, 在flash地址0X00处出错, Debug log win 提示错误: Writing outside flash memory at address 0x0,    什么原因呢 ?…

查看全部问答>

在wince上开发程序用ppb 超简单

在wince上开发程序用ppb 超简单   ppb     即  pocketbuilder........................., 可以满足 第一:本地存放数据 第二:上传数据到服务器 并进行同步.....   [ 本帖最后由 nsjnc 于 2012-2-25 23:11 编 ...…

查看全部问答>

求解

本帖最后由 dontium 于 2015-1-23 13:10 编辑 介绍一下模拟电路吧 …

查看全部问答>

怎么控制一般电容的充电电流

请教大家一个问题,怎么控制一般电容的充电电流,可不可以快充呢?…

查看全部问答>

led点阵程序求教 万分感谢 请赐教

#include unsigned char code tab[]={0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe}; unsigned char code digittab[10][8]={{0x00,0x00,0x3e,0x41,0x41,0x41,0x3e,0x00}, //0 {0x00,0x00,0x00,0x00,0x21,0x7f,0x01,0x00}, //1 {0x00,0x00,0x27,0x ...…

查看全部问答>

征求 sqlite + fatfs + raw-os 在VC环境上的移植。

目前raw-os + fatfs 的vc环境已经搭建也能正常运行。sqlite 的vc环境也能运行,但是是基于windows的文件系统的。现在需要把sqlite剥离windows的文件系统,采用开源的fatfs文件系统运行。 现征求开源志士,完成这一个利民项目。有意向的请联系本人 ...…

查看全部问答>