TQ210天嵌开发板S5PV210 LED闪烁程序C语言代码记录

          之前也学习过LDE闪烁程序,一般通过如下方式实现:
       主要思想是通过操作寄存器地址的方式操作寄存器,这种实现方式的优点就
       是简单容易理解,但是具有一定的局限性,一般在较大的工程中不会这样实
       现,因为通过直接操作地址的方式实现,必定会频繁查询数据手册,查询相
       应寄存器地址,还有就是程序中会出现大量地址,可读性差不利于程序移植
       和优化。
      通过学习,了解了一种通用的程序设计方式,特此记录
      先说下大概思想:
      1)引入GPIO基地址概念,建立GPIO结构体,这样每一个GPIO都可以通过
      ”基地址+偏移地址“的思想查找到,避免了频繁操作地址的弊端。
      2)位操作思想,不能为了实现某一个功能,影响其他功能,因此位操作的
      实现方式成为了程序设计中优先考虑的因素。
    下面说下具体细节实现:
    主要步骤如下(此处针对我使用的开发板TQ210,具体实现是一样的):
    1.	通过查询开发板原理图得到两个LED的引脚分别为:	GPC0_3、GPC0_4
    2.	查询GPIO的基地址为:0xE0200000
    3.	设置功能寄存器GPC0CON为输出 :因为输出为0001=Output
    4.	则32位的2进制值为:xxxx xxxx xxxx 0001  0001 xxxx xxxx xxxx
    5.	设置完模式为输出:仍需设置到底是低电平输出,还是高电平输出。
    6.设置组控制器:GPC0DAT 为高点亮LED
     则32位的2进制值为:xxxx xxxx xxxx  0001 0001 xxxx xxxx xxxx
     设置组控制器:GPC0DAT 为低熄灭LED
     则32位的2进制值为:xxxx xxxx xxxx 0000 0000 xxxx xxxx xxxx
     (x代表未知,即保留其原有的状态)
         具体程序分为以下几个程序:
         1.start.S汇编文件 主要功能跳到C语言main函数
         2.main.c 主程序 调用 led相关程序 延时程序等
         3.map.lds 链接脚本文件 控制程序文件顺序
          4.Makefie文件
          5.led.c  led.h  LED相关设置
          6.cpu_io.h     地址赋值等相关操作
          7.gpio.h        gpio结构体等
          具体程序代码如下:

start.S

.global _start
.global main

_start :
     bl   main
loop:
     b loop
.end

main.c

//main.c
#include "led.h"
#include "cpu_io.h"

static void mydelay()
{
        volatile unsigned int i=0xfffff;
        while(i--);

}
void led_test()
{

      led_init();
      while(1)
      {
         led_blink(1);
         mydelay();
         led_blink(0);
         mydelay();
      }
}

int main()
{
        led_test();
        return 0;
}

led.c

#include "gpio.h"
#include "led.h"
#include "cpu_io.h"

void led_init(void)
{
        struct s5pv210_gpio *gpio_base=(struct s5pv210_gpio *) S5PV210_GPIO_BASE;
        unsigned int var;
        var =_REG(&gpio_base->gpio_c0.con);
        var &=~(0xFF<<(4*3));  //1111 1111 0000 0000 0000
        var |= (0x11<<(4*3));  //0001 0001 0000 0000 0000
        writel(var,&gpio_base->gpio_c0.con); //11000
}

void led_blink(int status)
{
        struct s5pv210_gpio *gpio_base=(struct s5pv210_gpio *) S5PV210_GPIO_BASE;
        unsigned int var ;
        if(status)
        {
                var  = _REG(&gpio_base->gpio_c0.dat);
                var &=~0x18;   //00011000
                writel(var,&gpio_base->gpio_c0.dat);
        }
        else
        {
                var  = _REG(&gpio_base->gpio_c0.dat);
                var |=0x18;
                writel(var,&gpio_base->gpio_c0.dat);
        }

}

map.lds

OUTPUT_FORMAT("elf32-littlearm","elf32-littlearm","elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
        . =0x0;
        . =ALIGN(4);
        .text   :
        {
                start.o
                *(.text)
        }
        . =ALIGN(4);
        .rodata :
        {
                *(.rodata)
        }
        . =ALIGN(4);
        .data   :
        {
                *(.data)
        }
        . =ALIGN(4);
        .bss    :
        {
                *(.bss)
        }
}

led.h

#ifndef LED_H
#define LED_H
void led_init(void);
void led_blink(int status);
#endif

gpio.h

#ifndef _ASM_ARCH_GPIO_H
#define _ASM_ARCH_GPIO_H

struct s5pc1xx_gpio_bank{
        unsigned int con;
        unsigned int dat;
        unsigned int pull;
        unsigned int drv;
        unsigned int pdn_con;
        unsigned int pdn_pull;
        unsigned char res1[8];
};
struct s5pv210_gpio{
        struct s5pc1xx_gpio_bank gpio_a0;
        struct s5pc1xx_gpio_bank gpio_a1;
        struct s5pc1xx_gpio_bank gpio_b;
        struct s5pc1xx_gpio_bank gpio_c0;
        struct s5pc1xx_gpio_bank gpio_c1;
        struct s5pc1xx_gpio_bank gpio_d0;
        struct s5pc1xx_gpio_bank gpio_d1;
        struct s5pc1xx_gpio_bank gpio_e0;
        struct s5pc1xx_gpio_bank gpio_e1;
        struct s5pc1xx_gpio_bank gpio_f0;
        struct s5pc1xx_gpio_bank gpio_f1;
        struct s5pc1xx_gpio_bank gpio_f2;
        struct s5pc1xx_gpio_bank gpio_f3;
        struct s5pc1xx_gpio_bank gpio_g0;
        struct s5pc1xx_gpio_bank gpio_g1;
        struct s5pc1xx_gpio_bank gpio_g2;
        struct s5pc1xx_gpio_bank gpio_g3;
        struct s5pc1xx_gpio_bank gpio_i;
        struct s5pc1xx_gpio_bank gpio_j0;
        struct s5pc1xx_gpio_bank gpio_j1;
        struct s5pc1xx_gpio_bank gpio_j2;
        struct s5pc1xx_gpio_bank gpio_j3;
        struct s5pc1xx_gpio_bank gpio_j4;
};
#define S5PV210_GPIO_BASE (0xE0200000)
#endif

cpu_io.h

#ifndef _S5PV210_CPU_H
#define _S5PV210_CPU_H


#define _REG(x) (*(volatile unsigned int *)(x))

#define readb(a) (*(volatile unsigned char *)(a))
#define readw(a) (*(volatile unsigned short *)(a))
#define readl(a) (*(volatile unsigned int *)(a))


#define writeb(v, a) (*(volatile unsigned char *)(a) = v)
#define writew(v, a) (*(volatile unsigned short *)(a) = v)
#define writel(v, a) (*(volatile unsigned int *)(a) = v)

#endif

以上就是实现LED闪烁的全部思路思想,还是要感谢Rocky大神讲解的如此细致,
让我收获了很多,以上内容进攻学习交流,如有错误,还请批评指正。
01-14 17:21