OK6410裸机之串口发送中断

发布者:TranquilSilence最新更新时间:2018-10-11 来源: eefocus关键字:OK6410  裸机  串口  发送中断 手机看文章 扫描二维码
随时随地手机看文章

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 = .;

}


关键字:OK6410  裸机  串口  发送中断 引用地址:OK6410裸机之串口发送中断

上一篇:OK6410裸机之LCD显
下一篇:OK6410裸机之中断向量控制器

推荐阅读最新更新时间:2024-03-16 16:15

UART0串口编程(三):中断方式的串口编程;用中断编写发送
一:中断方式的串口编程 1.用中断方式编写串口程序由那几部分组成 2.硬件上的支持 1 UART0 发送FIFO缓冲区 A.UART0含有1个16字节的发送FIFO缓冲区 B.U0THR是UART0发送FIFO的最高字节 C.UART的发送FIFO是一直使能的 2 UART0接收FIFO缓冲区 A. UART0含有一个16字节的接收FIFO缓冲区。 B. 软件设置接收FIFO缓冲区的触发字节。 3 中断接口:UART0的中断接口包含中断使能寄存器(U0IER)和中断标识寄存器(U0IIR)。 第一:U0IIR:提供状态码用于指示一个挂起中断的中断源和优先级。 第二:U0IER可
[单片机]
UART0<font color='red'>串口</font>编程(三):<font color='red'>中断</font>方式的<font color='red'>串口</font>编程;用<font color='red'>中断</font>编写<font color='red'>发送</font>
Ramtron 推出512Kb FRAM扩展其串口存储器产品系列
半兆位 FRAM 有 助于满足仪表应用对增 加数据存储容量的需求 世界顶尖的非易失性铁电存储器 ( FRAM) 和集成半导 体产品 供应商 Ramtron International 公司 扩展了其串口 存储器产品系列 , 推出 带有 2 线工业标准串行接口的 半兆位非易失 性 FRAM 产品 FM24C512 , 面向需要高容量的数据采集领域,如市电计量和实时配置存储服务。 Ramtron 市务副总裁 Mike Alwais 称:“ FM24C512 为我们的 256Kb FRAM 用户提供与升级路径封装兼容的器件,但其
[新品]
msp430g2553串口接收字符串_接收指令
串口接收中断函数一次只能接收一个字,接收一个字符串并存下常用方法: ①设置标志位:如在末尾加入标志位’r’,’n’;前缀+数据+后缀 ②定时判断接收数据的长度,如果在规定时间内,长度没有什么变化,证明已经接收了任意长度的字符。 下面我用设置标志位的方式实现接收字符串,并根据不同字符串执行不同的操作。 代码与仿真 串口助手收发情况 打开板子,电脑端收到 MADE BY PengChengIT. G2553 UART READY!!! E5是前缀,E6为后缀,发送7个指令,执行了7种操作(收到7种不同的字符串) 测试成功! 接收字符串例子 接收并存储字符串有很多用途,如指令常常是一组字符串;其他设备、串口助手发送的指令来控制实验
[单片机]
msp430g2553<font color='red'>串口</font>接收字符串_接收指令
STM32 IAP 串口在线升级源码详解
下面着重介绍下本人修改源代码部分,下载官方例程,本人使用的是STM32F103C8T6芯片,修改ROM空间大小0x2000, 修改宏定义 更改启动文件,更改方法:更改的文件鼠标右键弹出窗口- Options for File ‘statup_stm32f10x_md.s’… - 选中红框里的两项(‘√’第一次选中后为深黑色,再次点击为浅灰色,浅灰色时点击确认,其中的原因我也不太懂,你们可以试试) 修改堆栈地址0x8002000 至此,BootLoader修改完毕直接下载进去就可以了。 下面修改测试程序,我用STM32CUBEMAX直接配置了一个流水灯程序,修改程序: 主函数添加地址偏
[单片机]
STM32 IAP <font color='red'>串口</font>在线升级源码详解
STM32多串口共用printf打印串口数据
(1)问题描述: 多串口共用printf函数,百度到的资料大部分是建议重新写一个xx_printf(format, …)。但是使用起来还是不方便,就此问题而言加上一个判断语句便可解决。 (2)解决方法: printf函数最后调用的是int fputc(int ch, FILE *f),那么重新改写此函数便可。 (3)代码: //标志量定义 int USART_PRINTF_FLAG = 2;//默认串口2 //改写fputc int fputc(int ch, FILE *f) { if (USART_PRINTF_FLAG == 2) { while(USART_GetFlagStatus(U
[单片机]
关于51单片机使用printf进行串口调试的方法
//关于51单片机使用printf进行串口调试 //重定义代码,可以使用printf给串口发送数据 char putchar(char c) { ES=0;//关串口中断 TI=0;//清除标志位 SBUF=c;//发送数据 while(!TI);//等待数据发送 TI=0;//清除标致位 ES=1;//开串口中断 return c; }
[单片机]
stm32串口7位数据位
STM32系列单片机控制寄存器只支持8、9位数据位。如: 控制寄存器 1(USART_CR1) 位12 M: 字长 该位定义了数据字的长度,由软件对其置位和清零操作 0:1起始位,8数据位,n停止位 1:1起始位,9数据位,n停止位 然而STM32串口通信中也可使用7位数据位,如何设置? 设置7位数据位重点在于校验控制,也即是奇偶控制,发送时生成一个奇偶位,接收时进行奇偶校验,可通过设置USART_CR1寄存器上的PCE位而激活。根据M位定义的帧长度,可设置: 0:1起始位,7数据位,奇偶校验位,n停止位 以上是stm32单片机串口7位数据位的设置方法,希望对用户有所帮助。
[单片机]
AVR单片机串口操作程序
#include #include #include #include #include #define FOSC 8000000 //mcu工作时钟频率 typedef unsigned int uint16; typedef unsigned char uchar8; uchar8 DoubleIRData ={0x64,0x00,0x20,0x04,0x40,0x00,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; //双红外发射数据 取PD2作为驱动远程红外发射 //uchar8 SingleIRData ={0x60,0x00,0x04,0x00,0x
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
发布文章
设计资源 培训 开发板 精华推荐

最新单片机文章
  • 学习ARM开发(16)
    ARM有很多东西要学习,那么中断,就肯定是需要学习的东西。自从CPU引入中断以来,才真正地进入多任务系统工作,并且大大提高了工作效率。采 ...
  • 学习ARM开发(17)
    因为嵌入式系统里全部要使用中断的,那么我的S3C44B0怎么样中断流程呢?那我就需要了解整个流程了。要深入了解,最好的方法,就是去写程序 ...
  • 学习ARM开发(18)
    上一次已经了解ARM的中断处理过程,并且可以设置中断函数,那么它这样就可以工作了吗?答案是否定的。因为S3C44B0还有好几个寄存器是控制中 ...
  • 嵌入式系统调试仿真工具
    嵌入式硬件系统设计出来后就要进行调试,不管是硬件调试还是软件调试或者程序固化,都需要用到调试仿真工具。 随着处理器新品种、新 ...
  • 最近困扰在心中的一个小疑问终于解惑了~~
    最近在驱动方面一直在概念上不能很好的理解 有时候结合别人写的一点usb的例子能有点感觉,但是因为arm体系里面没有像单片机那样直接讲解引脚 ...
  • 学习ARM开发(1)
  • 学习ARM开发(2)
  • 学习ARM开发(4)
  • 学习ARM开发(6)
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved