【飛凌嵌入式 OK3399-C+開發板試用體驗】本地編譯內核源碼&DHT11驅動編譯
作者:donatello1996
飛凌廠商提供的Linux源碼資料壓縮包實際上是多合一源碼,除了最常用的內核源碼以外,還有諸多額外內容比如交叉編譯鏈,Linux燒錄工具(卡刷+線刷),生成系統鏡像img的腳本,uboot源碼,應用程序代碼等諸多內容,這些不同內容面向不同層次的開發者,比如開發應用層的只看應用程序代碼即可,開發驅動的只看內核源碼和交叉編譯鏈即可,開發uboot的只看uboot源碼即可,產品部門相關的只需要會用工具即可。內核源碼為主目錄的kernel文件夾,交叉編譯鏈為主目錄的prebuilt文件夾,平時如果執行廠商提供的build_ubuntu.sh腳本,實際上不只是編譯內核和驅動(boot.img,**.ko),還有生成必須要的分區鏡像如recovery.img,userdata.img等:
1.mount /dev/sda /mnt 2.cd /mnt
然后是在板子上安裝64位aarch編譯工具,通常Ubuntu系統都會自帶的:
apt install aarch64-linux-gnu-gcc
那么就可以直接在板上進行本地內核編譯了:
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的公用產品ID 0x0125:
#define QUECTEL_PRODUCT_EC25 0x0125
{ USB_DEVICE(0x2C7C, 0x0125) }, /* Quectel EC25 */
繼續在此文件drivers/usb/serial/option.c文件中找到option_probe 函數,在此函數里面添加如下內容:
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, };
與設備樹的mygpio69節點對應:
static const struct of_device_id of_mygpio69_match[] = { { .compatible = "mygpio69", }, {}, };
添加節點之后就可以在驅動代碼里面進行GPIO寫電平操作了,復寫MYGPIO69_write函數,超級簡單:
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; } 當然了,要正常調用這些函數操作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設備文件,可以在應用層代碼直接操作:
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位數據 { 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
做個簡單的小實驗看下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 ) ; }
相關產品 >
-
FET3399-C核心板
飛凌RK3399安卓高性能核心板采用 采用六核Rockchip RK3399芯片,雙Cortex-A72大核+四Cortex-A53小核結構,對整數、浮點、內存等作了大幅優化,在整體性能、功耗及核心面積三個方面提升。以下將對瑞芯微芯片RK3399參數,RK3399核心板方案及其性能做具體介紹。如您對飛凌RK3399系列核心板有興趣,歡迎咨詢了解。
了解詳情 -
OK3399-C開發板
飛凌嵌入式RK3399安卓開發板主芯片采用高性能六核CPU Rockchip RK3399,GPU采用Mail-T860四核 GPU,RK3399作為目RK產品線中低功耗、高性能的代表,可滿足人臉識別設備、機器人、無人機、IoT物聯網領域應用。飛凌RK3399開發板在整體性能、功耗及核心面積做了大幅度優化,更加滿足工業設計需求。飛凌RK3399開發板為進一步減少用戶二次開發難度,開放了底板原理圖,并提供了RK3399用戶手冊、芯片手冊,加上優質的技術服務,讓您的方案從構思到上市時間縮短。