【飛凌嵌入式 OK3399-C+開發(fā)板試用體驗(yàn)】本地編譯內(nèi)核源碼&DHT11驅(qū)動(dòng)編譯
作者:donatello1996
飛凌廠商提供的Linux源碼資料壓縮包實(shí)際上是多合一源碼,除了最常用的內(nèi)核源碼以外,還有諸多額外內(nèi)容比如交叉編譯鏈,Linux燒錄工具(卡刷+線刷),生成系統(tǒng)鏡像img的腳本,uboot源碼,應(yīng)用程序代碼等諸多內(nèi)容,這些不同內(nèi)容面向不同層次的開發(fā)者,比如開發(fā)應(yīng)用層的只看應(yīng)用程序代碼即可,開發(fā)驅(qū)動(dòng)的只看內(nèi)核源碼和交叉編譯鏈即可,開發(fā)uboot的只看uboot源碼即可,產(chǎn)品部門相關(guān)的只需要會用工具即可。內(nèi)核源碼為主目錄的kernel文件夾,交叉編譯鏈為主目錄的prebuilt文件夾,平時(shí)如果執(zhí)行廠商提供的build_ubuntu.sh腳本,實(shí)際上不只是編譯內(nèi)核和驅(qū)動(dòng)(boot.img,**.ko),還有生成必須要的分區(qū)鏡像如recovery.img,userdata.img等:
1.mount /dev/sda /mnt 2.cd /mnt
然后是在板子上安裝64位aarch編譯工具,通常Ubuntu系統(tǒng)都會自帶的:
apt install aarch64-linux-gnu-gcc
那么就可以直接在板上進(jìn)行本地內(nèi)核編譯了:
1.make clean 2.make rockchip_linux_defconfig 3.make
1.apt install libssl-dev 2.apt install libssl1.0.0= 1.0.2g-1ubuntu4.16
1.cd /mnt/RTL8192EU 2.make clean 3.make
#define QUECTEL_VENDOR_ID 0x2c7c
然后是EC20/EC25的公用產(chǎn)品ID 0x0125:
#define QUECTEL_PRODUCT_EC25 0x0125
{ USB_DEVICE(0x2C7C, 0x0125) }, /* Quectel EC25 */
繼續(xù)在此文件drivers/usb/serial/option.c文件中找到option_probe 函數(shù),在此函數(shù)里面添加如下內(nèi)容:
if (dev_desc->idVendor == cpu_to_le16(0x05c6) &&
dev_desc->idProduct == cpu_to_le16(0x9003) &&
iface_desc->bInte**ceNumber >= 4)
return -ENODEV;
if (dev_desc->idVendor == cpu_to_le16(0x05c6) &&
dev_desc->idProduct == cpu_to_le16(0x9215) &&
iface_desc->bInte**ceNumber >= 4)
return -ENODEV;
if (dev_desc->idVendor == cpu_to_le16(0x2c7c) &&
iface_desc->bInte**ceNumber >= 4)
return -ENODEV;
static struct usb_serial_driver option_1port_device = {
.driver = {
.owner = THIS_MODULE,
.name = "option1",
},
.description = "GSM modem (1-port)",
.id_table = option_ids,
.num_ports = 1,
.probe = option_probe,
.open = usb_wwan_open,
.close = usb_wwan_close,
.dtr_rts = usb_wwan_dtr_rts,
.write = usb_wwan_write,
.write_room = usb_wwan_write_room,
.chars_in_buffer = usb_wwan_chars_in_buffer,
.tiocmget = usb_wwan_tiocmget,
.tiocmset = usb_wwan_tiocmset,
.ioctl = usb_wwan_ioctl,
.attach = option_attach,
.release = option_release,
.port_probe = usb_wwan_port_probe,
.port_remove = usb_wwan_port_remove,
.read_int_callback = option_instat_callback,
#ifdef CONFIG_PM
.suspend = usb_wwan_suspend,
.resume = usb_wwan_resume,
.reset_resume = usb_wwan_resume,
#endif
};
static struct urb *usb_wwan_setup_urb(struct usb_serial_port *port,
int endpoint,
int dir, void *ctx, char *buf, int len,
void (*callback) (struct urb *))
{
struct usb_serial *serial = port->serial;
struct urb *urb;
urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */
if (!urb)
return NULL;
usb_fill_bulk_urb(urb, serial->dev,
usb_sndbulkpipe(serial->dev, endpoint) | dir,
buf, len, callback, ctx);
if (dir == USB_DIR_OUT) {
struct usb_device_descriptor *desc = &serial->dev->descriptor;
if (desc->idVendor == cpu_to_le16(0x05C6) && desc->idProduct ==
cpu_to_le16(0x9090))
urb->transfer_flags |= URB_ZERO_PACKET;
if (desc->idVendor == cpu_to_le16(0x05C6) && desc->idProduct == cpu_to_le16(0x9003))
urb->transfer_flags |= URB_ZERO_PACKET;
if (desc->idVendor == cpu_to_le16(0x05C6) && desc->idProduct == cpu_to_le16(0x9215))
urb->transfer_flags |= URB_ZERO_PACKET;
if (desc->idVendor == cpu_to_le16(0x2C7C))
urb->transfer_flags |= URB_ZERO_PACKET;
}
return urb;
}
static struct file_operations mygpio69_fops = {
.owner = THIS_MODULE,
.read = MYGPIO69_read,
.write = MYGPIO69_write,
.open = MYGPIO69_open,
.release = MYGPIO69_close,
};
與設(shè)備樹的mygpio69節(jié)點(diǎn)對應(yīng):
static const struct of_device_id of_mygpio69_match[] =
{
{ .compatible = "mygpio69", },
{},
};
添加節(jié)點(diǎn)之后就可以在驅(qū)動(dòng)代碼里面進(jìn)行GPIO寫電平操作了,復(fù)寫MYGPIO69_write函數(shù),超級簡單:
static int mygpio69_gpio = 69;
//GPIO號
#define MYGPIO69_LOW gpio_set_value(mygpio69_gpio, 0)
#define MYGPIO69_HIGH gpio_set_value(mygpio69_gpio, 1)
static ssize_t MYGPIO69_write(struct file *file,const char __user *buf,
size_t nbytes, loff_t *ppos)
{
if(buf[0]==1)
MYGPIO69_HIGH;
else if(buf[0]==0)
MYGPIO69_LOW;
}
當(dāng)然了,要正常調(diào)用這些函數(shù)操作GPIO,是要先初始化GPIO的:
if (gpio_request(mygpio69_gpio, "mygpio69_gpio"))
{
printk("gpio %d request failed!\n", mygpio69_gpio);
gpio_free(mygpio69_gpio);
return -ENODEV;
}
else
printk("gpio %d request success!\n", mygpio69_gpio);
make生成ko文件之后,就會在/dev目錄下生成mygpio69設(shè)備文件,可以在應(yīng)用層代碼直接操作:
int main ()
{
int fd ;
unsigned char val[4],value;
fd = open ( "/dev/mygpio69" , O_RDWR) ;
if ( fd == -1 )
{
perror ( "open /dev/mygpio69 error\n" ) ;
exit ( -1 ) ;
}
printf ( "open /dev/mygpio69 successfully\n" ) ;
while (1)
{
value=0;
write(fd,&value,1);
sleep(1);
value=1;
write(fd,&value,1);
sleep(1);
}
close ( fd ) ;
}
static u8 DHT11_Read_Data(u16 *temp,u16 *humi)
{
u8 buf[5];
u8 i;
DHT11_Rst();
if(DHT11_Check()==0)
{
for(i=0;i<5;i++)//讀取40位數(shù)據(jù)
{
buf[i]=DHT11_Read_Byte();
}
if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4])
{
*humi=buf[0]<<8|buf[1];
*temp=buf[2]<<8|buf[3];
printk("buf=%d,%d,%d,%d,%d\n",buf[0],buf[1],buf[2],buf[3],buf[4]);
}
}else return 1;
return 0;
}
static ssize_t DHT11_read(struct file *file, char __user *buf,
size_t nbytes, loff_t *ppos)
{
printk("--------------%s--------------\n",__FUNCTION__);
dht11_data Last_dht11_data;
if(DHT11_Read_Data(&Last_dht11_data.temp,&Last_dht11_data.hum) == 0);//讀取溫濕度值
{
if (raw_copy_to_user(buf,&Last_dht11_data,sizeof(Last_dht11_data)) )
{
return EFAULT ;
}
}
}
static struct file_operations dht11_fops = {
.owner = THIS_MODULE,
.read = DHT11_read,
.open = DHT11_open,
.release = DHT11_close,
};
static const struct of_device_id of_dht11_match[] = {
{ .compatible = "dht11", },
{},
};
MODULE_DEVICE_TABLE(of, of_dht11_match);
static struct platform_driver dht11_driver = {
.probe = dht11_probe,
.remove = dht11_remove,
.shutdown = dht11_shutdown,
.driver = {
.name = "dht11_driver",
.of_match_table = of_dht11_match,
},
};
insmod dht11_drv.ko
做個(gè)簡單的小實(shí)驗(yàn)看下DHT11能否正常讀取溫度:
typedef struct DHT11_SENSOR_DATA
{
unsigned short temp;//溫度
unsigned short hum;//濕度
}dht11_data;
int main ( void )
{
int fd ;
int retval ;
dht11_data Curdht11_data;
fd = open ( "/dev/dht11" , O_RDONLY) ;
if ( fd == -1 )
{
perror ( "open dht11 error\n" ) ;
exit ( -1 ) ;
}
printf ( "open /dev/dht11 successfully\n" ) ;
sleep ( 2 ) ;
while ( 1 )
{
sleep ( 1 ) ;
retval = read ( fd , &Curdht11_data , sizeof(Curdht11_data) );
if ( retval == -1 )
{
printf ( "read dht11 error" ) ;
exit ( -1 ) ;
}
if(Curdht11_data.temp != 0xffff)
printf ( "Temperature:%d.%d C,Humidity:%d.%d %%RH\n",
Curdht11_data.temp>>8,
Curdht11_data.temp&0xff,
Curdht11_data.hum>>8,
Curdht11_data.hum&0xff ) ;
}
close ( fd ) ;
}
相關(guān)產(chǎn)品 >
-
FET3399-C核心板
飛凌RK3399安卓高性能核心板采用 采用六核Rockchip RK3399芯片,雙Cortex-A72大核+四Cortex-A53小核結(jié)構(gòu),對整數(shù)、浮點(diǎn)、內(nèi)存等作了大幅優(yōu)化,在整體性能、功耗及核心面積三個(gè)方面提升。以下將對瑞芯微芯片RK3399參數(shù),RK3399核心板方案及其性能做具體介紹。如您對飛凌RK3399系列核心板有興趣,歡迎咨詢了解。
了解詳情
-
OK3399-C開發(fā)板
飛凌嵌入式RK3399安卓開發(fā)板主芯片采用高性能六核CPU Rockchip RK3399,GPU采用Mail-T860四核 GPU,RK3399作為目RK產(chǎn)品線中低功耗、高性能的代表,可滿足人臉識別設(shè)備、機(jī)器人、無人機(jī)、IoT物聯(lián)網(wǎng)領(lǐng)域應(yīng)用。飛凌RK3399開發(fā)板在整體性能、功耗及核心面積做了大幅度優(yōu)化,更加滿足工業(yè)設(shè)計(jì)需求。飛凌RK3399開發(fā)板為進(jìn)一步減少用戶二次開發(fā)難度,開放了底板原理圖,并提供了RK3399用戶手冊、芯片手冊,加上優(yōu)質(zhì)的技術(shù)服務(wù),讓您的方案從構(gòu)思到上市時(shí)間縮短。
了解詳情


