Hisilicon 平台调试经验总结

Hisilicon 平台调试经验总结

2017年12月05日 11:45:54

阅读数:491

记录最近一年调试hisilicon 平台的相关经验,现已经转到互联网云存储方面的。话说嵌入领域,智能硬件领域,无非就是CPU,外设;但鉴于现在芯片原厂SDK 中基本都封装好啊! 改动的比较少,差不多就是按部就班的过程;  处于自己对互联网行业的向往, 现总结自己关于嵌入开发,特别是海思平台的开发; 鉴于自己的前期不重视,总结出三个字,“精,深,面”;精则为精通某一领域,深则为深挖其中的精髓,面则为逐步扩宽自己的知识面;

前面的纯属扯淡,欢迎调侃!

1.      3518EV200之Liteos

1.1  uboot篇

编译配置:make ARCH=arm CROSS_COMPILE=arm-hisiv300-linux- hi3518ev200_config

编译:make ARCH=arm CROSS_COMPILE=arm-hisiv300-linux-   

生成bin档:./mkboot.sh reg_info_hi3518ev200.bin u-boot-hi3518ev200.bin

注意,reg_info_hi3518ev200.bin 为SDK中uboot_tools 目录生成的xls文件生成的io配置文件。

1.2  Liteos系统篇

编译Liteos系统:make CHIP=hi3518ev200

编译liteos APP程序:make CHIP=hi3518ev200 (原SDK Sample目录中会生成sample.bin程序,该程序主要实现驱动的初始化,文件系统的初始化,挂载文件系统,以及应用业务)

1.2.1         uboot 引导Liteos系统的启动CMD参数:

nand flash:   

setenv bootcmd 'nand read 0x800080000x100000 0x700000; go 0x80008000’; saveenv

spi flash:

setenv bootcmd 'sf probe 0;sf read0x82000000  0x100000 0x700000;go 0x80008000'

注意,0x80008000 为Liteos 固定的启动地址,它是在编译时指定的连接启动地址,可在board.ld中修改。

1.3  Liteos 文件系统篇

1.3.1         Jffs2

JFFS2 (日志文件系统):管理在设备上实现的日志型文件系统;它主要应用与NOR型闪存,特点是可读写、支持数据压缩,并提供崩溃/掉电安全保护,提供写平衡支持。

初始化步骤:

(1)初始化头结点

         init_head()

(2)添加JFFS2 分区

         add_mtd_parttion(类型,分区起始地址,分区长度,分区号)

(3)挂载JFFS2

         mount()实现设备节点和挂载点的挂载

         shell 挂载命令  mount/dev/spinorblk1 /jffs1 jffs

         判断是否挂载成功:在文件系统的根目录是否可以正常查看到挂载目录

         将从串口得到如下回应信息,表明挂载成功。

         HuaweiLite OS# mount /dev/spinorblk1/jffs1 jffs

         挂载成功后,用户就能对norflash进行读写操作。

(4)卸载JFFS2

    umount()

(5)删除JFFS2 分区

     delete_mtd_partition 删除已经卸载的分区

jffspar 查看挂载分区的情况,如显示下列log 则说明挂载ok

jffs_partition num:0, devname:/dev/spinorblk0, mountpt:/jffs0, startaddr:0x0100000, length:0x0300000

1.3.2         FAT文件系统

它是File Alloction Table(文件配置表)的简称;它将硬盘分区为MBR、DBR、FAT、FDT、FADT区等5个区域;

ffconf.h FAT文件系统配置文件,可设置文件读写的相关属性

初始化步骤:

(1)      设备识别

(2)      文件系统挂载与卸载     mount /dev/mmcblk0p0 /sd0p0 vfat       ;umount /sd0p0

1.4  Liteos NAND/NOR Flash 篇

初始化步骤:

(1)      初始化nand flash控制

Nand_init() /spinor_init() 初始化主控

(2)分区,flash 控制器初始化后,即可对其进行分区操作。

int add_mtd_partition( char *type, uint32_tstart_addr, uint32_t length, uint32_t partition_num)

[type]:存储介质类型,指定字符串为"nand"与"spinor"。分别代表两类存储介质。

[start_addr]:分区操作flash的物理开始地址。

[length]:分区操作Nand flash的分区大小。

[partition_num]:分区盘符。

eg:

add_mtd_partition("nand", 0x900000,16*0x100000, 0);

(3)挂载分区

int mount(FAR const char *source, FAR constchar *target,FAR const char *filesystemtype, unsigned long mountflags,FAR constvoid *data)

[source]: 挂载源设备。参数意义指需要挂载的设备结点。

[target]: 挂载点目录。

[filesystemtype]: 挂载文件系统类型。

[mountflags]: 挂载标志。在此例挂载暂时无义,可传入0 参数。后续版本会进行

扩展。

[data]:挂载追加参数。此例挂载暂时无义。可传入参数0。

eg:

mount("/dev/nandblk0","/yaffs0", "yaffs", 0, NULL);

1.5  Liteos MMC/SD/EMMC篇

初始化步骤:

#1 初始化SD/MMC/SDIO模块        SD_MMC_Host_init()

#2 挂载设备         mount() 

#3 格式化设备       format(const char *dev, int sectors) 格式化FAT32 文件系统

#4 分区设备     

int add_mmc_partition(structdisk_divide_info *info, size_t sector_start,size_t sector_count);

参数说明:

*info:必须指定为extern structdisk_divide_info emmc;

sector_start:分区的起始扇区位置,目前版本以512kbyte为一个扇区。

sector_count:分区的扇区数量,目前版本以512kbyte为一个扇区。

1.6  Liteos 其他驱动篇

1.6.1 I2C

功能:完成CPU 对I2C 总线上连接的从设备的读写

#1 i2c初始化

i2c_dev_init()

#2 i2c 读写

i2c_read 命令对I2C 外围设备进行读操作:

i2c_read <i2c_num><device_addr> <reg_addr> <end_reg_addr> <reg_width> [data_width][data_rate].

i2c_write 命令对I2C 外围设备进行写操作:

i2c_write <i2c_num><device_addr> <reg_addr> <reg_value> <reg_width> [data_width][data_rate].

1.6.2 SPI

功能:完成对SPI 总线上连接的从设备的读写

#1 初始化

hi_spi_init()

1.6.3  USB Host Controller

初始化函数:usb_init() 

1.6.4   DDR 内存管理

#1 所有DDR内存中,一部分由操作系统管理,称为OS内存;另一部分由MMZ模块管理,供媒体业务单独使用,称为MMZ内存。

#2 OS内存起始地址为0x80008000,MMZ内存起始地址默认为(Hi3518EV200: 0x82000000;Hi3518EV201:0x81000000;Hi3516CV200:0x84000000),OS内存起始地址固定,不能修改。MMZ内存起始地址可以根据客户的场景业务修改。

#3 MMZ内存由MMZ内核模块管理,MMZ模块初始化时,通过参数指定其大小。

#4  请注意MMZ内存地址范围不能与OS内存重叠。

1.7  Liteos Shell指令篇

1.7.1 注册命令函数:

UINT32 osCmdReg( UINT32 uwCmdType, CHAR *pscCmdKey,UINT32

uiParaNum,CMD_CBK_FUNC pfnCmdProc );

– uwCmdType:命令类型,对外提供的命令类型为CMD_TYPE_EX。

– pscCmdKey:命令关键字,函数在Shell中访问的名称。

– uiParaNum:调用的执行函数的入参个数。

– pfnCmdProc:函数地址,即执行函数。

这个函数可以将一个函数链接到Shell中,可以在Shell命令行中使用。

1.7.2 常见shell 指令

#1 starthapd 用于启动AP 模式

startapd [channel][ssid][encryptionscheme][encryptionalgorithm][pwd]

                            信道    名字   加密方式           加密算法           密码

 参数总结:

channel            信道       0~11

encryptionscheme   加密方式   none,wep-shared,wep-open,wpa,wpa2,wpa+wpa2

encryptionalgorithm 加密算法  tkip,aes,tkip+aes            

注意:当加密方式为none 时,后面的参数就不需要再加

eg:        

         startapd3  ddpai_liteos wpa2 aes 1234567890

         startapd3  ddpai_liteos none

#2  stopapd  关闭AP模式

#3  startwpa   开启WiFi的station  

#4  setwpamode   设置WiFi station模式各项参数

命名格式:setwpamode [name] [encryptionscheme][encryptionalgorithm] [pwd]

#5  stowpa  关闭station模式

#6 iperf 测试网络传输速度

命令格式: iperf[-c] [ipaddrss]     

#7 memcheck 检查动态申请的内存块释放完整,释放存在内存踩踏

2 Hi3559 Liteos/Linux 系统篇

2.1  uboot篇

它主要完成引导liteos/linux 系统的功能;

配置指令:make ARCH=arm CROSS_COMPILE=arm-hisiv500-linux- hi3519_config

编译指令:make ARCH=arm CROSS_COMPILE=arm-hisiv500-linux-

镜像生成指令:./mkboot.sh reg_info.bin hi3519_uboot.bin 

2.2 Liteos/linux 系统篇

Liteos

Linux

NDK

MAPI

Local

HisysLink

HisysLink

MAPIClient

ndk 提供媒体相关的采集、处理、编解码等驱动和库,对外以MAPI接口形式呈现

#1 编译osdrv:

make osdrv -C ndk 或者 进入到ndk子目录,执行makeosdrv

#2 编译ndk:

make mapi -C ndk  或者 进入ndk子目录,执行makemapi

#3 编译Middleware:

make middleware   或者 进入middleware子目录,执行makemiddleware

#4 Uboot 编译:

make ARCH=arm CROSS_COMPILE=arm-hisiv500-linux-hi3559_config

make ARCH=armCROSS_COMPILE=arm-hisiv500-linux-

./mkboot.sh reg_info.bin hi3519_uboot.bin

#5 kernel 编译:

cp arch/arm/config/hi3559_xxx_defconfig.config

make ARCH=armCROSS_COMPILE=arm-hisiv500-linux- menuconfig

make ARCH=armCROSS_COMPILE=arm-hisiv500-linux- uImage

#6 LITEOS 编译

cd platform/liteos/liteos/

make menuconfig

make

#7 IPCM(Inter-Processor CommunictionModule)  多核通信模块,实现Liteos与linux 之间的通信

./build.sh

注意:当拿到3559 SDK时,需要进入到ndk文件夹。执行一次make all,对整个SDK进行编译;以后如要编译进入每个模块内执行makefile,详见个模块内部的makefile;

如编译出现部分错误,请参照Hi3559_编译环境note.txt 文件;

切记:3559 SDK 开发环境需用64位系统!!!!!

2.3 Liteos /Linux 内存布局

Hisilion 默认参考:

Linux Sys Mem

Liteos sys Mem

 IPCM

Parameter

Linux MMZ

Liteos MMZ

96M

80M

4M

1M

8M

220M

切记:必须先加载liteos,再加载linux

Liteos 内存配置文件 :platform/bsp/hi3559/cortex-a17/board.h

/* sample.bin should be loaded atSYS_MEM_BASE */

#define SYS_MEM_BASE 0x86000000   /*起始基地址*/

#define SYS_MEM_SIZE_DEFAULT 0x5000000  /*分配的内存长度*/ 

#define DDR_MEM_SIZE         0x100000000

2.4 uboot引导双系统启动篇

2.4.1 Flash 分区

2.4.2 uboot引导

Linux 系统启动参数:

bootargs=mem=96M console=ttyAMA0clk_ignore_unused rw root=/dev/mtdblock2 rootfstype=jffs2mtdparts=hi_sfc:1M(boot),4M(kernel),19M(rootfs)

uboot 引导双系统启动参数:

bootcmd=sf probe 0; sf read 0x860080000x1800000 0x100000; go_a17 0x86008000; sf read0x82000000 0x100000 0x400000; bootm 0x82000000

Linux系统的启动大致分为:

#1 uboot 引导uimage,解压uimage,并调用start_kernel来初始化内核镜像;

#2 内核初始化

#3 挂载root文件系统(由于jffs2 挂载时会扫描flash)

3 .linux 文件系统浅谈篇 

文件系统

系统有一个file_system_type类型的全局变量file_systems,用来保存系统已经支持的文件系统;在挂载(mount)文件系统时,会判断系统是否支持挂载的文件系统。

struct file_system_type {

const char *name;        /*文件系统名*/

int fs_flags;

struct dentry *(*mount) (structfile_system_type *, int,const char *, void *);

void (*kill_sb) (struct super_block *);

struct module *owner;

struct file_system_type * next;           /*所有已经注册的文件系统连接到file_systems*/

struct hlist_head fs_supers;           /*mount文件系统,系统都会为它创建一super_block,保存文件系统本身以及挂载点相关信息。*/

struct lock_class_key s_lock_key;

struct lock_class_key s_umount_key;

struct lock_class_key s_vfs_rename_key;

struct lock_class_key i_lock_key;

struct lock_class_key i_mutex_key;

struct lock_class_key i_mutex_dir_key;

};

文件件系统4大金刚:super_block,inode,file,dentry;

#1 super_block (超级块)

存储文件系统相关信息。

#2 inode  包含文件系统中的一个文件的所有信息,inode与文件系统中的文件是一一对应的。

主要组成部分:

#1  描述文件状态的元数据,文件元数据包括文件大小,权限,类型,时间;

#2 文件数据描述,则用来定义文件数据再磁盘上的存放位置;

#3 file

它与进程相关的,file代表一个打开的文件,file与inode 之间是多对一的关系;因为多进程可以同时

打开一个文件,系统就会为每一个打开的文件都创建file结构。

#4 dentry

它主要是用来加快目录遍历

struct dentry {

         /*RCU lookup touched fields */

         unsignedint d_flags;                 /* protectedby d_lock */

         seqcount_td_seq;            /* per dentry seqlock */

         structhlist_bl_node d_hash;  /* 保存在hash表中;为了处理hash冲突 */

         structdentry *d_parent;         /* parentdirectory */

         structqstr d_name;         /* 文件的名称*/

         structinode *d_inode;              /* dentry 所对应的inode,它主要就是通过路径名查找inode*/

         unsignedint d_count;   /*dentry引用计数*/

         conststruct dentry_operations *d_op;

         structsuper_block *d_sb;       /* 该目录项所在文件系统实例的超级块*/

};

文件系统mount 流程(内核函数调用关系):

SYSCALL_DEFINE5(mount,xxxx)  系统调用

do_mount

do_remount_sb         通知文件系统改变挂载属性

         do_new_mount

                   do_kern_mount

                            mount_fs

                                     type->mount(type,flags, name, data); 调用到file_system_type 文件系统的xxx_mount 

read/write 流程:

#1 VFS 层

它主要屏蔽下层具体文件系统操作的差异。

#2 具体文件系统层

#3 cache 层(page cache层)

它主要是为了提高linux操作系统对磁盘访问的性能

#4 通用块层(generic blocklayer)

它主要为接收上层发出的磁盘请求,并最终发出IO请求。

#5 IO 调度层

它主要接收通用块层发出的IO请求,缓存请求。

#6 块设备驱动层

#7 物理块设备层

Read 函数调用栈关系:

sys_read

         do_sync_read

                   filp->f_op->aio_read(&kiocb,&iov, 1, kiocb.ki_pos);

                   generic_file_aio_read(xxx_file_operations)

                            do_generic_file_read

BIO 层调用关系:

block 层调用:

submit_bio

         generic_make_request

                   __generic_make_request

                            q->make_request_fn(q,bio);  该make_request_fn 函数指针为__make_request

4 hisilion MMC Host/Block 初始化及req调用关系浅谈

4.1  /driver/mmc/host/himciv100/himci.c 主控初始文件

hi_mci_probe   初始化内核定时器,并启动是否有卡接入到卡槽;

         mmc_alloc_host   初始化延时队列mmc_rescan

                   mmc_rescan   延时队列,用于扫描SD卡

         hi_mci_detect_card   定时器,用于SD卡热插拔

         hi_mci_init_card  初始化SD/MMC/SDIO Host

         mmc_add_host

                   mmc_start_host     

                            mmc_detect_change   检测SD是否接入到卡槽,原理为:sd_detect管脚拉低,则表示有sdcard 接入

4.2 Block

mmc io的读写从mmc_queue_thread()的获取queue里面的request开始;

主要调用函数流程(从下到上),如下:

host->ops->request

mmc_start_request

         mmc_start_req

                   mmc_blk_issue_rw_rq

                            mmc_blk_part_switch(选择读写分区)

                            mmc_blk_issue_rq

                                     md->queue.issue_fn= mmc_blk_issue_rq;

                                               mmc_queue_thread-->blk_fetch_request(从块设备队列提取存储的req)

                                              

5 调试篇

主要记录调试uboot,linux,liteos,rootfs 相关经验;

烧录uboot:

sf probe 0

mw.b 82000000 ff 100000;

tftp 0x82000000 u-boot-hi3518ev200.bin;   通过tftp将uboot文件下载到内存8200000

sf probe 0;

sf erase 0 100000;

sf write 82000000 0 100000;

烧录镜像:

mw.b 82000000 ff 300000

tftp 82000000 uImage

sf probe 0

sf erase 100000 300000

sf write 82000000 100000 300000

烧录rootfs:

mw.b 82000000 ff C00000

tftp 0x82000000 jffs2-root.img

tftp 0x82000000rootfs_hi3516cv200_64k.jffs2

sf probe 0

sf erase 400000 C00000

sf write 82000000 400000 C00000

上传镜像:hi3516cV200_flash_16M.bin

 mw.b82000000 ff 1000000

 sfprobe 0

 sfread  0x82000000 0x0 0x1000000

 tftp0x82000000 hi3516cV200_flash.bin 0x1000000

LiteOS 调试记录:

tftp 0x80008000 sample.bin;go 0x80008000  通过tftp将sample.bin 下载到内存,并从0x80008000启动;

挂载SD卡命令:

mount /dev/mmcblk0p0 /sd0p0 vfat 

umount /sd0p0   

有什么问题或者错误的情况,请各位指正!

工作在于总结,在于交流,在于深入,在于理解,在于运用!请做一个善于思索,善于总结的工程师;每天进步一点点,日积月累就有可能成为专家!

猜你喜欢

转载自blog.csdn.net/xswy1/article/details/81624727
今日推荐