1. 板子f403tech的RT5350的板子和

(1)openWRT系统的定义和特点

        OpenWrt是一个高度模块化、高度自己主动化的嵌入式Linux系统。拥有强大的网络组件。经常被

用于工控设备、电话、小型机器人、智能家居、路由器以及VOIP设备中。

OpenWrt支持各种处理器架构。不管是对ARM。X86。PowerPC或者MIPS都有非常好的支持。

其多达3000多种软件包。囊括从工具链(toolchain)。到内核(linux kernel),到软件包

(packages)。再到根文件系统(rootfs)整个体系,使得用户仅仅需简单的一个make命令就可以方便快

速地定制一个具有特定功能的嵌入式系统来制作固件。 其模块化设计也能够方便的移植各类功能

到OpenWrt下,加快开发速度。

2 实验mjpeg-streamer、uvc视频监控

3 openwrt的下载安装

<pre name="code" class="cpp">sudo apt-get install subversion
sudo apt-get install git-core
sudo apt-get install gcc g++ binutils patch bzip2 flex bison make autoconf gettext texinfo unzip sharutils zlib1g-dev libncurses5-dev gawk
mkdir openwrt
cd openwrt/
svn co svn://svn.openwrt.org/openwrt/trunk
cd trunk/
./scripts/feeds update -a
./scripts/feeds install -a
(4) 配置编译openWRT系统
a、选择CPU型号
TargetSystem —> RalinkRT288x/RT3xxx
b、选择CPU子型号
Subtarget —> RT3x5x/RT5350basedboards
c、选择详细路由器型号
Targetprofile—>HAME-MPR-A2
(5) 编译
make V=99

至此,完毕内核和文件系统镜像编译





4 驱动开发流程

进入/home/openwrt/trunk/package/kernel驱动文件夹,仿照參考其它的驱动。



新建example目录,进入example目录。

创建Makefile:

#

# Copyright (C) 2008-2012 OpenWrt.org

#

# This is free software, licensed under the GNU General Public License v2.

# See /LICENSE for more information.

# modify by 2014-10-23



include $(TOPDIR)/rules.mk

include $(INCLUDE_DIR)/kernel.mk



PKG_NAME:=example

PKG_RELEASE:=1



include $(INCLUDE_DIR)/package.mk



define KernelPackage/example

  SUBMENU:=Other modules

#  DEPENDS:=@!LINUX_3_3

  TITLE:=Simple example driver

  FILES:=$(PKG_BUILD_DIR)/example.ko

#  AUTOLOAD:=$(call AutoLoad,30,gpio-button-hotplug,1)

  KCONFIG:=

endef



define KernelPackage/example/description

 This is a example for the following in-kernel drivers:

 1) example one

 2) example two

endef



MAKE_OPTS:= \

        ARCH="$(LINUX_KARCH)" \

        CROSS_COMPILE="$(TARGET_CROSS)" \

        SUBDIRS="$(PKG_BUILD_DIR)"



define Build/Prepare

        mkdir -p $(PKG_BUILD_DIR)

        $(CP) ./src/* $(PKG_BUILD_DIR)/

endef



define Build/Compile

        $(MAKE) -C "$(LINUX_DIR)" \

                $(MAKE_OPTS) \

                modules

endef



$(eval $(call KernelPackage,example))

新建srce目录。进入src目录。
创建Makefile:
obj-m += example.o
创建example.c源文件
#include <linux/module.h>
#include <linux/version.h>
#include <linux/kmod.h> static int __init example_init(void)
{
        printk("hello example openwrt\n");
        return 0;
} static void __exit example_exit(void)
{
        printk("hello example openwrt exit\n");
} module_init(example_init);
module_exit(example_exit); MODULE_AUTHOR("zhaochuang8888@126.com");
MODULE_DESCRIPTION("example driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:" DRV_NAME); c.编译驱动的命令
make package/kernel/example/compile V=99
<pre name="code" class="cpp"><pre name="code" class="cpp">在/home/openwrt/trunk/bin/ramips/packages/base文件夹生成:kmod-example_3.14.18-1_ramips_24kec.ipk

5 应用开发流程

进入/home/openwrt/trunk/package应用文件夹。參考其它的应用文件。

创建helloworld目录。并进入。

创建Makefile:

##############################################

# OpenWrt Makefile for helloworld program

#

#

# Most of the variables used here are defined in

# the include directives below. We just need to

# specify a basic description of the package,

# where to build our program, where to find

# the source files, and where to install the

# compiled program on the router.

#

# Be very careful of spacing in this file.

# Indents should be tabs, not spaces, and

# there should be no trailing whitespace in

# lines that are not commented.

#

##############################################



include $(TOPDIR)/rules.mk



# Name and release number of this package

PKG_NAME:=helloworld

PKG_RELEASE:=1





# This specifies the directory where we're going to build the program.

# The root build directory, $(BUILD_DIR), is by default the build_mipsel

# directory in your OpenWrt SDK directory

PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)





include $(INCLUDE_DIR)/package.mk



 



# Specify package information for this program.

# The variables defined here should be self explanatory.

# If you are running Kamikaze, delete the DESCRIPTION

# variable below and uncomment the Kamikaze define

# directive for the description below

define Package/helloworld

    SECTION:=utils

    CATEGORY:=Utilities

    TITLE:=Helloworld -- prints a snarky message

endef





# Uncomment portion below for Kamikaze and delete DESCRIPTION variable above

define Package/helloworld/description

        If you can't figure out what this program does, you're probably

        brain-dead and need immediate medical attention.

endef



 



# Specify what needs to be done to prepare for building the package.

# In our case, we need to copy the source files to the build directory.

# This is NOT the default.  The default uses the PKG_SOURCE_URL and the

# PKG_SOURCE which is not defined here to download the source from the web.

# In order to just build a simple program that we have just written, it is

# much easier to do it this way.

define Build/Prepare

    mkdir -p $(PKG_BUILD_DIR)

    $(CP) ./src/* $(PKG_BUILD_DIR)/

endef





# We do not need to define Build/Configure or Build/Compile directives

# The defaults are appropriate for compiling a simple program such as this one





# Specify where and how to install the program. Since we only have one file,

# the helloworld executable, install it by copying it to the /bin directory on

# the router. The $(1) variable represents the root directory on the router running

# OpenWrt. The $(INSTALL_DIR) variable contains a command to prepare the install

# directory if it does not already exist.  Likewise $(INSTALL_BIN) contains the

# command to copy the binary file from its current location (in our case the build

# directory) to the install directory.

define Package/helloworld/install

    $(INSTALL_DIR) $(1)/bin

    $(INSTALL_BIN) $(PKG_BUILD_DIR)/helloworld $(1)/bin/

endef





# This line executes the necessary commands to compile our program.

# The above define directives specify all the information needed, but this

# line calls BuildPackage which in turn actually uses this information to

# build a package.

$(eval $(call BuildPackage,helloworld))

创建src目录,并进入。

创建Makefile:

# build helloworld executable when user executes "make"



helloworld: helloworld.o

        $(CC) $(LDFLAGS) helloworld.o -o helloworld



helloworld.o: helloworld.c

        $(CC) $(CFLAGS) -c helloworld.c



# remove object files and executable when user executes "make clean"

clean:

        rm *.o helloworld

创建helloworld.c:

#include<stdio.h>

int main(void)

{

        printf("helloworld\n");

        return 0;

}



make package/helloworld/motor/compile V=99

在/home/openwrt/trunk/bin/ramips/packages/base文件夹生成:helloworld_1_ramips_24kec.ipk





5 LCD2004实验



lcd_204a_drv.c 驱动源程序:



#include <linux/module.h>

#include <linux/kernel.h>

#include <linux/fs.h>

#include <linux/init.h>

#include <linux/delay.h>

#include <linux/device.h>



#include <asm/uaccess.h>

#include <asm/irq.h>

#include <asm/io.h>



static struct class *lcddrv_class;

static struct device *lcddrv_class_dev;



volatile unsigned long *GPIOMODE;

volatile unsigned long *I2C_CONFIG;

volatile unsigned long *I2C_CLKDIV;

volatile unsigned long *I2C_DEVADDR;

volatile unsigned long *I2C_ADDR;

volatile unsigned long *I2C_DATAOUT;

volatile unsigned long *I2C_STATUS;

volatile unsigned long *I2C_STARTXFR;

volatile unsigned long *I2C_BYTECNT;



static int lcd_204a_open(struct inode *inode, struct file *file)

{

    return 0;

}



static ssize_t lcd_204a_write(struct file *file, const char __user *buf, size_t size, loff_t *ppos)

{

    unsigned char val;



    copy_from_user(&val, buf, 1);



    *I2C_CONFIG = (0x6<<2)|(1<<1);                // 设备地址是7bit、不用发地址

    *I2C_DEVADDR = 0x20;                        // 设备地址为0x20



    *I2C_DATAOUT = val;



    *I2C_STARTXFR = 0x0;



    while(*I2C_STATUS & 0x1);

    

    return 1;

}



static struct file_operations sencod_drv_fops = {

    .owner        = THIS_MODULE,    /* 这是一个宏,推向编译模块时自己主动创建的__this_module变量 */

    .open        = lcd_204a_open,

    .write        = lcd_204a_write,

};



int major;

static int lcd_204a_init(void)

{

    major = register_chrdev(0, "lcd_204a", &sencod_drv_fops);



    lcddrv_class = class_create(THIS_MODULE, "lcd");

    lcddrv_class_dev = device_create(lcddrv_class, NULL, MKDEV(major, 0), NULL, "lcd"); /* /dev/204a */

    

    /* 映射对应的寄存器的地址 */

    GPIOMODE = (volatile unsigned long *)ioremap(0x10000060, 4);

    I2C_CONFIG = (volatile unsigned long *)ioremap(0x10000900, 4);

    I2C_CLKDIV = (volatile unsigned long *)ioremap(0x10000904, 4);

    I2C_DEVADDR = (volatile unsigned long *)ioremap(0x10000908, 4);

    I2C_ADDR = (volatile unsigned long *)ioremap(0x1000090C, 4);

    I2C_DATAOUT = (volatile unsigned long *)ioremap(0x10000910, 4);

    I2C_STATUS = (volatile unsigned long *)ioremap(0x10000918, 4);

    I2C_STARTXFR = (volatile unsigned long *)ioremap(0x1000091C, 4);

    I2C_BYTECNT = (volatile unsigned long *)ioremap(0x10000920, 4);



    /* 開始设置这些寄存器 */

    *GPIOMODE &= ~(1<<0);                        // I2C_GPIO_MODE

    *I2C_CLKDIV = 0x200;                            // IIC总线时钟 = 40MHz / 512 = 79KHz

    

    return 0;

}



static void lcd_204a_exit(void)

{

    unregister_chrdev(major, "lcd_204a");

    device_unregister(lcddrv_class_dev);

    class_destroy(lcddrv_class);

    iounmap(GPIOMODE);

    iounmap(I2C_CONFIG);

    iounmap(I2C_CLKDIV);

    iounmap(I2C_DEVADDR);

    iounmap(I2C_ADDR);

    iounmap(I2C_DATAOUT);

    iounmap(I2C_STATUS);

    iounmap(I2C_STARTXFR);

    iounmap(I2C_BYTECNT);

}



module_init(lcd_204a_init);

module_exit(lcd_204a_exit);



MODULE_LICENSE("GPL");



lcd2004的应用程序:





#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

#include <stdio.h>

//依据LCD2004A和PCF8574T的引脚确定

//RS:指令/数据 寄存器选择  RS = 0 : 指令寄存器 RS = 1 : 数据寄存器   依据原理图得:RS 与 PCF8574T的PO链接

//RW:读/写 选择   R/W = 0 : 写     R/W = 1 : 读  依据原理图得:RW 与 PCF8574T的P1链接

//CS:同意信号    表示从高电平到低电平,

#define DATA(rs, rw, cs, data) (data<<4)|(cs<<2)|(rw<<1)|rs



int fd;



static void lcd_write_command(unsigned char command)

{

    unsigned char data;



    /* 1.发送命令的高4位 */

    data = DATA(0, 0, 1, (command>>4));

    printf("h data = %d\n", data);

    write(fd, &data, 1);

    usleep(20);

    data = DATA(0, 0, 0, (command>>4));

    printf("h data = %d\n", data);

    write(fd, &data, 1);



    /* 2.发送命令的低4位 */

    data = DATA(0, 0, 1, (command&0x0f));

    printf("l data = %d\n", data);

    write(fd, &data, 1);

    usleep(20);

    data = DATA(0, 0, 0, (command&0x0f));

    printf("l data = %d\n", data);

    write(fd, &data, 1);

}



static void lcd_write_data(unsigned char wdata)

{

    unsigned char data;



    /* 1.发送命令的高4位 */

    data = DATA(1, 0, 1, (wdata>>4));

    printf("h data = %d\n", data);

    write(fd, &data, 1);

    usleep(20);

    data = DATA(1, 0, 0, (wdata>>4));

    printf("h data = %d\n", data);

    write(fd, &data, 1);



    /* 2.发送命令的低4位 */

    data = DATA(1, 0, 1, (wdata&0x0f));

    printf("l data = %d\n", data);

    write(fd, &data, 1);

    usleep(20);

    data = DATA(1, 0, 0, (wdata&0x0f));

    printf("l data = %d\n", data);

    write(fd, &data, 1);

}



static void lcd_set_xy(unsigned char x, unsigned char y)

{

    unsigned char address;



    if (y == 0)

        address = 0x80 + x;

    else

        address = 0xc0 + x;

    

    lcd_write_command(address);

}



/*

    函数名:

        lcd_write_char()

    功能:

        列x=0~15,行y=0,1

    使用方法:

*/

static void lcd_write_char(unsigned char X,unsigned char Y,unsigned char Recdata)

{

    lcd_set_xy(X, Y);

    lcd_write_data(Recdata);

}



static int lcd_PutStr(unsigned char *DData,int pos)

{

    unsigned char i;

    

    if(pos==-1)

    {

        lcd_write_command(0x01); //清屏

        usleep(2);

        pos=0;

    }

    

    while((*DData)!='\0')

    {

        switch(*DData)

        {

            case '\n': //假设是\n,则换行   

            {

                if(pos<21)

                {

                    for(i=pos;i<20;i++)

                    lcd_write_char(i%20, i/20, ' ');

                    pos=20;

                }

                else

                {

                    for(i=pos;i<40;i++)

                        lcd_write_char(i%20, i/20, ' ');

                    pos=40;

                }

                break;

            }



            case '\b': //假设是\b。则退格   

            {

                if(pos>0)

                    pos--;

                lcd_write_char(pos%20, pos/20, ' ');

                break;

            }



            default:

            {

                if((*DData)<0x20)

                {

                    *DData=' ';

                }



                lcd_write_char(pos%20, pos/20,*DData);

                pos++;

                break;

            }

        }  

        DData++;

    }



    return(pos);

}



//从右边数。保留几位小数

static int lcd_PutNum(unsigned long num,int XS,int pos)

{

    unsigned long tmp=0;

    unsigned char numbits=0;

    

    if(pos==-1)

    {

        lcd_write_command(0x01);

        usleep(2);

        pos=0;

    }

    

    if(num==0)

    {

        lcd_write_char(pos%20, pos/20, '0');

        pos++;

    }

    else

    {

        if(num<0)

        {

            lcd_write_char(pos%20, pos/20, '-');

            num*=(-1);

            pos++;

        }



        while(num)

        {

            tmp=tmp*10+(num%10);

            num=num/10;

            numbits++;

        }

        

        while(tmp)

        {

            lcd_write_char(pos%20, pos/20, (tmp%10)+48);

            tmp=tmp/10;

            pos++;

            numbits--;

            if(numbits==XS)

                pos=lcd_PutStr(".",pos); //显示小数点

        }

        

        while(numbits--)

        {

            lcd_write_char(pos%20, pos/20, '0');

            pos++;

        }

    }

    

    return(pos);

}



void lcd_put_char(unsigned char ch, unsigned int pos , int flag)

{

    if(flag == 0)

    {

        lcd_write_command(0x80+pos);

    }

    if(flag == 1)

    {

        lcd_write_command(0xc0+pos);

    }

    lcd_write_data(ch);

}



void lcd_put_str(const char *str, int flag)

{

    int cnt=0;

    while(*str !='\0')

    {

        lcd_put_char(*str, cnt, flag);

        cnt++;

        str++;

    }

}

/* seconddrvtest

  */

int main(int argc, char **argv)

{

    int p;

    

    fd = open("/dev/lcd", O_RDWR);

    if (fd < 0)

    {

        printf("can't open!\n");

    }



    lcd_write_command(0x28);

    usleep(1000);

    lcd_write_command(0x28);

    usleep(1000);

    lcd_write_command(0x28);

    usleep(1000);



    lcd_write_command(0x0e);            // 显示开

    usleep(1000);

    lcd_write_command(0x01);            // 清屏

    usleep(1000);

    

//    lcd_write_char(0, 0, "a");



    int i = 0;

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

    {

        lcd_write_command(0x80+i);

        lcd_write_data('a'+i);

    }

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

    {

        lcd_write_command(0xc0+i);

        lcd_write_data('2'+i);

    }



    

     sleep(10);    

    lcd_write_command(0x01);                        // 清屏

        usleep(1000);

    lcd_put_str("Welcome RT5350", 0);

    lcd_put_str("        --By Dreeam", 1);

    //p = lcd_PutStr("RT5350 By F403tech!\n",0);    // 显示一段文字

    //usleep(1000);

    //p = lcd_PutStr("f403tech.taobao.com\n",p);    // 显示一段文字

    //lcd_PutNum(1234,2,p);                // 显示12.34这个数



    return 0;

}





a.软件包管理经常使用命令

opkg install xxx.ipk                        // 安装指定的软件包

opkg remove xxx.ipk                            // 卸载已经安装过的指定的软件包

opkg list                                                // 获取软件列表



生成的驱动位于 /lib/modules/3.14.18/文件夹下。

<pre name="code" class="cpp">生成的应用位于 /bin文件夹下。

opkg help




最新文章

  1. JavaScript 基础回顾——数组
  2. jQuery学习笔记(二)jQuery中DOM操作
  3. 最近在学习bootstrap的时候用bootstrap的视频教程2.0的引用bootstrap3.0突然发现很多不同,总结了一下
  4. Solr Cloud搭建
  5. wav文件格式分析(二)
  6. Android shape 渐变!描边!圆角!示例详解
  7. oc语言学习之基础知识点介绍(三):类方法、封装以及继承的介绍
  8. Seek the Name, Seek the Fame - POJ 2752(next运用)
  9. python 时间处理
  10. 关于MATLAB处理大数据坐标文件201762
  11. java多线程编程核心技术——第五章总结
  12. Firefox书签同步工具Xmarks
  13. iOS中 Swift初级入门学习(三)
  14. Pycharm+Django搭建第一个Python Web程序
  15. winform 子窗体调用父窗体中的方法
  16. Docker: 如何将node.js的项目部署到docker的swarm上面去
  17. Convolutional Neural Networks
  18. DOS 命令集锦——最常用命令
  19. Redis笔记(二):Redis数据类型
  20. INFORMATION_SCHEMA数据库介绍

热门文章

  1. 时钟周期 VS 机器周期
  2. 【memcached】memcached中flags字段的作用
  3. python3.x Day5 异常处理
  4. 在移动端H5开发中(关于安卓端position:fixed和position:absolute;和虚拟键盘冲突的问题,以及解决方案)
  5. Vue如何使用vue-area-linkage实现地址三级联动效果
  6. NOR flash and NAND flash
  7. 网络编程基础:网络基础之网络协议、socket模块
  8. XMLREADER/DOM/SIMPLEXML 解析大文件
  9. [NOIP2004] 提高组 洛谷P1091 合唱队形
  10. 解决json_encode中文乱码