datasheet

Tiny210裸机之按键中断

2018-10-12来源: eefocus 关键字:Tiny210裸机  按键中断

start.S源码:

.global _start

_start:

    ldr sp, =0xD0030000  // 初始化栈,因为后面要调用C函数 

    bl clock_init                // 初始化时钟 

    bl ddr_init                   // 初始化内存 

    bl nand_init                // 初始化NAND 

    ldr r0, =0x36000000   // 要拷贝到DDR中的位置 

    ldr r1, =0x0                 // 从NAND的0地址开始拷贝 

    ldr r2, =bss_start         // BSS段的开始地址 

    sub r2,r2,r0                  // 要拷贝的大小 

    bl nand_read              // 拷贝数据 

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:

    mrs  r0, cpsr

    bic    r0,r0,#0x1f  // 清M4~M0 

    orr    r0,r0,#0x12

    msr    cpsr,r0        // 进入irq 

    ldr sp, =0x3e000000    // 初始化普通中断模式的栈,指向内存 

    bl irq_init

    mrs  r0, cpsr

    bic    r0,r0,#0x9f  // 开总的中断开关,清M4~M0 

    orr    r0,r0,#0x10

    msr    cpsr,r0      // 进入user mode 

    ldr sp, =0x3f000000    // 初始化用户模式的栈,指向内存 

    ldr pc, =main

halt:

    b halt    

.global key_IRQ

key_IRQ:

    sub lr, lr, #4                   // 1.计算返回地址 

    stmdb sp!, {r0-r12, lr}  // 2.保护现场 

    // 3. 处理异常 

    bl do_irq

    

    // 4. 恢复现场 

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

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

irq.c源码:

#include "lib.h"

#define GPH2CON        (*(volatile unsigned int *)0xE0200C40)

#define GPH2DAT        (*(volatile unsigned int *)0xE0200C44)

#define GPH3CON        (*(volatile unsigned int *)0xE0200C60)

#define GPH3DAT        (*(volatile unsigned int *)0xE0200C64)

#define EXT_INT_2_CON        (*(volatile unsigned int *)0xE0200E08)

#define EXT_INT_3_CON        (*(volatile unsigned int *)0xE0200E0C)

#define EXT_INT_2_MASK        (*(volatile unsigned int *)0xE0200F08)

#define EXT_INT_3_MASK        (*(volatile unsigned int *)0xE0200F0C)

#define VIC0INTSELECT        (*(volatile unsigned int *)0xF200000C)

#define VIC0INTENABLE        (*(volatile unsigned int *)0xF2000010)

#define VIC0VECTADDR16        (*(volatile unsigned int *)0xF2000140)

#define VIC0ADDRESS          (*(volatile unsigned int *)0xF2000F00)

#define EXT_INT_2_PEND        (*(volatile unsigned int *)0xE0200F48)

#define EXT_INT_3_PEND        (*(volatile unsigned int *)0xE0200F4c)

int i = 0;

void do_irq(void)

{

    // 清中断 

    EXT_INT_2_PEND |= 1<<3;

    EXT_INT_3_PEND |= 1<<0;

    // 清中断向量 

    VIC0ADDRESS = 0;

    if(!(GPH2DAT & (1<<3)))

    {

        wy_printf("counter(k4) : %d \n",i++);

    }

    if(!(GPH3DAT & (1<<0)))

    {

        wy_printf("counter(K5) : %d \n",i--);

    }

}

extern void key_IRQ(void);

void irq_init(void)

{

    // 设置GPH2_3(K4),GPH3_0(K5)用于中断 

    GPH2CON |= 0xf<<12;

    GPH3CON |= 0xf<<0;

    // 设置触发方式为下降沿触发 

    EXT_INT_2_CON |= 0x2<<12;

    EXT_INT_3_CON |= 0x2<<0;

    // 使能中断(GPIO里面的) 

    EXT_INT_2_MASK &= ~(1<<3);

    EXT_INT_3_MASK &= ~(1<<0);

    // 设置为IRQ中断 

    VIC0INTSELECT &= ~(1<<16);

    // 使能中断(中断控制器里面的) 

    VIC0INTENABLE |= 1<<16;

    // 设置中断向量 

    VIC0VECTADDR16 = (int)key_IRQ;

}

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

main.c源码:

#include "command.h"

#include "clock.h"

#include "led.h"

#include "uart.h"

#include "lib.h"

#include "nand.h"

#define    CFG_PROMPT        "WY_BOOT # "    // Monitor Command Prompt    

#define    CFG_CBSIZE        256        // Console I/O Buffer Size    

char *argv[10];

int readline (const char *const prompt)

{

    char console_buffer[CFG_CBSIZE];        // console I/O buffer    

    char *buf = console_buffer;

    int argc = 0;

    int state = 0;

    //puts(prompt);

    wy_printf("%s",prompt);

    gets(console_buffer);

    

    while (*buf)

    {

        if (*buf != ' ' && state == 0)

        {

            argv[argc++] = buf;

            state = 1;

        }

        

        if (*buf == ' ' && state == 1)

        {

            *buf = '\0';

            state = 0;

        }

        

        buf++;    

    }

    

    return argc;

}

void message(void)

{

    wy_printf("\nThis bootloader support some command to test peripheral:\n");

    wy_printf("Such as: LCD, IIS, BUZZER \n");

    wy_printf("Try 'help' to learn them \n\n");    

}

int main(void)

{

    char buf[6];

    int argc = 0;

    int i = 0;

    led_init(); // 设置对应管脚为输出 

    uart_init(); // 初始化UART0 

    nand_read_id(buf);

    wy_printf("\n**********************************************************\n");

    wy_printf("                     wy_bootloader\n");

    wy_printf("                     vars: %d \n",2012);

    wy_printf("                     nand id:");

    putchar_hex(buf[0]);

    putchar_hex(buf[1]);

    putchar_hex(buf[2]);

    putchar_hex(buf[3]);

    putchar_hex(buf[4]);

wy_printf("\n********************************************

[1] [2]

关键字:Tiny210裸机  按键中断

编辑:什么鱼 引用地址:http://www.eeworld.com.cn/mcu/2018/ic-news101241714.html
本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。

上一篇:Tiny210裸机IIC之at24cxx操作
下一篇:S3C2440、S3C6410、S5PV210中断解析

关注eeworld公众号 快捷获取更多信息
关注eeworld公众号
快捷获取更多信息
关注eeworld服务号 享受更多官方福利
关注eeworld服务号
享受更多官方福利

推荐阅读

Tiny210裸机之UART串口操作

S5PV210的时钟的时候,一定要参考该图。上面给出的clock_init()函数,设置的寄存器参数,都是用的推荐值,在手册中都能够查到。我以HCLKD为什么等于166.75MHz为例,来讲述如何借助芯片手册的361页和362页的图来配置时钟:      1.HCLKD是用于显示域(如LCD等)的时钟,因此在361页的途中找到HCLK_DSYS,顺着箭头方向往回找,发现它是由DIVhclkd分频而来,即HCLK_DSYS = MOUT_DSYS / (HCLK_DSYS_RATIO + 1),类似的分频系数对应于CLK_DIVn寄存器;    
发表于 2018-10-13

Tiny210裸机之实现printf功能

注意:本节串口的printf等函数的实现方法可以参考OK6410的裸机“11th_uart_stdio”实验源码,该方法更实用。start.S源码:.global _start    _start:    ldr sp, =0xD0030000    @初始化堆栈        b main
发表于 2018-10-13

Tiny210裸机简单命令的实现

;   (*(volatile unsigned int *)0xe0100100) #define CLK_SRC0      (*(volatile unsigned int *)0xe0100200) #define CLK_DIV0      (*(volatile unsigned int *)0xe0100300) #define MPLL_CON      (*(volatile unsigned int
发表于 2018-10-13

Tiny210裸机之nand_flash操作

了,大家看我共享的代码,就明白,放在了"Tiny210学习日记_代码"目录下了,名为"6_nand"。测试:1).使用md命令:WY_BOOT # WY_BOOT # WY_BOOT # md 0xd0030000do_command  D0030000: 00EACEED CE4F284F 781CF81F 395E9CDE D0030010: 6B7DCBCF D4F870DB 9F07E61F 53BB9C51 2).使用nand read命令:WY_BOOT # WY_BOOT # nand read 0xd0030000 0x0
发表于 2018-10-13

Tiny210裸机之DDR_SDRAM重定位

u-boot里面的,只是自己从头对照寄存器去理解了一下,完全符合598页的初始化步骤),放在了"Tiny210学习日记_代码"目录下了,名为"7_ddr"注意:之前的代码,包括该部分代码,都没有重定位的操作,IROM最多可以拷贝16K的代码到IRAM中,够用了!但是,由于后面我会讲到LCD显示图片,声卡播放WAV文件,bootloader也随之慢慢变大,16K的大小可能不够,再加上现在已经把重定位的条件都准备好了,所以接下来将是重定位。(相关知识,大家可以学习韦东三一期视频的重定位部分),这里,我就不在细说,直接给出代码,和讲几个关键地方。以下为start.s的代码:.global
发表于 2018-10-13

Tiny210裸机之bootm命令启动内核

;  MACH_SMDKV210        SMDKV210        2456从而说明此时的机器ID是2456。注意:这个过程说得有点绕和啰嗦,再次抱歉。参数三:一句话,实在是没有什么可以说的,韦老大的视频里面讲得太详细了!!大家直接看视频和我上传的关于这章的代码吧,放在了"Tiny210学习日记_代码"目录下了,名为"9_bootm"。注意:本章写的代码,只能通过bootm命令来启动内核,延时自动启动内核,我会在后面章节讲到。
发表于 2018-10-13

小广播

何立民专栏

单片机及嵌入式宝典

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

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号 电信业务审批[2006]字第258号函 京公海网安备110108001534 Copyright © 2005-2018 EEWORLD.com.cn, Inc. All rights reserved
pt type="text/javascript" src="//v3.jiathis.com/code/jia.js?uid=2113614" charset="utf-8">