注意:以下内容主要参考了网上各位大牛的研究成果并实际操作验证成功,理论上可适用于sammung公司系列的ARM9、ARM11系列开发板,如TQ2440、OK6410和TQ210。
1 安装串口调试终端minicom
1.1 获取minicom
sudo apt-get install minicom
1.2 配置minicom
1) 连接usb转串口线连接到虚拟机
2) 查看串口设备
dmesg | grep ttyS*
可以看到设备名称是 ttyUSB0
3) 打开minicom
sudo minicom
4) 进入主界面后按Ctrl+A,放开后再按Z,进入配置界面
5) 按O进入配置界面,选择“Serialport setup”选项进行如下设置:
6) 配置完成后,选择Save setup as dfl将其保存为默认配置
2 安装arm-linux-gcc-4.4.3交叉编译器
2.1 解压安装包
tar zxvf arm-linux-gcc-4.4.3.tar.gz
将解压出来目录中的4.3.3文件夹拷贝到/opt/OK6410/arm-linux-gcc文件夹下,该文件夹为arm-linux-gcc的安装目录不可随意删除。
2.2 配置当前用户专属系统环境变量
gedit /home/ok6410/.bashrc
在该文件中最后一行添加:
export PATH=$PATH: /opt/OK6410/arm-linux-gcc/4.4.3/bin
2.3 使环境变量生效
source /home/ok6410/.bashrc
2.4 查看是否配置成功
arm-linux-gcc –v
3 安装DNW镜像下载工具
3.1 新建一个dnw.c文件,输入如下源代码
#include
#include
#include
#include
#include
#include
#include
const char* dev = "/dev/secbulk0";
int main(int argc, char* argv[])
{
unsignedchar* file_buffer = NULL;
if( 2!= argc )
{
printf("Usage:dwn
");
return1;
}
int fd= open(argv[1], O_RDONLY);
if(-1== fd)
{
printf("Cannot open file - %s
", argv[1]);
return1;
}
structstat file_stat;
if( -1== fstat(fd, &file_stat) )
{
printf("Getfile size filed!
");
return1;
}
file_buffer= (char*)malloc(file_stat.st_size+10);
if(NULL== file_buffer)
{
printf("mallocfailed!
");
gotoerror;
}
if(file_stat.st_size != read(fd,file_buffer+8, file_stat.st_size))
{
printf("Readfile failed!
");
gotoerror;
}
printf("filename : %s
", argv[1]);
printf("filesize : %d bytes
", file_stat.st_size);
intfd_dev = open(dev, O_WRONLY);
if( -1== fd_dev)
{
printf("Cannot open %s
", dev);
gotoerror;
}
*((unsignedlong*)file_buffer) = 0x32000000; //loadaddress
*((unsignedlong*)file_buffer+1) = file_stat.st_size+10; //filesize
unsignedshort sum = 0;
int i;
for(i=8;i
{
sum+= file_buffer[i];
}
/*****************************/
file_buffer[file_stat.st_size + 8] = sum & 0xff;
file_buffer[file_stat.st_size + 9] = sum >> 8;
/*****************************/
printf("Writingdata...
");
size_tremain_size = file_stat.st_size+10;
size_tblock_size = remain_size / 100;
size_twrited = 0;
while(remain_size>0)
{
size_tto_write = remain_size > block_size ? block_size:remain_size;
if(to_write != write(fd_dev, file_buffer+writed, to_write))
{
printf("failed!
");
return1;
}
remain_size-= to_write;
writed+= to_write;
printf("
%d% %d bytes ",writed*100/(file_stat.st_size+10), writed);
fflush(stdout);
}
printf("OK
");
return0;
error:
if(-1!=fd_dev)close(fd_dev);
if(fd!= -1) close(fd);
if(NULL!=file_buffer )
free(file_buffer);
return-1;
}
3.2 编译
sudo gcc -o dnw dnw.c
3.3 将dnw复制到/bin目录下,
sudo cp dnw /bin/
这样就可以在任意文件目录下调用dnw命令。
4 安装s3c系列开发板secbulk驱动
4.1 新建一个secbulk.c文件,输入以下源代码
#include
#include
#include
#include
#include
#include
#include
#define SECBULK_MAJOR 102
#define SECBULK_MINOR 0
#define DRIVER_NAME "secbulk"
#define BULKOUT_BUFFER_SIZE 512
struct secbulk_dev
{
structusb_device *udev;
structmutex 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(0x04e8, 0x1234)},
{ }
};
static struct usb_driver secbulk_driver;
static void secbulk_disconnect(structusb_interface *interface)
{
structsecbulk_dev *dev = NULL;
printk(KERN_INFO"secbulk:secbulk disconnected!
");
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_tto_write;
structsecbulk_dev *dev = file->private_data;
intret;
intactual_length;
size_ttotal_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!
");
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!
");
return-EFAULT;
}
len-= to_write;
total_writed+= to_write;
}
returntotal_writed;
}
static int secbulk_open(struct inode *node, structfile *file)
{
structusb_interface *interface;
structsecbulk_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;
return0;
}
static int secbulk_release(struct inode *node,struct file *file)
{
structsecbulk_dev *dev;
dev =(struct secbulk_dev*)(file->private_data);
kfree(dev->bulkout_buffer);
mutex_unlock(&dev->io_mutex);
return0;
}
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)
{
intret;
structsecbulk_dev *dev;
structusb_host_interface *iface_desc;
structusb_endpoint_descriptor *endpoint;
int i;
printk(KERN_INFO"secbulk:secbulk probing...
");
dev =kzalloc(sizeof(*dev), GFP_KERNEL);
if(!dev)
{
ret= -ENOMEM;
gotoerror;
}
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!
");
dev->bulk_out_endpointAddr= endpoint->bEndpointAddress;
break;
}
}
if(!(dev->bulk_out_endpointAddr))
{
ret= -EBUSY;
gotoerror;
}
ret =usb_register_dev(interface, &secbulk_class);
if(ret)
{
printk(KERN_ERR"secbulk: usb_register_dev failed!
");
returnret;
}
dev->udev= usb_get_dev(interface_to_usbdev(interface));
usb_set_intfdata(interface,dev);
mutex_init(&dev->io_mutex);
return0;
error:
if(!dev)
kfree(dev);
returnret;
}
static struct usb_driver secbulk_driver= {
.name= "secbulk",
.probe= secbulk_probe,
.disconnect= secbulk_disconnect,
.id_table= secbulk_table,
.supports_autosuspend=0,
};
static int __init secbulk_init(void)
{
intresult;
printk(KERN_INFO"secbulk:secbulk loaded
");
result= usb_register(&secbulk_driver);
if(result)
{ printk(KERN_ERR "secbulk:usb_registerfailed: %d", result);
returnresult;
}
return0;
}
static void __exit secbulk_exit(void)
{
usb_deregister(&secbulk_driver);
printk(KERN_INFO"secbulk:secbulk unloaded
");
}
module_init(secbulk_init);
module_exit(secbulk_exit);
MODULE_LICENSE("GPL");
注意,使用lsusb指令可以得到开发板对应的设备号,填入secbulk_table[]中。
4.2 编译
make
4.3 加载该模块到内核(注意:需要root权限)
sudo insmod secbulk.ko
加载后用dmesg命令可以看到模块已经成功加载
4.4 secbulk驱动随系统启动自动加载
修改/etc/init.d/rc.local文件,在后面加上下面一句:
insmod /“secbulk.ko文件所在目录”/secbulk.ko