要想用uboot启动内核,我推荐一种方法,用dnw下载内核到开发板上,然后用uboot命令启动:

首先我在网上随便下了一个dnw工具,经过移植修改后,代码如下:

/*
YYX--->for tiny4412 dnw
version:20170423
v1
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdint.h>const char* dev = "/dev/secbulk0";
#define BLOCK_SIZE  (1*1024*1024)struct download_buffer {uint32_t   load_addr;  /* load address */uint32_t  size; /* data size */uint8_t        data[0];/* uint16_t checksum; */
};static int _download_buffer(struct download_buffer *buf)
{int fd_dev = open(dev, O_WRONLY);if( -1 == fd_dev) {printf("Can not open %s: %s\n", dev, strerror(errno));return -1;}printf("Writing data...\n");size_t remain_size = buf->size;size_t block_size = BLOCK_SIZE;size_t writed = 0;while(remain_size>0) {size_t to_write = remain_size > block_size ? block_size : remain_size;if( to_write != write(fd_dev, (unsigned char*)buf + writed, to_write)) {perror("write failed");close(fd_dev);return -1;}remain_size -= to_write;writed += to_write;printf("\r%02zu%%\t0x%08zX bytes (%zu K)",(size_t)((uint64_t)writed*100/(buf->size)),writed,writed/1024);fflush(stdout);}printf("\n");close(fd_dev);return 0;
}static inline void cal_and_set_checksum(struct download_buffer *buf)
{uint16_t sum = 0;int i;for(i = 0; i < buf->size; i++) {sum += buf->data[i];}*((uint16_t*)(&((uint8_t*)buf)[buf->size - 2])) = sum;
}static struct download_buffer* alloc_buffer(size_t data_size)
{struct download_buffer *buffer = NULL;size_t total_size = data_size + sizeof(struct download_buffer) + 2;buffer = (typeof(buffer))malloc(total_size);if(NULL == buffer)return NULL;buffer->size = total_size;return buffer;
}static void free_buffer(struct download_buffer *buf)
{free(buf);
}static struct download_buffer *load_file(const char *path, unsigned long load_addr)
{struct stat        file_stat;struct download_buffer    *buffer = NULL;unsigned long       total_size;int          fd;fd = open(path, O_RDONLY);if(-1 == fd) {printf("Can not open file %s: %s\n", path, strerror(errno));return NULL;}if( -1 == fstat(fd, &file_stat) ) {perror("Get file size filed!\n");goto error;}   buffer = alloc_buffer(file_stat.st_size);if(NULL == buffer) {perror("malloc failed!\n");goto error;}if( file_stat.st_size !=  read(fd, buffer->data, file_stat.st_size)) {perror("Read file failed!\n");goto error;}buffer->load_addr = load_addr;cal_and_set_checksum(buffer);return buffer;error:if(fd != -1)close(fd);if( NULL != buffer )free(buffer);return NULL;
}static int download_file(const char *path, unsigned long load_addr)
{struct download_buffer *buffer;struct timeval __start, __end;long __time_val = 0;float speed = 0.0;buffer = load_file(path, load_addr);gettimeofday(&__start,NULL);if (buffer != NULL) {if (_download_buffer(buffer) == 0) {gettimeofday(&__end,NULL);__time_val = (long)(__end.tv_usec - __start.tv_usec)/1000 + \(long)(__end.tv_sec - __start.tv_sec) * 1000;speed = (float)buffer->size/__time_val/(1024*1024) * 1000;printf("speed: %fM/S\n",speed);free_buffer(buffer);} else {free_buffer(buffer);return -1;}} elsereturn -1;
}int main(int argc, char* argv[])
{unsigned load_addr = 0x57e00000;char* path = NULL;int    c;while ((c = getopt (argc, argv, "a:h")) != EOF)switch (c) {case 'a':load_addr = strtol(optarg, NULL, 16);continue;case '?':case 'h':default:
usage:printf("Usage: dwn [-a load_addr] <filename>\n");printf("Default load address: 0x57e00000\n");return 1;}if (optind < argc)path = argv[optind];elsegoto usage;printf("load address: 0x%08X\n", load_addr);if (download_file(path, load_addr) != 0) {return -1;}return 0;
}

然后我们还要写一个Makefile,用来编译dnw这个工具:

如下:

dnw : dnw.cgcc -g -o $@ $^clean :rm -rf dnw *.oinstall : dnwcp $^ /usr/bin

然后make , 编译成功

在当前目录下可以看到生成了dnw这个二进制文件。

接下来,我们还需要一个驱动secbulk,于是再去网上下载:

源码如下:

在源码中,我们看到:{ USB_DEVICE(0x04e8, 0x1234) }, /* EZTIN4412 */

这一行是我自己添加的,该驱动要知道4412开发板USB的设备ID还有厂商ID,这个信息可以通过lsusb来获得,如下:

查看方法如下:

(1)先在minicom中敲一下dnw,会弹出这个界面等待PC文件传输过来。

(2)然后回到PC端,敲lsusb命令,如图:

从上图,我们看到Samsung Electiornics Co. , Ltd , 所以得知开发板的ID是04e8:1234

所以以下代码就要添加这么一个ID:{ USB_DEVICE(0x04e8, 0x1234) }, /* EZTIN4412 */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/usb.h>
#include <linux/fs.h>
#include <linux/mutex.h>
#include <linux/slab.h>
#include <linux/uaccess.h>#define SECBULK_MAJOR   102
#define SECBULK_MINOR   0
#define DRIVER_NAME "secbulk"#define BULKOUT_BUFFER_SIZE  (4*1024)struct secbulk_dev
{struct usb_device *udev;struct mutex io_mutex;char*    bulkout_buffer;__u8 bulk_out_endpointAddr;
};static struct usb_class_driver secbulk_class;static struct usb_device_id secbulk_table[]= {{ USB_DEVICE(0x5345, 0x1234) }, /* FS2410 */{ USB_DEVICE(0x04e8, 0x1234) }, /* TINY4412 */{ }
};static struct usb_driver secbulk_driver;
static void secbulk_disconnect(struct usb_interface *interface)
{struct secbulk_dev *dev = NULL;printk(KERN_INFO "secbulk:secbulk disconnected!\n");dev = usb_get_intfdata(interface);if( NULL != dev )kfree(dev);usb_deregister_dev(interface, &secbulk_class);return;
}static ssize_t secbulk_read(struct file *file, char __user *buf, size_t len,loff_t *loff)
{return -EPERM;
}static ssize_t secbulk_write(struct file *file, const char __user *buf,size_t len, loff_t *loff)
{size_t to_write;struct secbulk_dev *dev = file->private_data;int ret;int actual_length;size_t total_writed;total_writed = 0;while(len > 0) {to_write = min(len, BULKOUT_BUFFER_SIZE);if(copy_from_user(dev->bulkout_buffer, buf+total_writed,to_write)) {printk(KERN_ERR "secbulk:copy_from_user failed!\n");return -EFAULT;    }   ret = usb_bulk_msg(dev->udev,usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr),dev->bulkout_buffer,to_write,&actual_length,3*HZ);if(ret || actual_length!=to_write) {printk(KERN_ERR "secbulk:usb_bulk_msg failed!\n");return -EFAULT;}    len -= to_write;total_writed += to_write;}   return total_writed;
}static int secbulk_open(struct inode *node, struct file *file)
{struct usb_interface *interface;struct secbulk_dev *dev;interface = usb_find_interface(&secbulk_driver, iminor(node));if(!interface)return -ENODEV;dev = usb_get_intfdata(interface);dev->bulkout_buffer = kzalloc(BULKOUT_BUFFER_SIZE, GFP_KERNEL);if(!(dev->bulkout_buffer))return -ENOMEM;if(!mutex_trylock(&dev->io_mutex))return -EBUSY;file->private_data = dev;return 0;
}static int secbulk_release(struct inode *node, struct file *file)
{struct secbulk_dev *dev;dev = (struct secbulk_dev*)(file->private_data);kfree(dev->bulkout_buffer);mutex_unlock(&dev->io_mutex);return 0;
}static struct file_operations secbulk_fops = {.owner  =  THIS_MODULE,.read   =  secbulk_read,.write =  secbulk_write,.open   =    secbulk_open,.release= secbulk_release,
};static struct usb_class_driver secbulk_class = {.name =     "secbulk%d",.fops =      &secbulk_fops,.minor_base= 100,
};static int secbulk_probe(struct usb_interface *interface, const struct usb_device_id *id)
{int ret;struct secbulk_dev *dev;struct usb_host_interface *iface_desc;struct usb_endpoint_descriptor *endpoint;int i;printk(KERN_INFO "secbulk:secbulk probing...\n");dev = kzalloc(sizeof(*dev), GFP_KERNEL);if(!dev) {ret = -ENOMEM;goto error;} iface_desc = interface->cur_altsetting;for(i=0; i < iface_desc->desc.bNumEndpoints; i++) {endpoint = &(iface_desc->endpoint[i].desc);if(!dev->bulk_out_endpointAddr&& usb_endpoint_is_bulk_out(endpoint)) {printk(KERN_INFO "secbulk:bulk out endpoint found!\n");dev->bulk_out_endpointAddr = endpoint->bEndpointAddress;break;}}if(!(dev->bulk_out_endpointAddr)) {ret = -EBUSY;goto error;}ret = usb_register_dev(interface, &secbulk_class);if(ret) {printk(KERN_ERR "secbulk: usb_register_dev failed!\n");return ret;}        dev->udev = usb_get_dev(interface_to_usbdev(interface));usb_set_intfdata(interface, dev);mutex_init(&dev->io_mutex);return 0;
error:if(!dev)kfree(dev);return ret;
}static struct usb_driver secbulk_driver= {.name=     "secbulk",.probe=        secbulk_probe,.disconnect= secbulk_disconnect,.id_table=  secbulk_table,
};
static int __init secbulk_init(void)
{int result;printk(KERN_INFO "secbulk:secbulk loaded\n");result = usb_register(&secbulk_driver);if(result) {printk(KERN_ERR "secbulk:usb_register failed: %d", result);return result;}     return 0;
}static void __exit secbulk_exit(void)
{usb_deregister(&secbulk_driver);printk(KERN_INFO "secbulk:secbulk unloaded\n");
}module_init(secbulk_init);
module_exit(secbulk_exit);
MODULE_LICENSE("GPL");

接下来,我们来写一个Makefile:

#obj-m := secbulk.o
#secbulk-m := secbulk.o
obj-m := secbulk.o
KDIR := /lib/modules/`uname -r`/build
PWD  := $(shell pwd)default:$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
clean:$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) cleanrm -rf *.order *.symvers

然后在当前目录下make

编译成功如下:

编译成功以后,需要执行

chmod 777 secbulk.ko

sudo insmod secbulk.ko将内核插入系统。

接下来,还要安装一个库,方法:

sudo apt-get install libusb-dev

万事具备,只欠东风,现在可以启动minicom来尝试下载内核了

方法如下:

(1)在minicom端执行dnw 0x40008000,如图:

(2)切换到另外一个终端

然后执行dnw arch/arm/boot/zImage

切换到minicom端看到下载成功如下图:

接下来,在uboot中敲击bootm 0x40008000,注意不要打tab按键,否则你回看到以下未识别的信息:

我们重新来一次:

成功启动内核!!!!

手把手教你在友善之臂tiny4412上用uboot启动Linux内核相关推荐

  1. 友善之臂编linux内核,友善之臂NanoPC-T3 Plus,s5p6818编译Linux内核流程

    按照维基教程编译内核4.4.y: //我的编译器是这个,先设置一下 1.CROSS_COMPILE=aarch64-linux-gnu- //配置文件在 arch/arm64/configs/ 2.m ...

  2. 16w行的nginx源码,如何分拆模块阅读,手把手教你造轮子丨Nginx模块开发丨C/C++丨Linux服务器开发丨后端开发

    16w行的nginx源码,如何分拆模块阅读,让你明白轮子如何造  1. 多进程模型下的惊群处理 2. 内存池的代码封装 3. slab共享内存分配 视频讲解如下,点击观看: 16w行的nginx源码, ...

  3. 手把手教你如何使用Spring Security(上):登录授权

    文章目录 一.什么是 Spring Security? 官方介绍 通俗来讲 二.初始搭建 创建 启动 三.项目原理 原理 思考 四.登录认证 登录过滤器 配置过滤器链 类补充 五.登录效果 效果演示 ...

  4. 手把手教你安装OpenStack——Ocata安装指南(上)

    本文参考:https://docs.openstack.org/ocata/install-guide-rdo/index.html官方文档来手把手教你安装Ocata,安装文档中有漏洞的地方,本文都会 ...

  5. 手把手教你:如何让Windows恋上Linux bash

    4月7日,微软开始向用户推送Windows 10 biuld 14316预览版,该版本不仅在Cortana跨平台支持.Edge浏览器支持和虚拟桌面方面得到了优化,还能够原生支持Linux bash. ...

  6. 手把手教大家在自己的Windows电脑上搭建一个视频电话系统(基于开源项目FreeSwitch+Linphone)

    目前可以做视频电话的流媒体开源项目有很多,那么今天我就手把手教大家(基于FreeSwitch+Linphone)搭建一个免费的开源的能在局域网中使用的视频电话系统,部署与配置都非常的简单,而且点对点的 ...

  7. ai可以用c 语言编程,C语言手把手教你实现贪吃蛇AI(上)

    本文实例为大家分享了手把手教你实现贪吃蛇AI的具体步骤,供大家参考,具体内容如下 1. 目标 编写一个贪吃蛇AI,也就是自动绕过障碍,去寻找最优路径吃食物. 2. 问题分析 为了达到这一目的,其实很容 ...

  8. 嵌入式系统体系结构编程 Ubuntu之QTE环境搭建友善之臂Tiny4412

    @Date 2021-12-26 @Author C君 所用环境 VMware-workstation 16.1.0 ubuntu14 (资料里的14版本32位,是的我装回来了233) arm-lin ...

  9. 华为云部署html网页,手把手教你如何在华为云服务器上部署一个自己的弹幕网站!...

    开发思路 首先是让弹幕的随机高度出现,这个计算方法是:最大高度=屏幕的高度-发送div的高度-弹幕本身的高度,范围就是 0-最大高度了,弹幕总是从右往左移动,所以出现最右侧的位置计算方法是:最右侧位置 ...

最新文章

  1. 《Linux命令详解手册》——Linux畅销书作家又一力作
  2. Apache Web服务器访问控制机制全解析
  3. 改善企业互联网安全性的方法—Vecloud微云
  4. 零基础学Python:使用type、metaclass动态创建方法和属性的详细用法
  5. linux软件包管理之rpm 、yum基本使用
  6. Android 混淆详解
  7. asp.net 中 SESSION和COOKIE的使用
  8. mariadb10.2 mysql5.7_说说在MySQL5.7迁到MariaDB10.2时栽的一部分坑
  9. springboot+1、图片上传到本地路径信息保存在数据库2、根据id删除本地图片
  10. hbase权威指南-客户端API高级特性
  11. ArcGIS无插件加载(无偏移)天地图
  12. (三)碳排放如何计算
  13. Markdown目录生成
  14. windows 全系列电脑加速,告别电脑“卡”的时代
  15. opencv显示图片只显示部分(或认为图片太大)
  16. JS判断当前页面是在 QQ客户端/微信客户端/iOS浏览器/Android浏览器/PC客户端
  17. OpenGL ES 帧缓冲区位块传送(Blit)
  18. Ubuntu 20.4 美化桌面、美化引导界面、Mac 既视感
  19. 推荐:几款优秀的数据挖掘工具
  20. 嵌入式计算机分类,嵌入式系统的分类

热门文章

  1. 中文数字转换为阿拉伯数字
  2. 根据数据表中的存储的方法名称来调用方法
  3. C# 取电信公网IP并发送邮件
  4. 守住你自己的“沉香”
  5. 【Java】使用springboot运行程序时出现的错误
  6. I/O流之缓冲流的文件复制代码及节点流处理数据加密
  7. 软件测试人员的三重境界
  8. Linux权限管理的认知
  9. 2021年跨专业/转行业学IT,还有前途吗?
  10. 绝对干货!纯用HTML+CSS+JS 编写的计算器应用