led灯点亮
2015-11-02 13:40
393 查看
手工点亮led arm汇编
start_led: mov r0,#8 mov r1,#0 bl _gpio_direction_output mov r1,#0x500000 delayloop: nop sub r1,r1,#1 cmp r1,#0 bne delayloop mov r0,#8 mov r1,#1 bl _gpio_direction_output nop mov r1,#0x500000 delayloop2: nop sub r1,r1,#1 cmp r1,#0 bne delayloop2 /* bl _arm_blink_led */ b start_led
C点亮led
int _arm_blink_led() { __asm__ __volatile__ ( "start_led:\n\t" "mov r0,#8\n\t" "mov r1,#0\n\t" "bl _gpio_direction_output\n\t" "mov r1,#0x500000\n\t" "delayloop:\n\t" "nop\n\t" "sub r1,r1,#1\n\t" "cmp r1,#0\n\t" "bne delayloop\n\t" "mov r0,#8\n\t" "mov r1,#1\n\t" "bl _gpio_direction_output\n\t" "nop\n\t" "mov r1,#0x500000\n\t" "delayloop2:\n\t" "nop\n\t" "sub r1,r1,#1\n\t" "cmp r1,#0\n\t" "bne delayloop2\n\t" "b start_led\n\t" ); }
while(1);灯灭 for (i=0,init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr,i++) { if ((*init_fnc_ptr)() != 0) { hang (); } if(i==0)while(1);//灯灭 if(i==1)while(1);//灯亮 void start_armboot (void) { init_fnc_t **init_fnc_ptr; char *s; int i; #ifndef CFG_NO_FLASH ulong size; #endif #if defined(CONFIG_VFD) || defined(CONFIG_LCD) unsigned long addr; #endif /* Pointer is writable since we allocated a register for it */ gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t)); /* compiler optimization barrier needed for GCC >= 3.4 */ __asm__ __volatile__("": : :"memory"); memset ((void*)gd, 0, sizeof (gd_t)); gd->bd = (bd_t*)((char*)gd - sizeof(bd_t)); memset (gd->bd, 0, sizeof (bd_t)); monitor_flash_len = _bss_start - _armboot_start; gpio_direction_output(8, 0); //while(1);灯亮 }
start.s 调用c的方法
X:\c300\uboot\board\mindspeed\c300v2evm\board.cint _gpio_direction_output(unsigned gpio, int level) { gpio_direction_output(gpio,level); return 0;} X:\c300\uboot\include\asm\arch\comcerto-300.h #ifndef __ASSEMBLY__ #include <asm/types.h> void comcerto300_init(void); int comcerto300_set_fcs(int enable, u8 cs, int base_addr, int size); int comcerto300_set_cs_type(u8 cs, int sdram_enable); int comcerto300_set_cs_region(u8 cs, u32 base, u32 size); int comcerto300_set_cse(u8 cs, int enable); void comcerto300_set_cse_highmem_to_cs1(int enable); int comcerto300_uexp_cfg_cs(u8 cs, u16 cfga, u16 cfgb, u16 cfgc); void comcerto300_pll_set_clocks(u32 arm_clock, u32 bus_clock, u32 spu_clock); void comcerto300_pll_set_arm_clock(u16 clkf, u16 clkr, u16 clkod); void comcerto300_pll_set_spu_clock(u16 clkf, u16 clkr, u16 clkod); void comcerto300_pll_set_amba_clock(u16 clkf, u16 clkr, u16 clkod); void comcerto300_ntg_8mhz_init(void); int _gpio_direction_output(unsigned gpio, int level);#endif X:\c300\uboot\cpu\arm1136\start.S mov r0,#8 mov r1,#0 bl _gpio_direction_outputffff: b ffff
int board_init(void) { /* reset on-board peripherals via GPIO line */ gpio_direction_output(CFG_GPIO_OUT_PERIPHERAL_RESET, 0); while(1); udelay(100); gpio_set_value(CFG_GPIO_OUT_PERIPHERAL_RESET, 1); /* CS0 is used for SDRAM, see bsp_init() */ /* CS1 and CS2 used for flash memories */ nor_init();
static int __init mru_init(void) { if(misc_register(&misc)){ printk(KERN_ERR "failed to register mru\n"); return -1; } mru_led_enable = 0; mru_led_stat = 0; gpio_direction_output(MRU_STAT_PIN, mru_led_stat); setup_timer(&mru_timer, mru_timer_proc, (unsigned long)&mru_timer); mod_timer(&mru_timer, jiffies + msecs_to_jiffies(50)); printk(KERN_INFO "register mru\n"); return 0; } static void mru_timer_proc(unsigned long data) { if(mru_led_enable && ++mru_led_count >= 10){ mru_led_count = 0; mru_led_stat = !mru_led_stat; gpio_set_value(MRU_STAT_PIN, mru_led_stat); } mod_timer((struct timer_list*)data, jiffies + msecs_to_jiffies(50)); }在linux驱动中常常会碰到gpio_set_value(port_num,0/1)或gpio_direction_output (port_num,0/1) 这两者有什么关系呢gpio_set_value(port_num,0/1)
一般只是在这个GPIO口的寄存器上写上某个值,至于这个端口是否设置为输出,它就管不了!而gpio_direction_output (port_num,0/1),在某个GPIO口写上某个值之后,还会把这个端口设置为输出模式。 因此,有人也许就会建议,把gpio_set_value这个函数直接去掉不用,是否可以,显然是可以的。
但是为什么系统还要用呢, 我个人分析是, 系统开发人员在要结合这两者来使用,以便提高效率。 一般某个端口设置好了输入与输出模式后,最好不要经常变动。 首先要调用gpio_direction_output(),以后要设置高低电平时,直接使用gpio_set_value()就可以了,这样可以省却再次调用设置输出模式的操作,从而提高运行效率!
Control and status reporting for the GPIO resources is provided through nine registers. The base address for the
GPIO control registers is mapped to 0x10070000. The GPIO control registers can be accessed by adding the
associated “Offset” to the GPIO base address.
54 | r | 32 | GPIO中断状态寄存器 | ||
54 | w | GPIO中断状态寄存器清除 | |||
58 | RW | 中断屏蔽寄存器 | 0 | 0 禁止中断 | |
5c | RW | Watchdog Timer to GPIO Select Register (default: ‘0’) | 0 | ||
64 | rw | Bootstrap Pin Override Register (default : all ‘0’). The control bits in this register allow the programmer to override the bootstrap pins on the device. | |||
0 | RW | 32 | GPIO 写 | 缺省全0 | |
4 | rw | 32 | GPIO写使能 | 缺省全0 | 1 输出使能 0 输入使能 |
8 | RW | 上升沿中断使能 | 缺省0 | 1使能(仅当电平中断使能没有配置) | |
c | RW | 下降沿中断使能 | 0 | 1使能 | |
10 | R | 输入寄存器 | 表示每个管脚的状态 | ||
18 | RW | 复用配置寄存器 | 0 | ||
1c | R | 系统状态寄存器 | 0 Status of ARAMBOOT_n pin In Normal Mode, EPROM = H and ARAMBOOT= L enable boot from internal ARAM. | ||
28 | RW | tdm复用控制寄存器 | "0010000_00000000 | ||
34 | RW | DDR SSTL Buffer Type Register | (default: “00000000_00000001”) | ||
50 | RW | 电平中断使能寄存器 | 0 | 1 使能 |
相关文章推荐
- Linux切换账号
- KISSY整体架构流程
- 链表删除节点--算法复杂度o(1)
- leetcode之Find Median from Data Stream
- android从通讯录中选择联系人并读取号码
- JDBC:大数据量插入的三种方法比较
- c++ 对象内存分配和虚函数
- [DP] 后缀表达式与求值 visitor
- 分享互联网公司经验一
- linux—用nc命令监控检测服务器端口
- PHP 按位与(&)运算符应用实践
- 小作坊食品生产企业如何办理营业执照和卫生许可证?
- HDU 5512 Meeting 博弈论
- PHP安装MongoDB扩展
- Android动画之补间动画
- 【HDU5543 2015 CCPC 南阳国赛D】【贪心+DP】Pick The Sticks 木棍重心放在容器内 贪心法+三维状态直接法
- 将图片裁剪为圆边
- 请求转发与重定向
- IntelliJ IDEA 使用心得与常用快捷键
- 线性表