├── .gitignore ├── README.md ├── mini2440 └── README.md ├── rk3288 ├── README.md ├── apps │ ├── Android.mk │ ├── event_parser.c │ ├── lcd_test.c │ └── test.c ├── buildenv ├── debug │ ├── android_gdb.md │ ├── codec │ │ ├── .gitignore │ │ ├── Makefile │ │ ├── README.md │ │ ├── es8316.c │ │ ├── es8316.dtsi │ │ ├── es8316.h │ │ ├── es8323.c │ │ ├── es8323.dtsi │ │ ├── es8323.h │ │ ├── pngs │ │ │ ├── I2S_DMA.png │ │ │ ├── I2S_INT.png │ │ │ ├── I2S_MAP.png │ │ │ ├── I2S_REG.png │ │ │ ├── Spatial-Audio-Diagram.png │ │ │ ├── analog_input.png │ │ │ ├── audio_adapter0.jpg │ │ │ ├── audio_adapter1.jpg │ │ │ ├── bpfs.png │ │ │ ├── codec_block_diagram.png │ │ │ ├── es8323.png │ │ │ ├── hp_ctl.png │ │ │ ├── hp_det.png │ │ │ ├── hp_mux.png │ │ │ ├── line-mic0.png │ │ │ ├── line-mic1.png │ │ │ ├── mixer.png │ │ │ ├── reg13.png │ │ │ ├── reg22.png │ │ │ ├── reg24.png │ │ │ ├── reg32.png │ │ │ ├── spk_ctl.png │ │ │ ├── trrs.jpg │ │ │ ├── trrs1.jpg │ │ │ ├── trs.jpg │ │ │ ├── trs1.jpg │ │ │ └── ts.jpg │ │ ├── rk_es8316.c │ │ ├── rk_es8323.c │ │ ├── rk_i2s.c │ │ └── rk_i2s.h │ ├── debug_technic.md │ ├── enter_kgdb_mode.sh │ ├── env_debug_kernel.cmd │ ├── hello │ │ ├── .gitignore │ │ ├── Makefile │ │ ├── README.md │ │ ├── hello.c │ │ └── hello.dis │ ├── i2c │ │ ├── .gitignore │ │ ├── Makefile │ │ ├── README.md │ │ ├── i2c_regmap.c │ │ ├── myi2c.c │ │ └── myi2c.dtsi │ ├── interrupt │ │ ├── .gitignore │ │ ├── Makefile │ │ ├── int.c │ │ └── test.dtsi │ ├── kernel_list_usage │ │ ├── .gitignore │ │ ├── Makefile │ │ └── list_usage.c │ ├── led │ │ ├── .gitignore │ │ ├── Makefile │ │ ├── myled.c │ │ └── myled.h │ ├── misc │ │ ├── .gitignore │ │ ├── Makefile │ │ ├── README.md │ │ ├── power_domain00.png │ │ ├── power_domain01.png │ │ ├── uk_io.c │ │ ├── uk_io.dtsi │ │ ├── uk_io_test.c │ │ ├── vfs_rw.c │ │ ├── wei.c │ │ └── wei.dtsi │ ├── mycpuinfo │ │ ├── .gitignore │ │ ├── Makefile │ │ └── mycpuinfo.c │ ├── netlink │ │ ├── .gitignore │ │ ├── Android.mk │ │ ├── Makefile │ │ ├── README.md │ │ ├── demo1_kernel.c │ │ ├── demo1_user.c │ │ ├── demo2_kernel.c │ │ ├── demo2_user.c │ │ ├── demo3_kernel.c │ │ ├── demo3_user.c │ │ ├── genl.png │ │ ├── genl_data.png │ │ ├── netlinkmsg.png │ │ └── nl00.png │ ├── notify_chain │ │ ├── .gitignore │ │ ├── AAAAA_chain.h │ │ ├── Makefile │ │ ├── README.md │ │ ├── call_flow.png │ │ ├── call_flow.txt │ │ ├── chain_core.c │ │ ├── demo1_core.c │ │ ├── demo1_notifier.c │ │ ├── demo1_register.c │ │ ├── notifier.c │ │ └── register.c │ ├── platform_driver_test │ │ ├── .gitignore │ │ ├── Makefile │ │ ├── README.md │ │ ├── VCC_TP.png │ │ ├── lock_test.dtsi │ │ ├── locks.md │ │ ├── mutex_test.c │ │ ├── show_store_pf.c │ │ ├── show_store_pf.dtsi │ │ ├── skeleton_ss.c │ │ ├── skeleton_ss.dtsi │ │ ├── skeleton_ss.h │ │ ├── spinlock_test.c │ │ ├── test_pf.c │ │ └── test_pf.dtsi │ ├── pwm │ │ ├── .gitignore │ │ ├── Makefile │ │ ├── README.md │ │ ├── pwm01.png │ │ ├── pwm02.png │ │ ├── pwm_backlight.c │ │ └── pwm_backlight.dtsi │ ├── regmap │ │ ├── .gitignore │ │ ├── Makefile │ │ ├── README.md │ │ ├── i2c_regmap.c │ │ └── regmap.png │ ├── regulator │ │ ├── .gitignore │ │ ├── DS-ACT8846-PrB-26DEC12-M.pdf │ │ ├── Makefile │ │ ├── README.md │ │ ├── act8846.c │ │ ├── act8846.dtsi │ │ ├── act8846.h │ │ ├── consumer1.c │ │ ├── consumer2.c │ │ ├── dcdc_ldo.png │ │ ├── regulator.c │ │ ├── rk32x_LINUX3.10_pmu 20140613.pdf │ │ ├── rk818.c │ │ ├── rk818.dtsi │ │ ├── rk818.h │ │ ├── rk818_powertree.png │ │ ├── rk818_test.c │ │ ├── rk818_test.dtsi │ │ ├── table5.png │ │ ├── vcc_tp_1.png │ │ └── vcc_tp_2.png │ ├── skeleton │ │ ├── .gitignore │ │ ├── Makefile │ │ ├── README.md │ │ └── skeleton.c │ ├── spi │ │ ├── .gitignore │ │ ├── README.md │ │ ├── spi0_cs.png │ │ ├── spi1_cs.png │ │ ├── spi2_cs.png │ │ └── spi2uart.c │ ├── timer │ │ ├── .gitignore │ │ ├── Makefile │ │ ├── README.md │ │ └── mytimer_test.c │ ├── timer_workq │ │ ├── .gitignore │ │ ├── Makefile │ │ ├── README.md │ │ └── timer_workq.c │ ├── uart │ │ ├── Android.mk │ │ ├── README.md │ │ ├── uart_loop_test.c │ │ └── uart_record_rw.c │ ├── usb │ │ ├── README.md │ │ └── android_usb.md │ └── workqueue │ │ ├── .gitignore │ │ ├── Makefile │ │ ├── README.md │ │ ├── workq_test.c │ │ ├── workq_test2.c │ │ └── workq_test3.c └── script │ └── README.md ├── rk3399 ├── 1p8.png ├── 3p0.png ├── README.md ├── apio4.png ├── apio4_vdd.png ├── apio5.png ├── apps │ ├── README.md │ └── lcd_test.c ├── bsp │ ├── README.md │ └── default_storage_map.png ├── cmdline_android ├── debug │ ├── adc │ │ ├── README.md │ │ └── keys.png │ ├── camera │ │ ├── README.md │ │ ├── camera_engine.png │ │ ├── cap-isp-yuv.sh │ │ ├── cap-sensor-raw-bayer.sh │ │ ├── rkisp1.png │ │ ├── system_connection.png │ │ └── test_camera-uvc.sh │ ├── char │ │ ├── .gitignore │ │ ├── Makefile │ │ ├── README.md │ │ ├── char_skeleton_drv.c │ │ ├── char_skeleton_test.c │ │ └── spinlock.c │ ├── fiq_debugger │ │ └── README.md │ ├── gpio │ │ ├── README.md │ │ ├── gpio1.png │ │ ├── pmugrf.png │ │ └── pmugrf_gpio1a_iomux.png │ ├── i2c │ │ ├── .gitignore │ │ ├── Makefile │ │ ├── README.md │ │ ├── i2c_regmap.c │ │ ├── i2c_timing.png │ │ └── rk808.h │ ├── misc │ │ ├── Makefile │ │ ├── README.md │ │ └── vfs_rw.c │ ├── mmc │ │ └── README.md │ ├── platform_driver_test │ │ ├── .gitignore │ │ ├── Makefile │ │ ├── README.md │ │ ├── kset_skeleton.c │ │ ├── pid2task.c │ │ ├── seq_test.c │ │ ├── seq_test2.c │ │ ├── skeleton_ss.c │ │ ├── skeleton_ss.dtsi │ │ └── skeleton_ss.h │ ├── regmap │ │ ├── .gitignore │ │ ├── Makefile │ │ ├── README.md │ │ ├── i2c_regmap.c │ │ └── regmap.png │ ├── spi │ │ ├── README.md │ │ ├── spi4mode.png │ │ ├── spi_skeleton.c │ │ ├── w25q128fv.c │ │ └── w25q128fv.dtsi │ ├── timer │ │ ├── .gitignore │ │ ├── Makefile │ │ ├── README.md │ │ └── mytimer_test.c │ ├── uart │ │ └── README.md │ ├── usb │ │ ├── .gitignore │ │ ├── Makefile │ │ ├── README.md │ │ ├── USB_Debugging_and_Profiling_Techniques.pdf │ │ ├── architecture.png │ │ ├── cmd_rockusb.c │ │ ├── cmd_rockusb.h │ │ ├── mass_storage.png │ │ ├── protocol.md │ │ ├── sequenceDiagram.png │ │ ├── sequenceDiagram.txt │ │ ├── tx_in_busy.png │ │ ├── tx_in_error.png │ │ ├── tx_in_normal.png │ │ ├── tx_out_busy.png │ │ ├── tx_out_error.png │ │ ├── tx_out_normal.png │ │ ├── tx_setup_busy.png │ │ ├── tx_setup_error.png │ │ ├── tx_setup_normal.png │ │ ├── usbmon.png │ │ └── usbmouse_as_key.c │ └── wdog │ │ ├── README.md │ │ └── wdt_driver_test.c ├── drm.md ├── fw_bcm4356a2_ag.bin ├── gst.md ├── input_event.md ├── io_domain.md ├── lcd.md ├── lp079qx1.png ├── nvram_ap6356s.txt ├── parameter_android ├── parameter_linux ├── pdmap.png ├── port1.png ├── port2.png ├── port3.png ├── ramdiskfs │ └── etc │ │ ├── fstab │ │ ├── group │ │ ├── init.d │ │ └── rcS │ │ ├── inittab │ │ ├── passwd │ │ ├── profile │ │ └── sysconfig │ │ └── HOSTNAME ├── replace_gpio.sh ├── replace_pin.sh ├── rk3399_busybox_defconfig ├── rtmp.md ├── serial-getty@ttyFIQ0.service ├── serial_port.png ├── test_enc.sh ├── uboot │ ├── README.md │ └── leds.png └── xconnect.c ├── tiny4412 ├── README.md └── debug │ ├── buttons │ ├── Makefile │ ├── README.md │ ├── button1.png │ ├── button2.png │ ├── buttons.c │ └── buttons.dtsi │ └── leds │ ├── Makefile │ ├── README.md │ ├── led1.png │ ├── led2.png │ ├── leds.c │ ├── leds.dtsi │ ├── reg1.png │ └── reg2.png └── x86 ├── README.md ├── bitmap ├── Makefile └── bitmap_test.c ├── bpf ├── .gitignore ├── Makefile ├── README.md ├── demo_kern.c ├── demo_user.c ├── trace_helpers.c ├── vmexit_kern.c └── vmexit_user.c ├── crypto ├── Makefile ├── README.md └── devmem2.c ├── hlist ├── Makefile └── demo.c └── usb ├── README.md ├── comp.png ├── mouse.png ├── rd.png ├── reportid.png ├── rid.png ├── send0.png ├── send3.png ├── sr.png └── srr.png /.gitignore: -------------------------------------------------------------------------------- 1 | *.cmd 2 | *.o 3 | *.mod.c 4 | *.ko 5 | *.order 6 | Module.symvers 7 | .tmp_versions 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Linux内核驱动开发 2 | 3 | ## 各平台驱动实例 4 | 5 | [RK3399](./rk3399/README.md) 6 | 7 | [RK3288](./rk3288/README.md) 8 | 9 | [tiny4412](./tiny4412/README.md) 10 | 11 | [mini2440](./mini2440/README.md) 12 | 13 | [x86](./x86/README.md) 14 | -------------------------------------------------------------------------------- /mini2440/README.md: -------------------------------------------------------------------------------- 1 | # mini2440 2 | 3 | ## 编译器版本 4 | 5 | gcc version 4.3.2 (Sourcery G++ Lite 2008q3-72) 6 | 7 | ## uboot 8 | 9 | ### 代码和补丁 10 | 11 | u-boot-2012.04.01 12 | patch -p1 < mini2440_uboot20120401.patch 13 | 14 | ### 编译 15 | 16 | make mini2440_config 17 | 18 | ### 烧写到norflash(使用norflash启动开发板) 19 | 20 | 下载u-boot.bin到sdram 21 | 22 | loady 32000000 23 | 24 | 烧写到norflash 25 | 26 | protect off all 27 | erase 0 7ffff 28 | cp.b 32000000 0 80000 29 | 30 | ### 设置启动参数 31 | 32 | set machid 7cf ;set bootargs console=ttySAC0,115200 root=/dev/nfs nfsroot=192.168.1.100:/export/nfs_rootfs ip=192.168.1.230:192.168.1.100:192.168.1.1:255.255.255.0::eth0:off ;nfs 30000000 192.168.1.100:/export/nfs_rootfs/uImage;bootm 30000000 33 | 34 | ## kernel 35 | 36 | ### 代码和补丁 37 | 38 | linux-3.4.2 39 | patch -p1 < linux-3.4.2_camera_mini2440.patch 40 | 41 | ### 编译 42 | 43 | mkdir out 44 | make ARCH=arm CROSS_COMPILE=arm-linux- mini2440_defconfig O=out 45 | make ARCH=arm CROSS_COMPILE=arm-linux- O=out -j8 uImage 46 | -------------------------------------------------------------------------------- /rk3288/README.md: -------------------------------------------------------------------------------- 1 | # RK3288 kernel driver example 2 | 3 | ## 目录说明 4 | 5 | - app 是测试驱动的应用程序 6 | - debug 是驱动模板 7 | - script 是测试脚本 8 | 9 | ## 各模块入口 10 | 11 | [Kernel debug technic](./debug/debug_technic.md) 12 | 13 | [HELLO](./debug/hello) 14 | 15 | [I2C](./debug/i2c) 16 | 17 | [SPI](./debug/spi) 18 | 19 | [UART](./debug/uart) 20 | 21 | [USB](./debug/usb) 22 | 23 | [Regulator (ACT8846, RK818)](./debug/regulator) 24 | 25 | [Platform_Driver_Test](./debug/platform_driver_test) 26 | 27 | [PWM Backlight](./debug/pwm) 28 | 29 | [Regmap](./debug/regmap) 30 | 31 | [Audio (ES8323, ES8316)](./debug/codec) 32 | 33 | [Timer](./debug/timer) 34 | 35 | [Timer And Workqueue](./debug/timer_workq) 36 | 37 | [Workqueue](./debug/workqueue) 38 | 39 | [Notify](./debug/notify_chain) 40 | 41 | [Script](./script) 42 | 43 | [PowerDomain](./debug/misc) 44 | 45 | [GDB on android](./debug/android_gdb.md) 46 | 47 | [Generic Netlink](./debug/netlink) 48 | 49 | ## 使用方法(单独编译模块)或者放到内核目录中编译 50 | 51 | - make CC=your_compiler_path KERNELDIR=your_kernel_dir 52 | 53 | ## 举例(以hello模块为例) 54 | 55 | ### 编译内核时没有指定O选项 56 | 57 | - cd debug/hello 58 | - make CC=/3288androidsrc/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/arm-eabi-gcc KERNELDIR=/3288androidsrc/kernel 59 | 60 | ### 编译内核时有指定O选项 61 | 62 | - cd debug/hello 63 | - make CROSS_COMPILE=/3288androidsrc/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/arm-eabi- KERNEL_DIR=/3288androidsrc/kernel KERNEL_BUID_OUTPUT=/3288androidsrc/out/target/product/rk3288/obj/KERNEL 64 | -------------------------------------------------------------------------------- /rk3288/apps/Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH:= $(call my-dir) 2 | 3 | # build lcd_test 4 | include $(CLEAR_VARS) 5 | 6 | LOCAL_SYSTEM_SHARED_LIBRARIES := libc 7 | LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES) 8 | LOCAL_MODULE_TAGS := debug 9 | LOCAL_SRC_FILES := lcd_test.c 10 | LOCAL_MODULE := lcd_test 11 | 12 | include $(BUILD_EXECUTABLE) 13 | 14 | # build event parser 15 | include $(CLEAR_VARS) 16 | 17 | LOCAL_SYSTEM_SHARED_LIBRARIES := libc 18 | LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES) 19 | LOCAL_MODULE_TAGS := debug 20 | LOCAL_SRC_FILES := event_parser.c 21 | LOCAL_MODULE := event_parser 22 | 23 | include $(BUILD_EXECUTABLE) 24 | -------------------------------------------------------------------------------- /rk3288/apps/lcd_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #ifdef ANDROID_SYSTEM 10 | #define DEFAULT_FB_DEVICE "/dev/graphics/fb0" 11 | #else 12 | #define DEFAULT_FB_DEVICE "/dev/fb0" 13 | #endif 14 | 15 | /* 16 | * Usage: 17 | * Android: 18 | * # stop 19 | * ./lcd_test 20 | * # start 21 | * Linux: 22 | * ./lcd_test 23 | */ 24 | int main(int argc, char *argv[]) 25 | { 26 | int fd = 0; 27 | struct fb_var_screeninfo vinfo; 28 | struct fb_fix_screeninfo finfo; 29 | long int screensize = 0; 30 | char *fbp = 0; 31 | int x = 0, y = 0; 32 | long int location = 0; 33 | 34 | /* Open the file for reading and writing */ 35 | fd = open(DEFAULT_FB_DEVICE, O_RDWR); 36 | if (fd == -1) { 37 | perror("Error: cannot open framebuffer device"); 38 | exit(1); 39 | } 40 | printf("The framebuffer device was opened successfully.\n"); 41 | 42 | /* Get fixed screen information */ 43 | if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1) { 44 | perror("Error reading fixed information"); 45 | exit(2); 46 | } 47 | 48 | /* Get variable screen information */ 49 | if (ioctl(fd, FBIOGET_VSCREENINFO, &vinfo) == -1) { 50 | perror("Error reading variable information"); 51 | exit(3); 52 | } 53 | 54 | printf("%dx%d, %dbpp\n", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel); 55 | 56 | /* Figure out the size of the screen in bytes */ 57 | screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8; 58 | 59 | /* Map the device to memory */ 60 | fbp = (char *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 61 | if (fbp < 0) { 62 | perror("Error: failed to map framebuffer device to memory"); 63 | exit(4); 64 | } 65 | printf("The framebuffer device was mapped to memory successfully.\n"); 66 | 67 | /* Figure out where in memory to put the pixel */ 68 | for (y = 0; y < vinfo.yres; y++) 69 | { 70 | for (x = 0; x < vinfo.xres; x++) 71 | { 72 | location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + 73 | (y+vinfo.yoffset) * finfo.line_length; 74 | 75 | if (vinfo.bits_per_pixel == 32) 76 | { 77 | *(fbp + location) = 100;// Some blue 78 | *(fbp + location + 1) = 15+(x-100)/2; // A little green 79 | *(fbp + location + 2) = 200-(y-100)/5;// A lot of red 80 | *(fbp + location + 3) = 0;// No transparency 81 | } 82 | else //assume 16bpp 83 | { 84 | int b = 10; 85 | int g = (x-100)/6; // A little green 86 | int r = 31-(y-100)/16;// A lot of red 87 | unsigned short int t = r<<11 | g << 5 | b; 88 | *((unsigned short int*)(fbp + location)) = t; 89 | } 90 | } 91 | } 92 | 93 | munmap(fbp, screensize); 94 | close(fd); 95 | return 0; 96 | } 97 | -------------------------------------------------------------------------------- /rk3288/apps/test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #define MISC_DEV_NAME "/dev/myledmiscname" 12 | 13 | #define IOCTL_INT_VALUE 0 14 | #define IOCTL_STRING_VALUE 1 15 | 16 | int main (int argc, char *argv[]) 17 | { 18 | int ret; 19 | int fd; 20 | char datas[] = "abcdefg"; 21 | 22 | fd = open(MISC_DEV_NAME, O_RDWR); 23 | if (fd < 0) 24 | return -1; 25 | 26 | ret = ioctl(fd, IOCTL_INT_VALUE, 911); 27 | if (ret < 0) 28 | { 29 | printf("error, %d\n", __LINE__); 30 | return -1; 31 | } 32 | 33 | ret = ioctl(fd, IOCTL_STRING_VALUE, datas); 34 | if (ret < 0) 35 | { 36 | printf("error, %d\n", __LINE__); 37 | return -1; 38 | } 39 | 40 | ret = close(fd); 41 | 42 | return 0; 43 | } 44 | -------------------------------------------------------------------------------- /rk3288/buildenv: -------------------------------------------------------------------------------- 1 | CROSS_COMPILE=/path_to_you_cross_compile/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/arm-eabi- 2 | KERNEL_DIR=/you_kerne_source_code/kernel 3 | KERNEL_BUILD_OUTPUT=/kernel_build_outfiles/out/target/product/rk3288/obj/KERNEL 4 | -------------------------------------------------------------------------------- /rk3288/debug/codec/.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.ko 3 | *.cmd 4 | Module.symvers 5 | modules.order 6 | .tmp_versions/ 7 | *.mod.c 8 | *.mod.c 9 | -------------------------------------------------------------------------------- /rk3288/debug/codec/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile 2 | # Comment/uncomment the following line to disable/enable debugging 3 | # DEBUG = y 4 | 5 | # Usage 6 | # make CROSS_COMPILE= KERNEL_DIR= KERNEL_BUID_OUTPUT= 7 | # 8 | # make CROSS_COMPILE=/home/zeroway/rk3399/tool/gcc-linaro-4.9.4-2017.01-i686_aarch64-linux-gnu/bin/aarch64-linux-gnu- KERNEL_DIR=/home/zeroway/rk3399/src/firefly/kernel KERNEL_BUID_OUTPUT=/home/zeroway/rk3399/src/firefly/out/target/product/rk3399_firefly_box/obj/KERNEL 9 | 10 | # Add your debugging flag (or not) to CFLAGS 11 | ifeq ($(DEBUG),y) 12 | DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines 13 | else 14 | DEBFLAGS = -O2 15 | endif 16 | 17 | obj-m := skeleton_ss.o 18 | obj-m += kset_skeleton.o 19 | obj-m += seq_test.o 20 | obj-m += seq_test2.o 21 | obj-m += seq_test3.o 22 | obj-m += pid2task.o 23 | 24 | KERNEL_DIR ?= /lib/modules/$(shell uname -r)/build 25 | KERNEL_BUID_OUTPUT ?=$(KERNEL_DIR) 26 | CC = $(CROSS_COMPILE)gcc 27 | LD = $(CROSS_COMPILE)ld 28 | PWD := $(shell pwd) 29 | 30 | modules: 31 | $(MAKE) -C $(KERNEL_DIR) ARCH=arm64 M=$(PWD) O=$(KERNEL_BUID_OUTPUT) modules 32 | 33 | clean: 34 | rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions modules.order Module.symvers 35 | 36 | depend .depend dep: 37 | $(CC) $(CFLAGS) -M *.c > .depend 38 | 39 | ifeq (.depend,$(wildcard .depend)) 40 | include .depend 41 | endif 42 | -------------------------------------------------------------------------------- /rk3288/debug/codec/es8316.dtsi: -------------------------------------------------------------------------------- 1 | / { 2 | rockchip-es8316 { 3 | compatible = "rockchip-es8316"; 4 | dais { 5 | dai0 { 6 | audio-codec = <&es8316>; 7 | audio-controller = <&i2s>; 8 | format = "i2s"; 9 | }; 10 | }; 11 | }; 12 | }; 13 | 14 | &i2c2 { 15 | es8316: es8316@10 { 16 | compatible = "es8316"; 17 | reg = <0x10>; 18 | spk-con-gpio = <&gpio7 GPIO_B7 GPIO_ACTIVE_LOW>; 19 | hp-con-gpio = <&gpio0 GPIO_B5 GPIO_ACTIVE_HIGH>; 20 | hp-det-gpio = <&gpio7 GPIO_A4 GPIO_ACTIVE_HIGH>; 21 | }; 22 | }; 23 | -------------------------------------------------------------------------------- /rk3288/debug/codec/es8323.dtsi: -------------------------------------------------------------------------------- 1 | / { 2 | rockchip-es8323 { 3 | compatible = "rockchip-es8323"; 4 | dais { 5 | dai0 { 6 | audio-codec = <&es8323>; 7 | audio-controller = <&i2s>; 8 | format = "i2s"; 9 | }; 10 | }; 11 | }; 12 | }; 13 | 14 | &i2c2 { 15 | es8323: es8323@10 { 16 | compatible = "es8323"; 17 | reg = <0x10>; 18 | spk-con-gpio = <&gpio7 GPIO_B7 GPIO_ACTIVE_HIGH>; 19 | hp-con-gpio = <&gpio0 GPIO_B5 GPIO_ACTIVE_HIGH>; 20 | hp-det-gpio = <&gpio7 GPIO_A4 GPIO_ACTIVE_HIGH>; 21 | }; 22 | }; 23 | -------------------------------------------------------------------------------- /rk3288/debug/codec/pngs/I2S_DMA.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3288/debug/codec/pngs/I2S_DMA.png -------------------------------------------------------------------------------- /rk3288/debug/codec/pngs/I2S_INT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3288/debug/codec/pngs/I2S_INT.png -------------------------------------------------------------------------------- /rk3288/debug/codec/pngs/I2S_MAP.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3288/debug/codec/pngs/I2S_MAP.png -------------------------------------------------------------------------------- /rk3288/debug/codec/pngs/I2S_REG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3288/debug/codec/pngs/I2S_REG.png -------------------------------------------------------------------------------- /rk3288/debug/codec/pngs/Spatial-Audio-Diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3288/debug/codec/pngs/Spatial-Audio-Diagram.png -------------------------------------------------------------------------------- /rk3288/debug/codec/pngs/analog_input.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3288/debug/codec/pngs/analog_input.png -------------------------------------------------------------------------------- /rk3288/debug/codec/pngs/audio_adapter0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3288/debug/codec/pngs/audio_adapter0.jpg -------------------------------------------------------------------------------- /rk3288/debug/codec/pngs/audio_adapter1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3288/debug/codec/pngs/audio_adapter1.jpg -------------------------------------------------------------------------------- /rk3288/debug/codec/pngs/bpfs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3288/debug/codec/pngs/bpfs.png -------------------------------------------------------------------------------- /rk3288/debug/codec/pngs/codec_block_diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3288/debug/codec/pngs/codec_block_diagram.png -------------------------------------------------------------------------------- /rk3288/debug/codec/pngs/es8323.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3288/debug/codec/pngs/es8323.png -------------------------------------------------------------------------------- /rk3288/debug/codec/pngs/hp_ctl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3288/debug/codec/pngs/hp_ctl.png -------------------------------------------------------------------------------- /rk3288/debug/codec/pngs/hp_det.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3288/debug/codec/pngs/hp_det.png -------------------------------------------------------------------------------- /rk3288/debug/codec/pngs/hp_mux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3288/debug/codec/pngs/hp_mux.png -------------------------------------------------------------------------------- /rk3288/debug/codec/pngs/line-mic0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3288/debug/codec/pngs/line-mic0.png -------------------------------------------------------------------------------- /rk3288/debug/codec/pngs/line-mic1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3288/debug/codec/pngs/line-mic1.png -------------------------------------------------------------------------------- /rk3288/debug/codec/pngs/mixer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3288/debug/codec/pngs/mixer.png -------------------------------------------------------------------------------- /rk3288/debug/codec/pngs/reg13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3288/debug/codec/pngs/reg13.png -------------------------------------------------------------------------------- /rk3288/debug/codec/pngs/reg22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3288/debug/codec/pngs/reg22.png -------------------------------------------------------------------------------- /rk3288/debug/codec/pngs/reg24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3288/debug/codec/pngs/reg24.png -------------------------------------------------------------------------------- /rk3288/debug/codec/pngs/reg32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3288/debug/codec/pngs/reg32.png -------------------------------------------------------------------------------- /rk3288/debug/codec/pngs/spk_ctl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3288/debug/codec/pngs/spk_ctl.png -------------------------------------------------------------------------------- /rk3288/debug/codec/pngs/trrs.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3288/debug/codec/pngs/trrs.jpg -------------------------------------------------------------------------------- /rk3288/debug/codec/pngs/trrs1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3288/debug/codec/pngs/trrs1.jpg -------------------------------------------------------------------------------- /rk3288/debug/codec/pngs/trs.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3288/debug/codec/pngs/trs.jpg -------------------------------------------------------------------------------- /rk3288/debug/codec/pngs/trs1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3288/debug/codec/pngs/trs1.jpg -------------------------------------------------------------------------------- /rk3288/debug/codec/pngs/ts.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3288/debug/codec/pngs/ts.jpg -------------------------------------------------------------------------------- /rk3288/debug/enter_kgdb_mode.sh: -------------------------------------------------------------------------------- 1 | adb shell "echo 0 > /proc/sys/kernel/watchdog" 2 | adb shell "echo 'ttyFIQ0,115200' > /sys/module/kgdboc/parameters/kgdboc" 3 | adb shell "echo g > /proc/sysrq-trigger" 4 | -------------------------------------------------------------------------------- /rk3288/debug/env_debug_kernel.cmd: -------------------------------------------------------------------------------- 1 | set remotebaud 115200 2 | target remote /dev/ttyUSB0 3 | file vmlinux 4 | -------------------------------------------------------------------------------- /rk3288/debug/hello/.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.ko 3 | *.cmd 4 | Module.symvers 5 | modules.order 6 | .tmp_versions/ 7 | *.mod.c 8 | *.mod.c 9 | -------------------------------------------------------------------------------- /rk3288/debug/hello/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile 2 | # Comment/uncomment the following line to disable/enable debugging 3 | # DEBUG = y 4 | 5 | # Usage 6 | # make CC= KERNELDIR= 7 | # 8 | # make CC=/home/zeroway/3288/src/3288_4.4/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/arm-eabi-gcc KERNELDIR=/home/zeroway/3288/src/3288_4.4/kernel 9 | 10 | # Add your debugging flag (or not) to CFLAGS 11 | ifeq ($(DEBUG),y) 12 | DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines 13 | else 14 | DEBFLAGS = -O2 15 | endif 16 | 17 | obj-m := hello.o 18 | KERNELDIR ?= /lib/modules/$(shell uname -r)/build 19 | CC ?= gcc 20 | PWD := $(shell pwd) 21 | 22 | modules: 23 | $(MAKE) -C $(KERNELDIR) M=$(PWD) modules 24 | 25 | clean: 26 | rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions modules.order Module.symvers 27 | 28 | depend .depend dep: 29 | $(CC) $(CFLAGS) -M *.c > .depend 30 | 31 | ifeq (.depend,$(wildcard .depend)) 32 | include .depend 33 | endif 34 | -------------------------------------------------------------------------------- /rk3288/debug/hello/README.md: -------------------------------------------------------------------------------- 1 | # 如何定位内核空指针崩溃问题 2 | 3 | 加载模块(insmod hello.ko)后系统崩溃的日志如下 4 | 5 | ```shell 6 | [ 574.755500] Unable to handle kernel NULL pointer dereference at virtual address 00000000 7 | [ 574.763511] pgd = dc268000 8 | [ 574.766174] [00000000] *pgd=00000000 9 | [ 574.769704] Internal error: Oops: 5 [#1] PREEMPT SMP ARM 10 | [ 574.774924] Modules linked in: hello(O+) mali_kbase 11 | [ 574.779756] CPU: 3 PID: 1083 Comm: insmod Tainted: G O 3.10.0 #25 12 | [ 574.786599] task: dc0c4440 ti: dea54000 task.ti: dea54000 13 | [ 574.791911] PC is at hello_init+0x10/0x2c [hello] 14 | [ 574.796541] LR is at do_one_initcall+0x34/0xc8 15 | [ 574.800911] pc : [] lr : [] psr: 600f0013 16 | [ 574.800911] sp : dea55f18 ip : 00000000 fp : 00000bd4 17 | [ 574.812190] r10: 00000000 r9 : dea54000 r8 : c0cfb000 18 | [ 574.817325] r7 : 00000000 r6 : dea54000 r5 : bf02b000 r4 : 00000000 19 | [ 574.823740] r3 : 00000000 r2 : 0000000d r1 : bf029028 r0 : bf02b000 20 | [ 574.830157] Flags: nZCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user 21 | [ 574.837169] Control: 10c5387d Table: 1c26806a DAC: 00000015 22 | ``` 23 | 24 | 从上面可以知道错误处在hello模块的hello_init函数里 25 | 26 | 错误发生是PC指针指向hello_init+0x10行 27 | 28 | ```shell 29 | [ 574.791911] PC is at hello_init+0x10/0x2c [hello] 30 | ``` 31 | 32 | 从反汇编得到相应代码方法如下 33 | 34 | ```shell 35 | arm-eabi-objdump your_module.ko -D > output.dis 36 | ``` 37 | 38 | 比如我是通过下面这样得到的 39 | 40 | ```shell 41 | /home/zeroway/3288/src/3288_4.4/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/arm-eabi-objdump hello.ko -D > hello.dis 42 | ``` 43 | 44 | 在反汇编文件里找到相应的位置 45 | 46 | ```shell 47 | 00000000 : 48 | 0: e92d4010 push {r4, lr} 49 | 4: e3a04000 mov r4, #0 50 | 8: e59f1014 ldr r1, [pc, #20] ; 24 51 | c: e3a0200d mov r2, #13 52 | 10: e5d43000 ldrb r3, [r4] 53 | ``` 54 | 55 | 错误地址是hello_init,也就是init_module的地方 56 | 57 | r4 为变量t 58 | push {r4, lr} 是压栈操作 59 | move r4, #0 对应 t = NULL 60 | ldr r1, [pc, #20] 这里打印__FUNCTION__ 61 | mov r2, #13 是对应行号 62 | ldrb r3, [r4] 这里将r4存入r3,但是这里r4是空指针,所以这里崩溃了 63 | 64 | 对应hello_init如下,其中printk是代码的第13行 65 | 66 | ```c 67 | static int __init hello_init(void) 68 | { 69 | struct test *t = NULL; 70 | 71 | printk("%s, %d, tmp = %s\n", __FUNCTION__, __LINE__, t->name); 72 | return 0; 73 | } 74 | ``` 75 | -------------------------------------------------------------------------------- /rk3288/debug/hello/hello.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | struct test { 5 | char name; 6 | int age; 7 | }; 8 | 9 | static int __init hello_init(void) 10 | { 11 | struct test *t = NULL; 12 | 13 | printk("%s, %d, tmp = %s\n", __FUNCTION__, __LINE__, t->name); 14 | return 0; 15 | } 16 | 17 | static void hello_exit (void) 18 | { 19 | printk("%s, %d\n", __FUNCTION__, __LINE__); 20 | } 21 | 22 | module_init(hello_init); 23 | module_exit(hello_exit); 24 | MODULE_LICENSE("GPL"); 25 | -------------------------------------------------------------------------------- /rk3288/debug/i2c/.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.ko 3 | *.cmd 4 | Module.symvers 5 | modules.order 6 | .tmp_versions/ 7 | *.mod.c 8 | *.mod.c 9 | -------------------------------------------------------------------------------- /rk3288/debug/i2c/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile 2 | # Comment/uncomment the following line to disable/enable debugging 3 | # DEBUG = y 4 | 5 | # Usage 6 | # make CROSS_COMPILE= KERNEL_DIR= KERNEL_BUID_OUTPUT= 7 | # 8 | # make CROSS_COMPILE=/home/zeroway/rk3399/tool/gcc-linaro-4.9.4-2017.01-i686_aarch64-linux-gnu/bin/aarch64-linux-gnu- KERNEL_DIR=/home/zeroway/rk3399/src/firefly/kernel KERNEL_BUID_OUTPUT=/home/zeroway/rk3399/src/firefly/out/target/product/rk3399_firefly_box/obj/KERNEL 9 | 10 | # Add your debugging flag (or not) to CFLAGS 11 | ifeq ($(DEBUG),y) 12 | DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines 13 | else 14 | DEBFLAGS = -O2 15 | endif 16 | 17 | obj-m := myi2c.o 18 | 19 | KERNEL_DIR ?= /lib/modules/$(shell uname -r)/build 20 | KERNEL_BUID_OUTPUT ?=$(KERNEL_DIR) 21 | CC = $(CROSS_COMPILE)gcc 22 | LD = $(CROSS_COMPILE)ld 23 | PWD := $(shell pwd) 24 | 25 | modules: 26 | $(MAKE) -C $(KERNEL_DIR) ARCH=arm64 M=$(PWD) O=$(KERNEL_BUID_OUTPUT) modules 27 | 28 | clean: 29 | rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions modules.order Module.symvers 30 | 31 | depend .depend dep: 32 | $(CC) $(CFLAGS) -M *.c > .depend 33 | 34 | ifeq (.depend,$(wildcard .depend)) 35 | include .depend 36 | endif 37 | -------------------------------------------------------------------------------- /rk3288/debug/i2c/README.md: -------------------------------------------------------------------------------- 1 | # I2C 2 | 3 | ## UBOOT 下 I2C 4 | 5 | 在UBOOT下测试硬件是否正常 6 | 7 | 确认UBOOT中对I2C支持,一般会有相应命令 8 | 9 | uboot # i2c 10 | i2c - I2C sub-system 11 | 12 | Usage: 13 | i2c crc32 chip address[.0, .1, .2] count - compute CRC32 checksum 14 | i2c dev [dev] - show or set current I2C bus 15 | i2c loop chip address[.0, .1, .2] [# of objects] - looping read of device 16 | i2c md chip address[.0, .1, .2] [# of objects] - read from I2C device 17 | i2c mm chip address[.0, .1, .2] - write to I2C device (auto-incrementing) 18 | i2c mw chip address[.0, .1, .2] value [count] - write to I2C device (fill) 19 | i2c nm chip address[.0, .1, .2] - write to I2C device (constant address) 20 | i2c probe [address] - test for and show device(s) on the I2C bus 21 | i2c read chip address[.0, .1, .2] length memaddress - read to memory 22 | i2c write memaddress chip address[.0, .1, .2] length - write memory to i2c 23 | i2c reset - re-init the I2C Controller 24 | i2c speed [speed] - show or set I2C bus speed 25 | 26 | 查看当前使用的I2C BUS 27 | 28 | uboot # i2c dev 29 | Current bus is 0 30 | 31 | 查询该总线下接的所有I2C设备 32 | 33 | uboot # i2c probe 34 | Valid chip addresses: 14 40 41 51 55 5A 35 | 36 | 如果是下面这样的输出,则说明该总线有异常,极大可能是有I2C设备拉低了总线 37 | 38 | uboot # i2c probe 39 | Valid chip addresses:I2C Send Start Bit Timeout 40 | I2C Send Start Bit Timeout 41 | 42 | 切换I2C BUS 43 | 44 | uboot # i2c dev 1 45 | Setting bus to 1 46 | -------------------------------------------------------------------------------- /rk3288/debug/i2c/myi2c.dtsi: -------------------------------------------------------------------------------- 1 | &i2c0 { 2 | myi2c@36 { 3 | compatible = "myi2c"; 4 | status = "okay"; 5 | reg = <0x36>; 6 | }; 7 | }; 8 | -------------------------------------------------------------------------------- /rk3288/debug/interrupt/.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.ko 3 | *.cmd 4 | Module.symvers 5 | modules.order 6 | .tmp_versions/ 7 | *.mod.c 8 | *.mod.c 9 | -------------------------------------------------------------------------------- /rk3288/debug/interrupt/Makefile: -------------------------------------------------------------------------------- 1 | # Add your debugging flag (or not) to CFLAGS 2 | ifeq ($(DEBUG),y) 3 | DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines 4 | else 5 | DEBFLAGS = -O2 6 | endif 7 | 8 | obj-m := crypto-drv.o 9 | KERNELDIR ?= /lib/modules/$(shell uname -r)/build 10 | CC ?= gcc 11 | PWD := $(shell pwd) 12 | 13 | modules: 14 | $(MAKE) -C $(KERNELDIR) M=$(PWD) modules 15 | 16 | clean: 17 | rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions modules.order Module.symvers 18 | 19 | depend .depend dep: 20 | $(CC) $(CFLAGS) -M *.c > .depend 21 | 22 | ifeq (.depend,$(wildcard .depend)) 23 | include .depend 24 | endif 25 | -------------------------------------------------------------------------------- /rk3288/debug/interrupt/test.dtsi: -------------------------------------------------------------------------------- 1 | / { 2 | my_test_node { 3 | compatible = "test_platform"; 4 | irq_gpio = <&gpio0 GPIO_B1 IRQ_TYPE_EDGE_FALLING>; 5 | }; 6 | }; 7 | -------------------------------------------------------------------------------- /rk3288/debug/kernel_list_usage/.gitignore: -------------------------------------------------------------------------------- 1 | *.cmd 2 | *.o 3 | *.mod.c 4 | *.ko 5 | *.order 6 | Module.symvers 7 | .tmp_versions 8 | -------------------------------------------------------------------------------- /rk3288/debug/kernel_list_usage/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile 2 | # Comment/uncomment the following line to disable/enable debugging 3 | # DEBUG = y 4 | 5 | # Usage 6 | # make CROSS_COMPILE= KERNEL_DIR= KERNEL_BUID_OUTPUT= 7 | # 8 | # make CROSS_COMPILE=/home/zeroway/rk3399/tool/gcc-linaro-4.9.4-2017.01-i686_aarch64-linux-gnu/bin/aarch64-linux-gnu- KERNEL_DIR=/home/zeroway/rk3399/src/firefly/kernel KERNEL_BUID_OUTPUT=/home/zeroway/rk3399/src/firefly/out/target/product/rk3399_firefly_box/obj/KERNEL 9 | 10 | # Add your debugging flag (or not) to CFLAGS 11 | ifeq ($(DEBUG),y) 12 | DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines 13 | else 14 | DEBFLAGS = -O2 15 | endif 16 | 17 | obj-m := i2c_regmap.o 18 | 19 | KERNEL_DIR ?= /lib/modules/$(shell uname -r)/build 20 | KERNEL_BUID_OUTPUT ?=$(KERNEL_DIR) 21 | CC = $(CROSS_COMPILE)gcc 22 | LD = $(CROSS_COMPILE)ld 23 | PWD := $(shell pwd) 24 | 25 | modules: 26 | $(MAKE) -C $(KERNEL_DIR) ARCH=arm64 M=$(PWD) O=$(KERNEL_BUID_OUTPUT) modules 27 | 28 | clean: 29 | rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions modules.order Module.symvers 30 | 31 | depend .depend dep: 32 | $(CC) $(CFLAGS) -M *.c > .depend 33 | 34 | ifeq (.depend,$(wildcard .depend)) 35 | include .depend 36 | endif 37 | -------------------------------------------------------------------------------- /rk3288/debug/kernel_list_usage/list_usage.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | static LIST_HEAD(person_list); 6 | struct person 7 | { 8 | char name[20]; 9 | struct list_head list; 10 | }; 11 | 12 | /* add a person to the person list */ 13 | void add_person(const char *person_name) 14 | { 15 | struct person *tmp; 16 | tmp = kmalloc(sizeof(struct person), GFP_KERNEL); 17 | if (NULL == tmp) 18 | { 19 | printk("error\n"); 20 | return -1; 21 | } 22 | 23 | strcpy(tmp->name, person_name); 24 | list_add(&tmp->list, &person_list); 25 | } 26 | 27 | const char *players[] = { 28 | "jordan", 29 | "eminem", 30 | "shady" 31 | }; 32 | 33 | void check_person_list(void) 34 | { 35 | struct person *ps; 36 | list_for_each_entry(ps, &person_list, list) { 37 | printk("%s, %d, %s\n", __FUNCTION__, __LINE__, ps->name); 38 | } 39 | } 40 | 41 | static int kernel_list_init(void) 42 | { 43 | int i; 44 | 45 | /* add player to the list */ 46 | for (i = 0; i < sizeof(players) / sizeof(players[0]); i++) 47 | add_person(players[i]); 48 | 49 | check_person_list(); 50 | return 0; 51 | } 52 | 53 | static void kernel_list_exit (void) 54 | { 55 | printk("%s, %d\n", __FUNCTION__, __LINE__); 56 | } 57 | 58 | module_init(kernel_list_init); 59 | module_exit(kernel_list_exit); 60 | MODULE_LICENSE("GPL"); 61 | -------------------------------------------------------------------------------- /rk3288/debug/led/.gitignore: -------------------------------------------------------------------------------- 1 | *.cmd 2 | *.o 3 | *.mod.c 4 | *.ko 5 | *.order 6 | Module.symvers 7 | .tmp_versions 8 | -------------------------------------------------------------------------------- /rk3288/debug/led/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile 2 | # Comment/uncomment the following line to disable/enable debugging 3 | # DEBUG = y 4 | 5 | # Usage 6 | # make CC= KERNELDIR= 7 | # 8 | # make CC=/home/zeroway/3288/src/3288_4.4/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/arm-eabi-gcc KERNELDIR=/home/zeroway/3288/src/3288_4.4/kernel 9 | 10 | # Add your debugging flag (or not) to CFLAGS 11 | ifeq ($(DEBUG),y) 12 | DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines 13 | else 14 | DEBFLAGS = -O2 15 | endif 16 | 17 | obj-m := myled.o 18 | KERNELDIR ?= /lib/modules/$(shell uname -r)/build 19 | CC ?= gcc 20 | PWD := $(shell pwd) 21 | 22 | modules: 23 | $(MAKE) -C $(KERNELDIR) M=$(PWD) modules 24 | 25 | clean: 26 | rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions modules.order Module.symvers 27 | 28 | depend .depend dep: 29 | $(CC) $(CFLAGS) -M *.c > .depend 30 | 31 | ifeq (.depend,$(wildcard .depend)) 32 | include .depend 33 | endif 34 | -------------------------------------------------------------------------------- /rk3288/debug/led/myled.c: -------------------------------------------------------------------------------- 1 | #include "myled.h" 2 | 3 | static long myled_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 4 | { 5 | void __user *argp = (void __user *)arg; 6 | char msg[1024]; 7 | 8 | switch (cmd) 9 | { 10 | case IOCTL_INT_VALUE: 11 | printk("cmd: %d arg = %ld, %s, %d\n", cmd, arg, __FUNCTION__, __LINE__); 12 | break; 13 | case IOCTL_STRING_VALUE: 14 | if (copy_from_user(&msg, argp, sizeof(msg))) 15 | { 16 | printk("error fault\n"); 17 | return -EFAULT; 18 | } 19 | 20 | printk("msg = %s\n", msg); 21 | break; 22 | default: 23 | break; 24 | } 25 | 26 | return 0; 27 | } 28 | 29 | static int myled_release(struct inode *inode, struct file *file) 30 | { 31 | printk("%s, %d\n", __FUNCTION__, __LINE__); 32 | return 0; 33 | } 34 | 35 | static int myled_open(struct inode *inode, struct file *file) 36 | { 37 | printk("%s, %d\n", __FUNCTION__, __LINE__); 38 | return 0; 39 | } 40 | 41 | static struct file_operations myled_fops = { 42 | .owner = THIS_MODULE, 43 | .open = myled_open, 44 | .release = myled_release, 45 | .unlocked_ioctl = myled_ioctl 46 | }; 47 | 48 | static struct miscdevice myled_misc = { 49 | .minor = MISC_DYNAMIC_MINOR, 50 | .name = "myledmiscname", 51 | .fops = &myled_fops 52 | }; 53 | 54 | static int __exit myled_remove(struct platform_device *pdev) 55 | { 56 | printk("%s, %d\n", __FUNCTION__, __LINE__); 57 | misc_deregister(&myled_misc); 58 | return 0; 59 | } 60 | 61 | static int myled_probe(struct platform_device *pdev) 62 | { 63 | int rc; 64 | printk("%s, %d\n", __FUNCTION__, __LINE__); 65 | rc = misc_register(&myled_misc); 66 | if (rc < 0) { 67 | pr_err("%s: could not register misc device\n", __func__); 68 | return -1; 69 | } 70 | 71 | return 0; 72 | } 73 | 74 | #if 0//需要在DT里root节点下添加myled的节点 75 | /{ 76 | myled { 77 | compatible = "myled"; 78 | }; 79 | 80 | } 81 | #endif 82 | static const struct of_device_id myled_dt_ids[] = { 83 | { .compatible = "myled", .data = NULL, }, 84 | { /* sentinel */ } 85 | }; 86 | MODULE_DEVICE_TABLE(of, myled_dt_ids); 87 | 88 | static struct platform_driver myled_driver = { 89 | .driver = { 90 | .name = "myled", 91 | .owner = THIS_MODULE, 92 | .of_match_table = myled_dt_ids, 93 | }, 94 | .probe = myled_probe, 95 | .remove = myled_remove, 96 | }; 97 | 98 | module_platform_driver(myled_driver); 99 | 100 | MODULE_DESCRIPTION("led driver"); 101 | MODULE_LICENSE("GPL"); 102 | -------------------------------------------------------------------------------- /rk3288/debug/led/myled.h: -------------------------------------------------------------------------------- 1 | #ifndef _MYLED_H_ 2 | #define _MYLED_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #define IOCTL_INT_VALUE 0 26 | #define IOCTL_STRING_VALUE 1 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /rk3288/debug/misc/.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.ko 3 | *.cmd 4 | Module.symvers 5 | modules.order 6 | .tmp_versions/ 7 | *.mod.c 8 | *.mod.c 9 | -------------------------------------------------------------------------------- /rk3288/debug/misc/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile 2 | # Comment/uncomment the following line to disable/enable debugging 3 | # DEBUG = y 4 | 5 | # Usage 6 | # make CROSS_COMPILE= KERNEL_DIR= KERNEL_BUID_OUTPUT= 7 | # 8 | 9 | PWD := $(shell pwd) 10 | BUILD_ENV = $(PWD)/../../buildenv 11 | cross_compiler_prefix = $(shell awk -F "CROSS_COMPILE=" '/CROSS_COMPILE=/{print $$2}' $(BUILD_ENV)) 12 | kernel_output = $(shell awk -F "KERNEL_BUILD_OUTPUT=" '/KERNEL_BUILD_OUTPUT=/{print $$2}' $(BUILD_ENV)) 13 | kernel_dir = $(shell awk -F "KERNEL_DIR=" '/KERNEL_DIR=/{print $$2}' $(BUILD_ENV)) 14 | 15 | # Add your debugging flag (or not) to CFLAGS 16 | ifeq ($(DEBUG),y) 17 | DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines 18 | else 19 | DEBFLAGS = -O2 20 | endif 21 | 22 | obj-m := uk_io.o 23 | obj-m += vfs_rw.o 24 | obj-m += wei.o 25 | 26 | KERNEL_DIR ?= /lib/modules/$(shell uname -r)/build 27 | KERNEL_BUID_OUTPUT ?=$(KERNEL_DIR) 28 | CC = $(CROSS_COMPILE)gcc 29 | LD = $(CROSS_COMPILE)ld 30 | PWD := $(shell pwd) 31 | 32 | modules: 33 | $(MAKE) CROSS_COMPILE=$(cross_compiler_prefix) -C $(kernel_dir) O=$(kernel_output) M=$(PWD) modules 34 | 35 | clean: 36 | rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions modules.order Module.symvers 37 | 38 | depend .depend dep: 39 | $(CC) $(CFLAGS) -M *.c > .depend 40 | 41 | ifeq (.depend,$(wildcard .depend)) 42 | include .depend 43 | endif 44 | -------------------------------------------------------------------------------- /rk3288/debug/misc/README.md: -------------------------------------------------------------------------------- 1 | # PowerDomain 2 | 3 | WIFI_PWR由GPIO4_D3控制,对应的电源域是APIO3,由datasheet中可以查到 4 | 5 | ![GPIO4_D3电源域APIO3](./power_domain01.png) 6 | 7 | ![GPIO4_D3电源域APIO3](./power_domain00.png) 8 | 9 | APIO3_VDD电源由PMU上LDO(VCC_WL)提供电源,所以GPIO4_D3上电时序肯定是在VCC_WL之后 10 | 即使在代码中先操作GPIO4_D3的gpio,后使能regulator,但是用示波器量的结果始终是先有VCC_WL后有GPIO4_D3 11 | -------------------------------------------------------------------------------- /rk3288/debug/misc/power_domain00.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3288/debug/misc/power_domain00.png -------------------------------------------------------------------------------- /rk3288/debug/misc/power_domain01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3288/debug/misc/power_domain01.png -------------------------------------------------------------------------------- /rk3288/debug/misc/uk_io.dtsi: -------------------------------------------------------------------------------- 1 | / { 2 | uk_io_node { 3 | compatible = "test_platform"; 4 | }; 5 | }; 6 | -------------------------------------------------------------------------------- /rk3288/debug/misc/uk_io_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define DEVICE_NODE "/dev/user_kernel_io" 9 | 10 | #define GET_VALUE 10 11 | #define PUT_VALUE 11 12 | 13 | struct self_define_data { 14 | int age; 15 | char name[20]; 16 | }; 17 | 18 | static struct self_define_data sdd; 19 | 20 | int main(int argc, char *argv[]) 21 | { 22 | int ret; 23 | int i; 24 | int fd; 25 | struct self_define_data tmp_sdd; 26 | 27 | fd = open(DEVICE_NODE, O_RDWR); 28 | if (fd < 0) 29 | printf("Open failed\n"); 30 | 31 | sdd.age = 111; 32 | strcpy(sdd.name, "noname"); 33 | 34 | ioctl(fd, GET_VALUE, &tmp_sdd); 35 | printf("get %s, %d\n", tmp_sdd.name, tmp_sdd.age); 36 | 37 | ioctl(fd, PUT_VALUE, &sdd); 38 | printf("set %s, %d\n", sdd.name, sdd.age); 39 | 40 | ioctl(fd, GET_VALUE, &tmp_sdd); 41 | printf("get %s, %d\n", tmp_sdd.name, tmp_sdd.age); 42 | 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /rk3288/debug/misc/vfs_rw.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | /* read write buffer */ 7 | static char wbuf[] = "this is a kernel read write test"; 8 | static char rbuf[1024]; 9 | 10 | #define FILE_NAME "/tmp/vfs_rw_test" 11 | 12 | /* 13 | * 在内核中一般不容易生成用户空间的指针 14 | * 或者不方便独立使用用户空间内存 15 | * 而vfs_read,vfs_write的参数buffer都是用户空间指针 16 | * 所以需要调用set_fs目的是为了让内核改变对内存地址检查的处理方式 17 | * set_fs参数只有两个USER_DS和KERNEL_DS 18 | * USER_DS代表用户空间,set_fs 19 | * KERNEL_DS代表内核空间 20 | */ 21 | static int vfs_rw_init(void) 22 | { 23 | struct file *fp; 24 | mm_segment_t fs; 25 | loff_t pos; 26 | 27 | printk("%s, %d\n", __FUNCTION__, __LINE__); 28 | 29 | /* open file */ 30 | fp = filp_open(FILE_NAME, O_RDWR | O_CREAT, 0644); 31 | if (IS_ERR(fp)) 32 | { 33 | printk("create file error\n"); 34 | return -1; 35 | } 36 | 37 | /* write file */ 38 | 39 | /* get current fs*/ 40 | fs = get_fs(); 41 | 42 | /* 即对内核空间地址检查并做变换 */ 43 | set_fs(KERNEL_DS); 44 | pos = 0; 45 | printk("=> %s\n", wbuf); 46 | vfs_write(fp, wbuf, sizeof(wbuf), &pos); 47 | 48 | /* read file */ 49 | pos = 0; 50 | vfs_read(fp, rbuf, sizeof(wbuf), &pos); 51 | printk("<= %s\n", rbuf); 52 | 53 | /* close file */ 54 | filp_close(fp, NULL); 55 | set_fs(fs); 56 | 57 | return 0; 58 | } 59 | 60 | static void vfs_rw_exit(void) 61 | { 62 | printk("%s, %d\n", __FUNCTION__, __LINE__); 63 | } 64 | 65 | module_init(vfs_rw_init); 66 | module_exit(vfs_rw_exit); 67 | MODULE_LICENSE("GPL"); 68 | -------------------------------------------------------------------------------- /rk3288/debug/misc/wei.dtsi: -------------------------------------------------------------------------------- 1 | / { 2 | my_test_node { 3 | compatible = "test_platform"; 4 | }; 5 | }; 6 | -------------------------------------------------------------------------------- /rk3288/debug/mycpuinfo/.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.ko 3 | *.cmd 4 | Module.symvers 5 | modules.order 6 | .tmp_versions/ 7 | *.mod.c 8 | *.mod.c 9 | -------------------------------------------------------------------------------- /rk3288/debug/mycpuinfo/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile 2 | # Comment/uncomment the following line to disable/enable debugging 3 | # DEBUG = y 4 | 5 | # Usage 6 | # make CC= KERNELDIR= 7 | # 8 | # make CC=/home/zeroway/3288/src/3288_4.4/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/arm-eabi-gcc KERNELDIR=/home/zeroway/3288/src/3288_4.4/kernel 9 | 10 | # Add your debugging flag (or not) to CFLAGS 11 | ifeq ($(DEBUG),y) 12 | DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines 13 | else 14 | DEBFLAGS = -O2 15 | endif 16 | 17 | obj-m := mycpuinfo.o 18 | KERNELDIR ?= /lib/modules/$(shell uname -r)/build 19 | CC ?= gcc 20 | PWD := $(shell pwd) 21 | 22 | modules: 23 | $(MAKE) -C $(KERNELDIR) M=$(PWD) modules 24 | 25 | clean: 26 | rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions modules.order Module.symvers 27 | 28 | depend .depend dep: 29 | $(CC) $(CFLAGS) -M *.c > .depend 30 | 31 | ifeq (.depend,$(wildcard .depend)) 32 | include .depend 33 | endif 34 | -------------------------------------------------------------------------------- /rk3288/debug/mycpuinfo/mycpuinfo.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | static int c_show(struct seq_file *m, void *v) 8 | { 9 | int i; 10 | for (i = 0; i < 100; i++) 11 | seq_printf(m, "Hardware\t: %s, %d\n", "machine_name", i); 12 | 13 | return 0; 14 | } 15 | 16 | static void *c_start(struct seq_file *m, loff_t *pos) 17 | { 18 | printk("%s, %d\n", __FUNCTION__, __LINE__); 19 | return *pos < 1 ? (void *)1 : NULL; 20 | } 21 | 22 | static void *c_next(struct seq_file *m, void *v, loff_t *pos) 23 | { 24 | printk("%s, %d\n", __FUNCTION__, __LINE__); 25 | ++*pos; 26 | return NULL; 27 | } 28 | 29 | static void c_stop(struct seq_file *m, void *v) 30 | { 31 | printk("%s, %d\n", __FUNCTION__, __LINE__); 32 | } 33 | 34 | const struct seq_operations cpuinfo_op = { 35 | .start = c_start, 36 | .next = c_next, 37 | .stop = c_stop, 38 | .show = c_show 39 | }; 40 | 41 | static int cpuinfo_open(struct inode *inode, struct file *file) 42 | { 43 | printk("%s, %d\n", __FUNCTION__, __LINE__); 44 | return seq_open(file, &cpuinfo_op); 45 | } 46 | 47 | static const struct file_operations proc_cpuinfo_operations = { 48 | .open = cpuinfo_open, 49 | .read = seq_read, 50 | .llseek = seq_lseek, 51 | .release = seq_release, 52 | }; 53 | 54 | static int __init proc_cpuinfo_init(void) 55 | { 56 | proc_create("mycpuinfo", 0, NULL, &proc_cpuinfo_operations); 57 | return 0; 58 | } 59 | 60 | static void proc_cpuinfo_exit (void) 61 | { 62 | printk("%s, %d\n", __FUNCTION__, __LINE__); 63 | remove_proc_entry("mycpuinfo", NULL); 64 | } 65 | 66 | module_init(proc_cpuinfo_init); 67 | module_exit(proc_cpuinfo_exit); 68 | MODULE_LICENSE("GPL"); 69 | -------------------------------------------------------------------------------- /rk3288/debug/netlink/.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.ko 3 | *.cmd 4 | Module.symvers 5 | modules.order 6 | .tmp_versions/ 7 | *.mod.c 8 | *.mod.c 9 | -------------------------------------------------------------------------------- /rk3288/debug/netlink/Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH:= $(call my-dir) 2 | include $(CLEAR_VARS) 3 | 4 | LOCAL_SYSTEM_SHARED_LIBRARIES := libc 5 | LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES) 6 | LOCAL_MODULE_TAGS := debug 7 | LOCAL_SRC_FILES := demo1_user.c 8 | LOCAL_MODULE := demo1_user 9 | 10 | include $(BUILD_EXECUTABLE) 11 | -------------------------------------------------------------------------------- /rk3288/debug/netlink/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile 2 | # Comment/uncomment the following line to disable/enable debugging 3 | # DEBUG = y 4 | 5 | # Usage 6 | # make CROSS_COMPILE= KERNEL_DIR= KERNEL_BUID_OUTPUT= 7 | # 8 | PWD := $(shell pwd) 9 | BUILD_ENV = $(PWD)/../../buildenv 10 | cross_compiler_prefix = $(shell awk -F "CROSS_COMPILE=" '/CROSS_COMPILE=/{print $$2}' $(BUILD_ENV)) 11 | kernel_output = $(shell awk -F "KERNEL_BUILD_OUTPUT=" '/KERNEL_BUILD_OUTPUT=/{print $$2}' $(BUILD_ENV)) 12 | kernel_dir = $(shell awk -F "KERNEL_DIR=" '/KERNEL_DIR=/{print $$2}' $(BUILD_ENV)) 13 | 14 | # Add your debugging flag (or not) to CFLAGS 15 | ifeq ($(DEBUG),y) 16 | DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines 17 | else 18 | DEBFLAGS = -O2 19 | endif 20 | 21 | obj-m := demo1_kernel.o 22 | obj-m += demo2_kernel.o 23 | obj-m += demo3_kernel.o 24 | 25 | KERNEL_DIR ?= /lib/modules/$(shell uname -r)/build 26 | KERNEL_BUID_OUTPUT ?=$(KERNEL_DIR) 27 | CC = $(CROSS_COMPILE)gcc 28 | LD = $(CROSS_COMPILE)ld 29 | PWD := $(shell pwd) 30 | ARCH := x86_64 31 | 32 | modules: 33 | $(MAKE) CROSS_COMPILE=$(cross_compiler_prefix) -C $(kernel_dir) O=$(kernel_output) M=$(PWD) modules 34 | 35 | clean: 36 | rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions modules.order Module.symvers 37 | 38 | depend .depend dep: 39 | $(CC) $(CFLAGS) -M *.c > .depend 40 | 41 | ifeq (.depend,$(wildcard .depend)) 42 | include .depend 43 | endif 44 | -------------------------------------------------------------------------------- /rk3288/debug/netlink/README.md: -------------------------------------------------------------------------------- 1 | # Linux (Generic) NetLink 2 | 3 | ### 什么是Netlink 4 | 5 | [参考文章 用户空间和内核空间通讯](http://blog.chinaunix.net/uid-23069658-id-3400761.html) 6 | 7 | 关于Netlink的理解,需要把握几个关键点 8 | 9 | - 面向数据报的无连接消息子系统 10 | - 基于通用的BSD Socket架构而实现 11 | 12 | Netlink可以实现如下通信 13 | 14 | 内核->用户和用户->内核的双向,异步的数据通信,同时它还支持两个用户进程之间,甚至两个内核子系统之间的数据通信 15 | 16 | ### Netlink通信类型 17 | 18 | Netlink支持两种类型的通信方式:单播和多播 19 | 20 | - 单播:经常用于一个用户进程和一个内核子系统之间1:1的数据通信.用户空间发送命令到内核,然后从内核接受命令的返回结果. 21 | - 多播:经常用于一个内核进程和多个用户进程之间的1:N的数据通信.内核作为会话的发起者,用户空间的应用程序是接收者.为了实现这个功能,内核空间的程序会创建一个多播组,然后所有用户空间的对该内核进程发送的消息感兴趣的进程都加入到该组即可接收来自内核发送的消息了 22 | 23 | ![netlink topologic](./nl00.png) 24 | 25 | 其中进程A和子系统1之间是单播通信,进程B,C和子系统2是多播通信.上图还向我们说明了一个信息.从用户空间传递到内核的数据是不需要排队的,即其操作是同步完成;而从内核空间向用户空间传递数据时需要排队,是异步的.假如向内核发送了一个消息需要获取内核中某些信息,比如路由表,或其他信息,如果路由表过于庞大,那么内核在通过Netlink向应用返回数据时,应用可以好生琢磨一下如何接收这些数据的问题,毕竟已经看到了那个输出队列了,不能视而不见 26 | 27 | ### Netlink编程需要注意的问题 28 | 29 | 基于Netlink的用户/内核通信,有两种情况可能会导致丢包 30 | 31 | - 内存耗尽 32 | - 用户空间接收进程的缓冲区溢出.导致缓冲区溢出的主要原因有可能是:用户空间的进程运行太慢;或者接收队列太短 33 | 34 | 如果Netlink不能将消息正确传递到用户空间的接收进程,那么用户空间的接收进程在调用recvmsg()系统调用时就会返回一个内存不足(ENOBUFS)的错误,这一点需要注意.换句话说,缓冲区溢出的情况是不会发送在从用户->内核的sendmsg()系统调用里(同步操作) 35 | 36 | 当然,如果使用的是阻塞型socket通信,也就不存在内存耗尽的隐患了 37 | 38 | ![net link msg](./netlinkmsg.png) 39 | 40 | 一般netlink demo([demo1_user.c](demo1_user.c) [demo2_kernel.c](demo2_kernel.c)) 41 | 42 | ## Generic Netlink 43 | 44 | [generic_netlink_howto](https://wiki.linuxfoundation.org/networking/generic_netlink_howto#architectural-overview) 45 | 46 | [Generic Netlink(genl)介绍与例子](https://blog.csdn.net/ty3219/article/details/63683698) 47 | 48 | 介绍Generic Netlink之前,不得不说Netlink.Netlink是一种灵活的并且健壮的通讯方式, 49 | 可以用于kernel to user,user to kernel,kernel to kernel甚至user to user的通讯 50 | Netlink的通道是通过Family来组织的,但随着使用越来越多, 51 | Family ID已经不够分配了,所以才有了Generic Netlink. 52 | 所以,Generic Netlink其实是对Netlink报文中的数据进行了再次封装 53 | 54 | Generic Netlink 架构如下 55 | 56 | ![GenericNetlink](./genl.png) 57 | 58 | Genl数据包结构如下图 59 | 60 | ![genl data struct](./genl_data.png) 61 | 62 | - genl机制的数据包分了4层 63 | - 用户的实际数据封装在attribute里 64 | - 一个或多个attribute可以被封装在用户自定义的一个family报文里 65 | - 一个family报文又被封装在genlmsg里,最后genlmsg被封装在nlmsg里,总共4层 66 | 67 | ### User2Kernel 68 | 69 | user2kernel 工作流程([demo2_user.c](demo2_user.c) [demo2_kernel.c](demo2_kernel.c)) 70 | 71 | 对于从user to kernel的通讯,driver必须先向内核注册一个struct genl_family, 72 | 并且注册一些cmd的处理函数.这些cmd是跟某个family关联起来的. 73 | 注册family的时候我们可以让内核自动为这个family分配一个ID. 74 | 每个family都有一个唯一的ID,其中ID号0x10是被内核的nlctrl family所使用. 75 | 当注册成功以后,如果user program向某个family发送cmd,那么内核就会回调对应cmd的处理函数. 76 | 对于user program,使用前,除了要创建一个socket并绑定地址以外,还需要先通过family的名字获取family的ID. 77 | 获取方法,就是向nlctrl这个family查询.详细的方法可以看后面的例子.有了family的ID以后,才能向该family发送cmd 78 | 79 | ### Kernel2User 80 | 81 | kernel2user 工作流程([demo3_user.c](demo3_user.c) [demo3_kernel.c](demo3_kernel.c)) 82 | 83 | 对于从kernel to user的通讯,采用的是广播的形式, 84 | 只要user program监听了,都能收到.但是同样的, 85 | user program在监听前,也必须先查询到family的ID 86 | 87 | 测试方法 88 | 89 | 加载内核模块 90 | 91 | insmod demo3_kernel.ko 92 | 93 | 启动两个应用程序 94 | 95 | ./demo3_user 96 | ./demo3_user 97 | 98 | 触发内核上报消息通知所有应用程序 99 | 100 | echo 1 > /sys/kernel/genl_test/genl_trigger 101 | -------------------------------------------------------------------------------- /rk3288/debug/netlink/demo1_kernel.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #define NETLINK_USER 22 10 | #define USER_MSG (NETLINK_USER + 1) 11 | 12 | static struct sock *netlinkfd = NULL; 13 | const char *message = "This is kernel speaking"; 14 | 15 | int send_msg(const char *pbuf, unsigned short len, unsigned int pid) 16 | { 17 | struct sk_buff *nl_skb; 18 | struct nlmsghdr *nlh; 19 | int ret; 20 | 21 | nl_skb = nlmsg_new(len, GFP_ATOMIC); 22 | if (!nl_skb) 23 | { 24 | printk("netlink_alloc_skb error\n"); 25 | return -1; 26 | } 27 | 28 | nlh = nlmsg_put(nl_skb, 0, 0, USER_MSG, len, 0); 29 | if (nlh == NULL) 30 | { 31 | printk("nlmsg_put() error\n"); 32 | nlmsg_free(nl_skb); 33 | return -1; 34 | } 35 | 36 | memcpy(nlmsg_data(nlh), pbuf, len); 37 | 38 | ret = netlink_unicast(netlinkfd, nl_skb, pid, MSG_DONTWAIT); 39 | 40 | return ret; 41 | } 42 | 43 | /* wait for message coming down from user-space */ 44 | static void recv_cb(struct sk_buff *skb) 45 | { 46 | struct nlmsghdr *nlh = NULL; 47 | void *data = NULL; 48 | unsigned int pid; 49 | 50 | printk("skb->len:%u\n", skb->len); 51 | if (skb->len >= nlmsg_total_size(0)) 52 | { 53 | nlh = nlmsg_hdr(skb); 54 | pid = nlh->nlmsg_pid; /*pid of sending process */ 55 | printk("calling process pid = %d\n", pid); 56 | 57 | data = NLMSG_DATA(nlh); 58 | if (data) 59 | { 60 | printk("KERNEL receive : %s\n", (int8_t *)data); 61 | send_msg(message, strlen(message), pid); 62 | } 63 | } 64 | } 65 | 66 | struct netlink_kernel_cfg nl_cfg = { 67 | .input = recv_cb, 68 | }; 69 | 70 | static int test_netlink_init(void) 71 | { 72 | printk("%s, %d\n", __FUNCTION__, __LINE__); 73 | 74 | netlinkfd = netlink_kernel_create(&init_net, USER_MSG, &nl_cfg); 75 | if (!netlinkfd) 76 | { 77 | printk(KERN_ERR "can not create a netlink socket!\n"); 78 | return -1; 79 | } 80 | 81 | return 0; 82 | } 83 | 84 | static void test_netlink_exit(void) 85 | { 86 | printk("%s, %d\n", __FUNCTION__, __LINE__); 87 | sock_release(netlinkfd->sk_socket); 88 | } 89 | 90 | module_init(test_netlink_init); 91 | module_exit(test_netlink_exit); 92 | MODULE_LICENSE("GPL"); 93 | MODULE_DESCRIPTION("netlink_demo"); 94 | -------------------------------------------------------------------------------- /rk3288/debug/netlink/demo1_user.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #define NETLINK_USER 22 11 | #define USER_MSG (NETLINK_USER + 1) 12 | #define MSG_LEN 100 13 | #define MAX_PLOAD 100 14 | 15 | /* user define data */ 16 | struct user_define_data 17 | { 18 | struct nlmsghdr hdr; 19 | char data[MSG_LEN]; 20 | }; 21 | 22 | int main(int argc, char **argv) 23 | { 24 | int sock_fd; 25 | int ret; 26 | const char *message = "This is userspace speaking"; 27 | struct sockaddr_nl src_addr, dest_addr; 28 | struct nlmsghdr *nlh = NULL; 29 | struct user_define_data udd; 30 | 31 | /* create a socket with USER_MSG type */ 32 | sock_fd = socket(AF_NETLINK, SOCK_RAW, USER_MSG); 33 | if (sock_fd == -1) 34 | { 35 | printf("create socket error...%s\n", strerror(errno)); 36 | return -1; 37 | } 38 | 39 | /* source address */ 40 | memset(&src_addr, 0, sizeof(src_addr)); 41 | src_addr.nl_family = AF_NETLINK; 42 | /* 43 | * In scenarios where different threads of the same process want to 44 | * have different netlink sockets opened under the same netlink protocol 45 | */ 46 | #ifndef DIFFERENT_NETLINK_IN_SAME_NETLINK 47 | src_addr.nl_pid = getpid(); 48 | #else 49 | src_addr.nl_pid = pthread_self() << 16 | getpid(); 50 | #endif 51 | src_addr.nl_groups = 0; /* not in mcast groups */ 52 | if (bind(sock_fd, (struct sockaddr *)&src_addr, sizeof(src_addr)) != 0) 53 | { 54 | printf("bind() error\n"); 55 | close(sock_fd); 56 | return -1; 57 | } 58 | 59 | /* destination address */ 60 | memset(&dest_addr, 0, sizeof(dest_addr)); 61 | dest_addr.nl_family = AF_NETLINK; 62 | dest_addr.nl_pid = 0; /* For Linux Kernel */ 63 | dest_addr.nl_groups = 0; /* unicast */ 64 | 65 | nlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_PLOAD)); 66 | 67 | /* Fill the netlink message header */ 68 | memset(nlh, 0, sizeof(struct nlmsghdr)); 69 | nlh->nlmsg_len = NLMSG_SPACE(MAX_PLOAD); 70 | nlh->nlmsg_flags = 0; 71 | nlh->nlmsg_type = 0; 72 | nlh->nlmsg_seq = 0; 73 | nlh->nlmsg_pid = src_addr.nl_pid; /* self pid */ 74 | printf("calling process pid = %d\n", nlh->nlmsg_pid); 75 | 76 | /* Fill in the netlink message payload */ 77 | memcpy(NLMSG_DATA(nlh), message, strlen(message)); 78 | 79 | ret = sendto(sock_fd, nlh, nlh->nlmsg_len, 0, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr_nl)); 80 | if (!ret) 81 | { 82 | perror("sendto error1\n"); 83 | close(sock_fd); 84 | exit(-1); 85 | } 86 | 87 | memset(&udd, 0, sizeof(udd)); 88 | ret = recvfrom(sock_fd, &udd, sizeof(struct user_define_data), 0, (struct sockaddr *)&dest_addr, sizeof(dest_addr)); 89 | if (!ret) 90 | { 91 | perror("recv form kernel error\n"); 92 | close(sock_fd); 93 | exit(-1); 94 | } 95 | 96 | printf("USERSPACE receive :%s\n", udd.data); 97 | close(sock_fd); 98 | free((void *)nlh); 99 | 100 | return 0; 101 | } 102 | -------------------------------------------------------------------------------- /rk3288/debug/netlink/genl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3288/debug/netlink/genl.png -------------------------------------------------------------------------------- /rk3288/debug/netlink/genl_data.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3288/debug/netlink/genl_data.png -------------------------------------------------------------------------------- /rk3288/debug/netlink/netlinkmsg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3288/debug/netlink/netlinkmsg.png -------------------------------------------------------------------------------- /rk3288/debug/netlink/nl00.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3288/debug/netlink/nl00.png -------------------------------------------------------------------------------- /rk3288/debug/notify_chain/.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.ko 3 | *.cmd 4 | Module.symvers 5 | modules.order 6 | .tmp_versions/ 7 | *.mod* 8 | -------------------------------------------------------------------------------- /rk3288/debug/notify_chain/AAAAA_chain.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #define TESTCHAIN_EVENT 0x1234 7 | -------------------------------------------------------------------------------- /rk3288/debug/notify_chain/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile 2 | # Comment/uncomment the following line to disable/enable debugging 3 | # DEBUG = y 4 | 5 | # Usage 6 | # make CROSS_COMPILE= KERNEL_DIR= KERNEL_BUID_OUTPUT= 7 | # 8 | # make CROSS_COMPILE=/home/zeroway/rk3399/tool/gcc-linaro-4.9.4-2017.01-i686_aarch64-linux-gnu/bin/aarch64-linux-gnu- KERNEL_DIR=/home/zeroway/rk3399/src/firefly/kernel KERNEL_BUID_OUTPUT=/home/zeroway/rk3399/src/firefly/out/target/product/rk3399_firefly_box/obj/KERNEL 9 | 10 | # Add your debugging flag (or not) to CFLAGS 11 | ifeq ($(DEBUG),y) 12 | DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines 13 | else 14 | DEBFLAGS = -O2 15 | endif 16 | 17 | obj-m := chain_core.o notifier.o register.o 18 | obj-m += demo1_core.o demo1_notifier.o demo1_register.o 19 | KERNEL_DIR ?= /lib/modules/$(shell uname -r)/build 20 | KERNEL_BUID_OUTPUT ?=$(KERNEL_DIR) 21 | CC = $(CROSS_COMPILE)gcc 22 | LD = $(CROSS_COMPILE)ld 23 | PWD := $(shell pwd) 24 | 25 | modules: 26 | $(MAKE) -C $(KERNEL_DIR) ARCH=arm64 M=$(PWD) O=$(KERNEL_BUID_OUTPUT) modules 27 | 28 | clean: 29 | rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions modules.order Module.symvers 30 | 31 | depend .depend dep: 32 | $(CC) $(CFLAGS) -M *.c > .depend 33 | 34 | ifeq (.depend,$(wildcard .depend)) 35 | include .depend 36 | endif 37 | -------------------------------------------------------------------------------- /rk3288/debug/notify_chain/README.md: -------------------------------------------------------------------------------- 1 | # Notify 2 | 3 | [参考文章](http://blog.chinaunix.net/uid-25871104-id-3086446.html) 4 | 5 | ![call flow](./call_flow.png) 6 | 7 | ## 测试方法 8 | 9 | [参考文章](http://www.linuxidc.com/Linux/2013-07/86999.htm) 10 | 11 | demo1 使用方法 12 | 13 | insmod demo1_core.ko 14 | insmod demo1_register.ko 15 | insmod demo1_notifier.ko 16 | 17 | demo 使用方法 18 | 19 | insmod chain_core.ko 20 | insmod register.ko 21 | insmod notifier.ko 22 | -------------------------------------------------------------------------------- /rk3288/debug/notify_chain/call_flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3288/debug/notify_chain/call_flow.png -------------------------------------------------------------------------------- /rk3288/debug/notify_chain/call_flow.txt: -------------------------------------------------------------------------------- 1 | @startuml 2 | 3 | chain_core <- register : 向系统注册通知接受者 4 | notifier -> chain_core : 触发通知信号 5 | chain_core -> register : 通知注册者 6 | 7 | @enduml 8 | -------------------------------------------------------------------------------- /rk3288/debug/notify_chain/chain_core.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /* user define local chain */ 6 | static RAW_NOTIFIER_HEAD(test_chain); 7 | 8 | int register_test_notifier(struct notifier_block *nb) 9 | { 10 | return raw_notifier_chain_register(&test_chain, nb); 11 | } 12 | EXPORT_SYMBOL(register_test_notifier); 13 | 14 | int unregister_test_notifier(struct notifier_block *nb) 15 | { 16 | return raw_notifier_chain_unregister(&test_chain, nb); 17 | } 18 | EXPORT_SYMBOL(unregister_test_notifier); 19 | 20 | int test_notifier_call_chain(unsigned long val, void *v) 21 | { 22 | return raw_notifier_call_chain(&test_chain, val, v); 23 | } 24 | EXPORT_SYMBOL(test_notifier_call_chain); 25 | 26 | static int init_notifier(void) 27 | { 28 | printk("init_notifier\n"); 29 | return 0; 30 | } 31 | 32 | static void exit_notifier(void) 33 | { 34 | printk("exit_notifier\n"); 35 | } 36 | 37 | module_init(init_notifier); 38 | module_exit(exit_notifier); 39 | MODULE_LICENSE("GPL"); 40 | -------------------------------------------------------------------------------- /rk3288/debug/notify_chain/demo1_core.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 1. 申明一个通知链 3 | * 2. 向内核注册通知链 4 | * 3. 定义事件 5 | * 4. 导出符号,因而必需最后退出 6 | */ 7 | #include "AAAAA_chain.h" 8 | 9 | /* 自定义一个通知链头 */ 10 | static RAW_NOTIFIER_HEAD(AAAAA_nh); 11 | 12 | /* 定义调用通知链的函数 */ 13 | static int call_test_notifiers(unsigned long val, void *v) 14 | { 15 | return raw_notifier_call_chain(&AAAAA_nh, val, v); 16 | } 17 | EXPORT_SYMBOL(call_test_notifiers); 18 | 19 | /* 定义注册自己通知链的函数 */ 20 | static int register_BBBBB_notifier(struct notifier_block *nb) 21 | { 22 | int err = 0; 23 | err = raw_notifier_chain_register(&AAAAA_nh, nb); 24 | 25 | return err; 26 | } 27 | EXPORT_SYMBOL(register_BBBBB_notifier); 28 | 29 | static int unregister_BBBBB_notifier(struct notifier_block *nb) 30 | { 31 | int err = 0; 32 | err = raw_notifier_chain_unregister(&AAAAA_nh, nb); 33 | 34 | return err; 35 | } 36 | EXPORT_SYMBOL(unregister_BBBBB_notifier); 37 | 38 | /* AAAAA means the module name */ 39 | static int AAAAA_core_init(void) 40 | { 41 | printk("%s, %d\n", __FUNCTION__, __LINE__); 42 | return 0; 43 | } 44 | 45 | static void AAAAA_core_exit(void) 46 | { 47 | printk("%s, %d\n", __FUNCTION__, __LINE__); 48 | } 49 | module_init(AAAAA_core_init); 50 | module_exit(AAAAA_core_exit); 51 | MODULE_LICENSE("GPL v2"); 52 | MODULE_AUTHOR("zeroway"); 53 | -------------------------------------------------------------------------------- /rk3288/debug/notify_chain/demo1_notifier.c: -------------------------------------------------------------------------------- 1 | #include "AAAAA_chain.h" 2 | 3 | extern int call_test_notifiers(unsigned long val, void *v); 4 | 5 | /* CCCCC means the module name */ 6 | static int CCCCC_init(void) 7 | { 8 | printk("%s, %d\n", __FUNCTION__, __LINE__); 9 | call_test_notifiers(TESTCHAIN_EVENT, "no_use"); 10 | 11 | return 0; 12 | } 13 | 14 | static void CCCCC_exit(void) 15 | { 16 | printk("%s, %d\n", __FUNCTION__, __LINE__); 17 | } 18 | module_init(CCCCC_init); 19 | module_exit(CCCCC_exit); 20 | MODULE_LICENSE("GPL v2"); 21 | MODULE_AUTHOR("zeroway"); 22 | -------------------------------------------------------------------------------- /rk3288/debug/notify_chain/demo1_register.c: -------------------------------------------------------------------------------- 1 | #include "AAAAA_chain.h" 2 | 3 | extern int register_BBBBB_notifier(struct notifier_block *nb); 4 | extern int unregister_BBBBB_notifier(struct notifier_block *nb); 5 | 6 | /* 收到通知后的处理函数 */ 7 | int BBBBB_event_handler(struct notifier_block *nb, unsigned long event, void *v) 8 | { 9 | switch(event) { 10 | case TESTCHAIN_EVENT: 11 | printk("Register handling the event(%d)\n", event); 12 | break; 13 | default: 14 | break; 15 | } 16 | 17 | return NOTIFY_DONE; 18 | } 19 | 20 | /* define a notifier_block */ 21 | static struct notifier_block BBBBB_nb = { 22 | .notifier_call = BBBBB_event_handler, 23 | }; 24 | 25 | /* BBBBB means the module name */ 26 | static int BBBBB_register_init(void) 27 | { 28 | printk("%s, %d\n", __FUNCTION__, __LINE__); 29 | register_BBBBB_notifier(&BBBBB_nb); 30 | return 0; 31 | } 32 | 33 | static void BBBBB_register_exit(void) 34 | { 35 | printk("%s, %d\n", __FUNCTION__, __LINE__); 36 | unregister_BBBBB_notifier(&BBBBB_nb); 37 | } 38 | module_init(BBBBB_register_init); 39 | module_exit(BBBBB_register_exit); 40 | MODULE_LICENSE("GPL"); 41 | MODULE_AUTHOR("zeroway"); 42 | -------------------------------------------------------------------------------- /rk3288/debug/notify_chain/notifier.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | extern int test_notifier_call_chain(unsigned long val, void *v); 6 | 7 | /* 自定义通知事件号 */ 8 | enum self_define_event_number { 9 | evt_no0, 10 | evt_no1, 11 | }; 12 | 13 | static int call_notifier(void) 14 | { 15 | int err; 16 | printk("%s, Begin to notify:\n", __FUNCTION__); 17 | 18 | printk("%s, event %d emit\n", __FUNCTION__, evt_no0); 19 | err = test_notifier_call_chain(evt_no0, NULL); 20 | 21 | printk("%s, event %d emit\n", __FUNCTION__, evt_no1); 22 | err = test_notifier_call_chain(evt_no1, "new_test"); 23 | if (err) 24 | printk("notifier_call_chain error\n"); 25 | return err; 26 | } 27 | 28 | static void uncall_notifier(void) 29 | { 30 | printk("Endnotify\n"); 31 | } 32 | 33 | module_init(call_notifier); 34 | module_exit(uncall_notifier); 35 | MODULE_LICENSE("GPL"); 36 | -------------------------------------------------------------------------------- /rk3288/debug/notify_chain/register.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | extern int unregister_test_notifier(struct notifier_block*); 6 | extern int register_test_notifier(struct notifier_block *nb); 7 | 8 | static int test_event1(struct notifier_block *this, unsigned long event, void *ptr) 9 | { 10 | printk("In %s: evt_no = %ld\n", __FUNCTION__, event); 11 | 12 | if (NULL != ptr) 13 | printk("%s get %s\n", __FUNCTION__, (char *)ptr); 14 | 15 | return 0; 16 | } 17 | 18 | static int test_event2(struct notifier_block *this, unsigned long event, void *ptr) 19 | { 20 | printk("In %s: evt_no = %ld\n", __FUNCTION__, event); 21 | 22 | if (NULL != ptr) 23 | printk("%s get %s\n", __FUNCTION__, (char *)ptr); 24 | 25 | return 0; 26 | } 27 | 28 | static int test_event3(struct notifier_block *this, unsigned long event, void *ptr) 29 | { 30 | printk("In %s: evt_no = %ld\n", __FUNCTION__, event); 31 | 32 | if (NULL != ptr) 33 | printk("%s get %s\n", __FUNCTION__, (char *)ptr); 34 | 35 | return 0; 36 | } 37 | 38 | static struct notifier_block test_notifier1 = 39 | { 40 | .notifier_call = test_event1, 41 | }; 42 | 43 | static struct notifier_block test_notifier2 = 44 | { 45 | .notifier_call = test_event2, 46 | }; 47 | 48 | static struct notifier_block test_notifier3 = 49 | { 50 | .notifier_call = test_event3, 51 | }; 52 | 53 | static int reg_notifier(void) 54 | { 55 | int err; 56 | printk("Begin to register:\n"); 57 | 58 | err = register_test_notifier(&test_notifier1); 59 | if (err) 60 | { 61 | printk("register test_notifier1 error\n"); 62 | return -1; 63 | } 64 | printk("register test_notifier1 completed\n"); 65 | 66 | err = register_test_notifier(&test_notifier2); 67 | if (err) 68 | { 69 | printk("register test_notifier2 error\n"); 70 | return -1; 71 | } 72 | printk("register test_notifier2 completed\n"); 73 | 74 | err = register_test_notifier(&test_notifier3); 75 | if (err) 76 | { 77 | printk("register test_notifier3 error\n"); 78 | return -1; 79 | } 80 | printk("register test_notifier3 completed\n"); 81 | 82 | return err; 83 | } 84 | 85 | static void unreg_notifier(void) 86 | { 87 | printk("Begin to unregister\n"); 88 | unregister_test_notifier(&test_notifier1); 89 | unregister_test_notifier(&test_notifier2); 90 | unregister_test_notifier(&test_notifier3); 91 | printk("Unregister finished\n"); 92 | } 93 | 94 | module_init(reg_notifier); 95 | module_exit(unreg_notifier); 96 | MODULE_LICENSE("GPL"); 97 | -------------------------------------------------------------------------------- /rk3288/debug/platform_driver_test/.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.ko 3 | *.cmd 4 | Module.symvers 5 | modules.order 6 | .tmp_versions/ 7 | *.mod.c 8 | *.mod.c 9 | -------------------------------------------------------------------------------- /rk3288/debug/platform_driver_test/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile 2 | # Comment/uncomment the following line to disable/enable debugging 3 | # DEBUG = y 4 | 5 | PWD := $(shell pwd) 6 | BUILD_ENV = $(PWD)/../../buildenv 7 | cross_compiler_prefix = $(shell awk -F "CROSS_COMPILE=" '/CROSS_COMPILE=/{print $$2}' $(BUILD_ENV)) 8 | kernel_output = $(shell awk -F "KERNEL_BUILD_OUTPUT=" '/KERNEL_BUILD_OUTPUT=/{print $$2}' $(BUILD_ENV)) 9 | kernel_dir = $(shell awk -F "KERNEL_DIR=" '/KERNEL_DIR=/{print $$2}' $(BUILD_ENV)) 10 | 11 | # Add your debugging flag (or not) to CFLAGS 12 | ifeq ($(DEBUG),y) 13 | DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines 14 | else 15 | DEBFLAGS = -O2 16 | endif 17 | 18 | obj-m := test_pf.o 19 | obj-m += show_store_pf.o 20 | obj-m += skeleton_ss.o 21 | obj-m += spinlock_test.o 22 | obj-m += mutex_test.o 23 | 24 | KERNEL_DIR ?= /lib/modules/$(shell uname -r)/build 25 | KERNEL_BUILD_OUTPUT ?=$(KERNEL_DIR) 26 | CC = $(CROSS_COMPILE)gcc 27 | LD = $(CROSS_COMPILE)ld 28 | 29 | modules: 30 | $(MAKE) CROSS_COMPILE=$(cross_compiler_prefix) -C $(kernel_dir) O=$(kernel_output) M=$(PWD) modules 31 | 32 | clean: 33 | rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions modules.order Module.symvers 34 | 35 | depend .depend dep: 36 | $(CC) $(CFLAGS) -M *.c > .depend 37 | 38 | ifeq (.depend,$(wildcard .depend)) 39 | include .depend 40 | endif 41 | -------------------------------------------------------------------------------- /rk3288/debug/platform_driver_test/README.md: -------------------------------------------------------------------------------- 1 | # PlatformDriver 2 | 3 | 把dtsi文件包含到所使用的dts里 4 | 5 | #include "test_pf.dtsi" 6 | 7 | 在驱动中如何使用下图中的VCC_TP,详见代码 8 | 9 | ![VCC_TP](./VCC_TP.png) 10 | 11 | # show_store_pf.c 12 | 13 | device attr show and store 14 | 15 | ## usage 16 | 17 | 把dtsi文件包含到所使用的dts里 18 | 19 | #include "show_store_pf.dtsi" 20 | 21 | ## debug 22 | 23 | 输入3个值并查看 24 | 25 | echo 1 3 4 > /sys/devices/my_test_node.23/BBBBB_debug 26 | cat /sys/devices/my_test_node.23/BBBBB_debug 27 | 28 | ## SpinLock and Mutex 29 | 30 | [locks in linux kernel](./locks.md) 31 | -------------------------------------------------------------------------------- /rk3288/debug/platform_driver_test/VCC_TP.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3288/debug/platform_driver_test/VCC_TP.png -------------------------------------------------------------------------------- /rk3288/debug/platform_driver_test/lock_test.dtsi: -------------------------------------------------------------------------------- 1 | / { 2 | lock_node { 3 | compatible = "lock-test"; 4 | }; 5 | }; 6 | -------------------------------------------------------------------------------- /rk3288/debug/platform_driver_test/locks.md: -------------------------------------------------------------------------------- 1 | # Locks in linux kernel 2 | 3 | ## 为什么需要内核锁 4 | 5 | 多核处理器下,会存在多个进程处于内核态的情况,而在内核态下, 6 | 进程是可以访问所有内核数据的,因此要对共享数据进行保护,即互斥处理 7 | 8 | ## 有哪些内核锁机制 9 | 10 | - 原子操作 11 | 12 | atomic_t数据类型,atomic_inc(atomic_t *v)将v加1 13 | 原子操作比普通操作效率要低,因此必要时才使用,且不能与普通操作混合使用 14 | 如果是单核处理器,则原子操作与普通操作相同 15 | 16 | - 自旋锁 17 | 18 | spinlock_t数据类型,spin_lock(&lock)和spin_unlock(&lock)是加锁和解锁 19 | 等待解锁的进程将反复检查锁是否释放,而`不会进入睡眠状态(忙等待)`, 20 | 所以常用于`短期`保护某段代码 21 | 22 | 同时,持有自旋锁的进程也`不允许睡眠`, 23 | 不然会造成死锁——因为睡眠可能造成持有锁的进程被重新调度, 24 | 而再次申请自己已持有的锁 25 | 26 | 如果是单核处理器,则自旋锁定义为空操作,因为简单的关闭中断即可实现互斥 27 | 28 | - 信号量与互斥量 29 | 30 | struct semaphore数据类型,down(struct semaphore * sem)和 31 | up(struct semaphore * sem)是占用和释放 32 | 33 | struct mutex数据类型,mutex_lock(struct mutex *lock)和 34 | mutex_unlock(struct mutex *lock)是加锁和解锁 35 | 36 | 竞争信号量与互斥量时需要进行进程睡眠和唤醒, 37 | 代价较高,所以不适于短期代码保护,适用于保护`较长的临界区` 38 | 39 | ## 互斥量与信号量的区别 40 | 41 | - 互斥量用于线程的互斥,信号线用于线程的同步 42 | 43 | 这是互斥量和信号量的根本区别,也就是互斥和同步之间的区别 44 | 45 | 互斥:是指某一资源同时只允许一个访问者对其进行访问, 46 | 具有唯一性和排它性.但互斥无法限制访问者对资源的访问顺序,即访问是无序的 47 | 48 | 同步:是指在互斥的基础上(大多数情况),通过其它机制实现访问者对资源的有序访问. 49 | 在大多数情况下,同步已经实现了互斥,特别是所有写入资源的情况必定是互斥的. 50 | 少数情况是指可以允许多个访问者同时访问资源 51 | 52 | - 互斥量值只能为0/1,信号量值可以为非负整数 53 | 54 | 也就是说,一个互斥量只能用于一个资源的互斥访问, 55 | 它不能实现多个资源的多线程互斥问题.信号量可以实现多个同类资源的多线程互斥和同步. 56 | 当信号量为单值信号量是,也可以完成一个资源的互斥访问 57 | 58 | - 互斥量的加锁和解锁必须由同一线程分别对应使用, 59 | 信号量可以由一个线程释放,另一个线程得到 60 | 61 | ## mutex和spin lock的区别 62 | 63 | mutex和spin lock的区别和应用(sleep-waiting和busy-waiting的区别) 64 | 65 | 互斥mutex是`sleep-waiting`(可休眠) 66 | 就是说当没有获得mutex时,会有上下文切换,将自己、 67 | 加到忙等待队列中,直到另外一个线程释放mutex并唤醒它, 68 | 而这时CPU是空闲的,可以调度别的任务处理. 69 | 70 | 而自旋锁spin lock是`busy-waiting` 71 | 就是说当没有可用的锁时,就一直忙等待并不停的进行锁请求, 72 | 直到得到这个锁为止.这个过程中cpu始终处于忙状态,不能做别的任务. 73 | 74 | 例如在一个双核的机器上有两个线程(线程A和线程B),它们分别运行在Core0 和Core1上. 75 | 用spin-lock,coer0上的线程就会始终占用CPU. 76 | 另外一个值得注意的细节是spin lock耗费了更多的user time. 77 | 这是因为两个线程分别运行在两个核上,大部分时间只有一个线程能拿到锁, 78 | 所以另一个线程就一直在它运行的core上进行忙等待,CPU占用率一直是100%; 79 | 而mutex则不同,当对锁的请求失败后上下文切换就会发生,这样就能空出一个核来进行别的运算任务了 80 | (其实这种上下文切换对已经拿着锁的那个线程性能也是有影响的, 81 | 因为当该线程释放该锁时它需要通知操作系统去唤醒那些被阻塞的线程,这也是额外的开销) 82 | 83 | ## 使用场景总结 84 | 85 | - Mutex适合`对锁操作非常频繁`的场景,并且具有更好的适应性. 86 | 尽管相比spin lock它会花费更多的开销(主要是上下文切换), 87 | 但是它能适合实际开发中复杂的应用场景,在保证一定性能的前提下提供更大的灵活度. 88 | 89 | - spin lock的lock/unlock性能更好(花费更少的cpu指令), 90 | 但是它只适应用于`临界区运行时间很短`的场景. 91 | 而在实际软件开发中,除非程序员对自己的程序的锁操作行为非常的了解, 92 | 否则使用spin lock不是一个好主意 93 | (通常一个多线程程序中对锁的操作有数以万次,如果失败的锁操作 94 | (contended lock requests)过多的话就会浪费很多的时间进行空等待). 95 | 96 | - 更保险的方法或许是先(保守的)使用 97 | Mutex,然后如果对性能还有进一步的需求,可以尝试使用spin 98 | lock进行调优.毕竟我们的程序不像Linux kernel那样对性能需求那么高 99 | (Linux Kernel最常用的锁操作是spin lock和rw lock). 100 | -------------------------------------------------------------------------------- /rk3288/debug/platform_driver_test/mutex_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | struct locktest_chip { 16 | struct mutex lock; 17 | }; 18 | 19 | static int mutexlock_test_probe(struct platform_device *pdev) 20 | { 21 | struct locktest_chip *chip; 22 | int ret = 0; 23 | 24 | printk("%s, %d\n", __FUNCTION__, __LINE__); 25 | 26 | /* alloc for chip point */ 27 | chip = devm_kzalloc(&pdev->dev, sizeof(struct locktest_chip), GFP_KERNEL); 28 | if (!chip) 29 | { 30 | printk("no memory\n"); 31 | ret = -ENOMEM; 32 | } 33 | 34 | /* init mutext lock */ 35 | mutex_init(&chip->lock); 36 | 37 | /* set pdata */ 38 | dev_set_drvdata(&pdev->dev, (void *)chip); 39 | 40 | /* visit the race conditon area */ 41 | if (!mutex_trylock(&chip->lock)) 42 | { 43 | printk("can not get the lock\n"); 44 | return -1; 45 | } 46 | printk("Accessing race condition area...\n"); 47 | 48 | /* 49 | * mutext can sleep 50 | * sleep will cause context switch 51 | */ 52 | msleep(1); 53 | mutex_unlock(&chip->lock); 54 | 55 | return ret; 56 | } 57 | 58 | static int mutexlock_test_remove(struct platform_device *pdev) 59 | { 60 | printk("%s, %d\n", __FUNCTION__, __LINE__); 61 | 62 | return 0; 63 | } 64 | 65 | static const struct of_device_id mutexlock_test_dt_ids[] = { 66 | {.compatible = "lock-test",}, 67 | {}, 68 | }; 69 | 70 | static struct platform_driver mutexlock_test = { 71 | .driver = { 72 | .name = "locktest example", 73 | .owner = THIS_MODULE, 74 | .of_match_table = of_match_ptr(mutexlock_test_dt_ids), 75 | }, 76 | .probe = mutexlock_test_probe, 77 | .remove = mutexlock_test_remove, 78 | }; 79 | 80 | module_platform_driver(mutexlock_test); 81 | 82 | MODULE_LICENSE("GPL"); 83 | MODULE_AUTHOR("zeroway "); 84 | MODULE_DESCRIPTION("locktest"); 85 | -------------------------------------------------------------------------------- /rk3288/debug/platform_driver_test/show_store_pf.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | static int g_x = -1; 11 | static int g_y = -1; 12 | static int g_z = -1; 13 | 14 | static ssize_t BBBBB_debug_show(struct device *dev, struct device_attribute *attr, char *buf) 15 | { 16 | printk("x = %d y = %d z = %d\n", g_x, g_y, g_z); 17 | return 0; 18 | } 19 | 20 | static ssize_t BBBBB_debug_store(struct device *dev, 21 | struct device_attribute *attr, const char *buf, size_t count) 22 | { 23 | sscanf(buf, "%d %d %d", &g_x, &g_y, &g_z); 24 | return count; 25 | } 26 | 27 | static DEVICE_ATTR(BBBBB_debug, S_IRUGO | S_IWUSR, BBBBB_debug_show, BBBBB_debug_store); 28 | 29 | static struct attribute *BBBBB_attrs[] = { 30 | &dev_attr_BBBBB_debug.attr, 31 | NULL, 32 | }; 33 | 34 | static const struct attribute_group BBBBB_attr_group = { 35 | .attrs = BBBBB_attrs, 36 | }; 37 | 38 | static int AAAAA_platform_probe(struct platform_device *pdev) 39 | { 40 | int ret; 41 | 42 | ret = sysfs_create_group(&pdev->dev.kobj, &BBBBB_attr_group); 43 | if (ret) { 44 | printk("failed to create sysfs device attributes\n"); 45 | return -1; 46 | } 47 | return 0; 48 | } 49 | 50 | static const struct of_device_id AAAAA_platform_dt_ids[] = { 51 | { .compatible = "test_platform", }, 52 | {} 53 | }; 54 | 55 | static int AAAAA_platform_remove(struct platform_device *pdev) 56 | { 57 | int ret; 58 | 59 | sysfs_remove_group(&pdev->dev.kobj, &BBBBB_attr_group); 60 | 61 | printk("%s, %d\n", __FUNCTION__, __LINE__); 62 | return 0; 63 | } 64 | 65 | static struct platform_driver AAAAA_platform_driver = { 66 | .driver = { 67 | .name = "test platform driver", 68 | .owner = THIS_MODULE, 69 | .of_match_table = of_match_ptr(AAAAA_platform_dt_ids), 70 | }, 71 | .probe = AAAAA_platform_probe, 72 | .remove = AAAAA_platform_remove, 73 | }; 74 | 75 | static int AAAAA_platform_init(void) 76 | { 77 | return platform_driver_register(&AAAAA_platform_driver); 78 | } 79 | 80 | static void AAAAA_platform_exit(void) 81 | { 82 | platform_driver_unregister(&AAAAA_platform_driver); 83 | } 84 | 85 | module_init(AAAAA_platform_init); 86 | module_exit(AAAAA_platform_exit); 87 | MODULE_LICENSE("GPL"); 88 | -------------------------------------------------------------------------------- /rk3288/debug/platform_driver_test/show_store_pf.dtsi: -------------------------------------------------------------------------------- 1 | / { 2 | my_test_node { 3 | compatible = "test_platform"; 4 | }; 5 | }; 6 | -------------------------------------------------------------------------------- /rk3288/debug/platform_driver_test/skeleton_ss.dtsi: -------------------------------------------------------------------------------- 1 | / { 2 | skeleton_gpios { 3 | compatible = "skeleton, compatible"; 4 | 5 | pin_a_name = <&gpio5 GPIO_C0 GPIO_ACTIVE_HIGH>; 6 | pin_b_name = <&gpio8 GPIO_B0 GPIO_ACTIVE_HIGH>; 7 | pin_c_name = <&gpio8 GPIO_B1 GPIO_ACTIVE_LOW>; 8 | }; 9 | }; 10 | -------------------------------------------------------------------------------- /rk3288/debug/platform_driver_test/skeleton_ss.h: -------------------------------------------------------------------------------- 1 | #ifndef _SKELETON_H_ 2 | #define _SKELETON_H_ 3 | 4 | /* 5 | * Describe a pin 6 | * gpio_pin : gpio pin number 7 | * name : gpio name 8 | */ 9 | struct pin_desc { 10 | int gpio_pin; 11 | int gpio_active_flag; 12 | char name[20]; 13 | }; 14 | 15 | /* skeleton gpios, pdata or chip */ 16 | struct skeleton_chip { 17 | char name[20]; 18 | int pin_name_index; 19 | int value; 20 | 21 | /* a struct point array which contain of gpio_nr struct point */ 22 | struct pin_desc **pd; 23 | 24 | /* kobject */ 25 | struct kobject kobj; 26 | }; 27 | 28 | /* equal to dts pin name which is low case in pcb file */ 29 | const char *dts_name[] = { 30 | "pin_a_name", 31 | "pin_b_name", 32 | "pin_c_name", 33 | }; 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /rk3288/debug/platform_driver_test/spinlock_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | struct locktest_chip { 16 | spinlock_t lock; 17 | }; 18 | 19 | static int spinlock_test_probe(struct platform_device *pdev) 20 | { 21 | struct locktest_chip *chip; 22 | int ret = 0; 23 | 24 | printk("%s, %d\n", __FUNCTION__, __LINE__); 25 | 26 | /* alloc for chip point */ 27 | chip = devm_kzalloc(&pdev->dev, sizeof(struct locktest_chip), GFP_KERNEL); 28 | if (!chip) 29 | { 30 | printk("no memory\n"); 31 | ret = -ENOMEM; 32 | } 33 | 34 | /* set pdata */ 35 | dev_set_drvdata(&pdev->dev, (void *)chip); 36 | 37 | /* visit the race conditon area */ 38 | spin_lock(&chip->lock); 39 | printk("Accessing race condition area...\n"); 40 | #ifdef TRY_TO_SLEEP 41 | /* 42 | * sleep is not allow in spinlock context 43 | * using for (i = 0; i < loop; i++); instead 44 | * or using mutex 45 | */ 46 | msleep(1); 47 | #endif 48 | spin_unlock(&chip->lock); 49 | 50 | return ret; 51 | } 52 | 53 | static int spinlock_test_remove(struct platform_device *pdev) 54 | { 55 | printk("%s, %d\n", __FUNCTION__, __LINE__); 56 | 57 | return 0; 58 | } 59 | 60 | static const struct of_device_id spinlock_test_dt_ids[] = { 61 | {.compatible = "lock-test",}, 62 | {}, 63 | }; 64 | 65 | static struct platform_driver spinlock_test = { 66 | .driver = { 67 | .name = "locktest example", 68 | .owner = THIS_MODULE, 69 | .of_match_table = of_match_ptr(spinlock_test_dt_ids), 70 | }, 71 | .probe = spinlock_test_probe, 72 | .remove = spinlock_test_remove, 73 | }; 74 | 75 | module_platform_driver(spinlock_test); 76 | 77 | MODULE_LICENSE("GPL"); 78 | MODULE_AUTHOR("zeroway "); 79 | MODULE_DESCRIPTION("locktest"); 80 | -------------------------------------------------------------------------------- /rk3288/debug/platform_driver_test/test_pf.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #ifdef CONFIG_HAS_EARLYSUSPEND 21 | #include 22 | #endif 23 | #include 24 | #include 25 | 26 | #if 0 27 | / { 28 | my_test_node { 29 | compatible = "test_platform"; 30 | VCC_TP-supply = <&ldo4_reg>; 31 | }; 32 | }; 33 | #endif 34 | 35 | static struct regulator *supply; 36 | static int test_pf_probe(struct platform_device *pdev) 37 | { 38 | int ret; 39 | 40 | printk("%s, %d\n", __FUNCTION__, __LINE__); 41 | supply = devm_regulator_get(&pdev->dev, "VCC_TP"); 42 | if (IS_ERR(supply)) { 43 | printk("regulator get of vdd_ana failed"); 44 | ret = PTR_ERR(supply); 45 | supply = NULL; 46 | return -1; 47 | } 48 | 49 | /* Enable the regulator */ 50 | ret = regulator_enable(supply); 51 | printk("Enable regulator :) ret = %d\n", ret); 52 | 53 | return 0; 54 | } 55 | 56 | static const struct of_device_id test_pf_dt_ids[] = { 57 | { .compatible = "test_platform", }, 58 | {} 59 | }; 60 | 61 | static int test_pf_remove(struct platform_device *dev) 62 | { 63 | int ret; 64 | 65 | printk("%s, %d\n", __FUNCTION__, __LINE__); 66 | /* Disable the regulator */ 67 | ret = regulator_disable(supply); 68 | printk("Disable regulator :( ret = %d\n", ret); 69 | return 0; 70 | } 71 | 72 | static int test_pf_suspend(struct platform_device *dev, pm_message_t state) 73 | { 74 | printk("%s, %d\n", __FUNCTION__, __LINE__); 75 | return 0; 76 | } 77 | 78 | static int test_pf_resume(struct platform_device *dev) 79 | { 80 | printk("%s, %d\n", __FUNCTION__, __LINE__); 81 | return 0; 82 | } 83 | 84 | static void test_pf_shutdown(struct platform_device *dev) 85 | { 86 | printk("%s, %d\n", __FUNCTION__, __LINE__); 87 | } 88 | 89 | static struct platform_driver test_pf_driver = { 90 | .driver = { 91 | .name = "test platform driver", 92 | .owner = THIS_MODULE, 93 | .of_match_table = of_match_ptr(test_pf_dt_ids), 94 | }, 95 | .probe = test_pf_probe, 96 | .remove = test_pf_remove, 97 | .suspend = test_pf_suspend, 98 | .resume = test_pf_resume, 99 | .shutdown = test_pf_shutdown, 100 | }; 101 | 102 | static int __init test_pf_init(void) 103 | { 104 | return platform_driver_register(&test_pf_driver); 105 | } 106 | 107 | static void __exit test_pf_exit(void) 108 | { 109 | platform_driver_unregister(&test_pf_driver); 110 | } 111 | 112 | module_init(test_pf_init); 113 | module_exit(test_pf_exit); 114 | MODULE_LICENSE("GPL"); 115 | -------------------------------------------------------------------------------- /rk3288/debug/platform_driver_test/test_pf.dtsi: -------------------------------------------------------------------------------- 1 | / { 2 | my_test_node { 3 | compatible = "test_platform"; 4 | VCC_TP-supply = <&ldo4_reg>; 5 | }; 6 | }; 7 | -------------------------------------------------------------------------------- /rk3288/debug/pwm/.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.ko 3 | *.cmd 4 | Module.symvers 5 | modules.order 6 | .tmp_versions/ 7 | *.mod.c 8 | *.mod.c 9 | -------------------------------------------------------------------------------- /rk3288/debug/pwm/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile 2 | # Comment/uncomment the following line to disable/enable debugging 3 | # DEBUG = y 4 | 5 | # Usage 6 | # make CROSS_COMPILE= KERNEL_DIR= KERNEL_BUID_OUTPUT= 7 | # 8 | # make CROSS_COMPILE=/home/zeroway/3288/51/src/3288_5.1_v2/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/arm-eabi- KERNEL_DIR=/home/zeroway/3288/51/src/3288_5.1_v2/kernel KERNEL_BUID_OUTPUT=/home/zeroway/3288/51/src/3288_5.1_v2/out/target/product/rk3288/obj/KERNEL 9 | 10 | # Add your debugging flag (or not) to CFLAGS 11 | ifeq ($(DEBUG),y) 12 | DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines 13 | else 14 | DEBFLAGS = -O2 15 | endif 16 | 17 | obj-m := pwm_backlight.o 18 | KERNEL_DIR ?= /lib/modules/$(shell uname -r)/build 19 | KERNEL_BUID_OUTPUT ?=$(KERNEL_DIR) 20 | CC = $(CROSS_COMPILE)gcc 21 | LD = $(CROSS_COMPILE)ld 22 | PWD := $(shell pwd) 23 | 24 | modules: 25 | $(MAKE) -C $(KERNEL_DIR) M=$(PWD) O=$(KERNEL_BUID_OUTPUT) modules 26 | 27 | clean: 28 | rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions modules.order Module.symvers 29 | 30 | depend .depend dep: 31 | $(CC) $(CFLAGS) -M *.c > .depend 32 | 33 | ifeq (.depend,$(wildcard .depend)) 34 | include .depend 35 | endif 36 | -------------------------------------------------------------------------------- /rk3288/debug/pwm/README.md: -------------------------------------------------------------------------------- 1 | # Linux PWM 2 | 3 | [参考文章http://www.wowotech.net/comm/pwm_overview.html?utm_source=tuicool](http://www.wowotech.net/comm/pwm_overview.html?utm_source=tuicool) 4 | 5 | # 硬件连接图 6 | 7 | ![pwm](./pwm01.png) 8 | 9 | ![pwm](./pwm02.png) 10 | 11 | PWM引脚功能配置 12 | 13 | #define PWM0 0x7a01 14 | GPIO7_A0 配置成了PWM功能 15 | 16 | pwm0_pin:pwm0 { 17 | rockchip,pins = ; 18 | rockchip,pull = ; 19 | rockchip,drive = ; 20 | }; 21 | 22 | PWM控制器设备树描述 23 | 24 | pwm0: pwm@ff680000 { 25 | compatible = "rockchip,rk-pwm"; 26 | reg = <0xff680000 0x10>; 27 | 28 | /* used by driver on remotectl'pwm */ 29 | interrupts = ; 30 | #pwm-cells = <2>; 31 | pinctrl-names = "default"; 32 | pinctrl-0 = <&pwm0_pin>; 33 | clocks = <&clk_gates11 11>; 34 | clock-names = "pclk_pwm"; 35 | status = "disabled"; 36 | }; 37 | 38 | 背光驱动的设备树描述 39 | 40 | backlight { 41 | compatible = "pwm-backlight"; 42 | pwms = <&pwm0 0 25000>; 43 | brightness-levels = <255 254 253 252 251 250 249 248 247 246 245 244 243 242 241 240 44 | 239 238 237 236 235 234 233 232 231 230 229 228 227 226 225 224 223 222 221 220 45 | 219 218 217 216 215 214 213 212 211 210 209 208 207 206 205 204 203 202 201 200 46 | 199 198 197 196 195 194 193 192 191 190 189 188 187 186 185 184 183 182 181 180 47 | 179 178 177 176 175 174 173 172 171 170 169 168 167 166 165 164 163 162 161 160 48 | 159 158 157 156 155 154 153 152 151 150 149 148 147 146 145 144 143 142 141 140 49 | 139 138 137 136 135 134 133 132 131 130 129 128 127 126 125 124 123 122 121 120 50 | 119 118 117 116 115 114 113 112 111 110 109 108 107 106 105 104 103 102 101 100 51 | 99 98 97 96 95 94 93 92 91 90 89 88 87 86 85 84 83 82 81 80 79 78 77 76 75 74 73 72 71 70 52 | 69 68 67 66 65 64 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 53 | 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 54 | 9 8 7 6 5 4 3 2 1 0>; 55 | default-brightness-level = <200>; 56 | enable-gpios = <&gpio7 GPIO_A2 GPIO_ACTIVE_HIGH>; 57 | }; 58 | 59 | # Usage 60 | 61 | 在主dts文件中包含pwm的dtsi文件 62 | 63 | #include "pwm_backlight.dtsi" 64 | 65 | # 测试方法 66 | 67 | ### 每一秒钟修改一次背光 68 | 69 | ```shell 70 | # i=0;while (($i < 250)); do echo $i > /sys/devices/backlight.25/backlight/my_backlight/brightness; ((i+=20)); sleep 1;done 71 | ``` 72 | 73 | ### 循环修改背光 74 | 75 | ```shell 76 | # i=0;while (($i < 250)); do echo $i > /sys/devices/backlight.25/backlight/my_backlight/brightness; ((i+=20)); sleep 1;done 77 | # while true; do if (($i > 250)) then;i=0 fi; echo $i; i+=1;done 78 | ``` 79 | 80 | ```shell 81 | i=0 82 | while true 83 | do 84 | if(($i > 250)) then 85 | i=0 86 | fi 87 | echo $i > /sys/devices/backlight.25/backlight/my_backlight/brightness; 88 | ((i+=10)) 89 | sleep 1 90 | done 91 | ``` 92 | -------------------------------------------------------------------------------- /rk3288/debug/pwm/pwm01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3288/debug/pwm/pwm01.png -------------------------------------------------------------------------------- /rk3288/debug/pwm/pwm02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3288/debug/pwm/pwm02.png -------------------------------------------------------------------------------- /rk3288/debug/pwm/pwm_backlight.dtsi: -------------------------------------------------------------------------------- 1 | /{ 2 | backlight { 3 | compatible = "pwm-backlight"; 4 | pwms = <&pwm0 0 25000>; 5 | brightness-levels = <255 254 253 252 251 250 249 248 247 246 245 244 243 242 241 240 6 | 239 238 237 236 235 234 233 232 231 230 229 228 227 226 225 224 223 222 221 220 7 | 219 218 217 216 215 214 213 212 211 210 209 208 207 206 205 204 203 202 201 200 8 | 199 198 197 196 195 194 193 192 191 190 189 188 187 186 185 184 183 182 181 180 9 | 179 178 177 176 175 174 173 172 171 170 169 168 167 166 165 164 163 162 161 160 10 | 159 158 157 156 155 154 153 152 151 150 149 148 147 146 145 144 143 142 141 140 11 | 139 138 137 136 135 134 133 132 131 130 129 128 127 126 125 124 123 122 121 120 12 | 119 118 117 116 115 114 113 112 111 110 109 108 107 106 105 104 103 102 101 100 13 | 99 98 97 96 95 94 93 92 91 90 89 88 87 86 85 84 83 82 81 80 79 78 77 76 75 74 73 72 71 70 14 | 69 68 67 66 65 64 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 15 | 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 16 | 9 8 7 6 5 4 3 2 1 0>; 17 | default-brightness-level = <200>; 18 | enable-gpios = <&gpio7 GPIO_A2 GPIO_ACTIVE_HIGH>; 19 | }; 20 | }; 21 | -------------------------------------------------------------------------------- /rk3288/debug/regmap/.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.ko 3 | *.cmd 4 | Module.symvers 5 | modules.order 6 | .tmp_versions/ 7 | *.mod.c 8 | *.mod.c 9 | -------------------------------------------------------------------------------- /rk3288/debug/regmap/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile 2 | # Comment/uncomment the following line to disable/enable debugging 3 | # DEBUG = y 4 | 5 | # Usage 6 | # make CC= KERNELDIR= 7 | # 8 | # make CC=/home/zeroway/3288/src/3288_4.4/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/arm-eabi-gcc KERNELDIR=/home/zeroway/3288/src/3288_4.4/kernel 9 | 10 | # Add your debugging flag (or not) to CFLAGS 11 | ifeq ($(DEBUG),y) 12 | DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines 13 | else 14 | DEBFLAGS = -O2 15 | endif 16 | 17 | obj-m := i2c_regmap.o 18 | KERNELDIR ?= /lib/modules/$(shell uname -r)/build 19 | CC ?= gcc 20 | PWD := $(shell pwd) 21 | 22 | modules: 23 | $(MAKE) -C $(KERNELDIR) M=$(PWD) modules 24 | 25 | clean: 26 | rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions modules.order Module.symvers 27 | 28 | depend .depend dep: 29 | $(CC) $(CFLAGS) -M *.c > .depend 30 | 31 | ifeq (.depend,$(wildcard .depend)) 32 | include .depend 33 | endif 34 | -------------------------------------------------------------------------------- /rk3288/debug/regmap/README.md: -------------------------------------------------------------------------------- 1 | # Regmap 2 | 3 | [参考链接http://www.tinylab.org/kernel-explore-regmap-framework/](http://www.tinylab.org/kernel-explore-regmap-framework/) 4 | 5 | ![regmap](./regmap.png) 6 | -------------------------------------------------------------------------------- /rk3288/debug/regmap/regmap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3288/debug/regmap/regmap.png -------------------------------------------------------------------------------- /rk3288/debug/regulator/.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.ko 3 | *.cmd 4 | Module.symvers 5 | modules.order 6 | .tmp_versions/ 7 | *.mod.c 8 | *.mod.c 9 | -------------------------------------------------------------------------------- /rk3288/debug/regulator/DS-ACT8846-PrB-26DEC12-M.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3288/debug/regulator/DS-ACT8846-PrB-26DEC12-M.pdf -------------------------------------------------------------------------------- /rk3288/debug/regulator/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile 2 | # Comment/uncomment the following line to disable/enable debugging 3 | # DEBUG = y 4 | 5 | # Usage 6 | # make CC= KERNELDIR= 7 | # 8 | # make CC=/home/zeroway/3288/src/3288_4.4/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/arm-eabi-gcc KERNELDIR=/home/zeroway/3288/src/3288_4.4/kernel 9 | 10 | # Add your debugging flag (or not) to CFLAGS 11 | ifeq ($(DEBUG),y) 12 | DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines 13 | else 14 | DEBFLAGS = -O2 15 | endif 16 | 17 | obj-m := regulator.o 18 | obj-m += act8846.o 19 | KERNELDIR ?= /lib/modules/$(shell uname -r)/build 20 | CC ?= gcc 21 | PWD := $(shell pwd) 22 | 23 | modules: 24 | $(MAKE) -C $(KERNELDIR) M=$(PWD) modules 25 | 26 | clean: 27 | rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions modules.order Module.symvers 28 | 29 | depend .depend dep: 30 | $(CC) $(CFLAGS) -M *.c > .depend 31 | 32 | ifeq (.depend,$(wildcard .depend)) 33 | include .depend 34 | endif 35 | -------------------------------------------------------------------------------- /rk3288/debug/regulator/act8846.h: -------------------------------------------------------------------------------- 1 | #ifndef _ACT8846_H_ 2 | #define _ACT8846_H_ 3 | 4 | #define REGISTER_NUMBERS 0xF5 5 | #define ACT8846_BUCK1_SET_VOL_BASE 0x10 6 | #define ACT8846_NUM_REGULATORS 13 7 | 8 | #define ACT8846_DCDC1 0 9 | #define ACT8846_LDO1 4 10 | #define BUCK_VOL_MASK 0x3f 11 | #define LDO_VOL_MASK 0x3f 12 | #define VOL_MIN_IDX 0x00 13 | #define VOL_MAX_IDX 0x3f 14 | #define ACT8846_BUCK1_SET_VOL_BASE 0x10 15 | #define ACT8846_BUCK2_SET_VOL_BASE 0x20 16 | #define ACT8846_BUCK3_SET_VOL_BASE 0x30 17 | #define ACT8846_BUCK4_SET_VOL_BASE 0x40 18 | 19 | #define ACT8846_BUCK2_SLP_VOL_BASE 0x21 20 | #define ACT8846_BUCK3_SLP_VOL_BASE 0x31 21 | #define ACT8846_BUCK4_SLP_VOL_BASE 0x41 22 | 23 | #define ACT8846_LDO1_SET_VOL_BASE 0x50 24 | #define ACT8846_LDO2_SET_VOL_BASE 0x58 25 | #define ACT8846_LDO3_SET_VOL_BASE 0x60 26 | #define ACT8846_LDO4_SET_VOL_BASE 0x68 27 | #define ACT8846_LDO5_SET_VOL_BASE 0x70 28 | #define ACT8846_LDO6_SET_VOL_BASE 0x80 29 | #define ACT8846_LDO7_SET_VOL_BASE 0x90 30 | #define ACT8846_LDO8_SET_VOL_BASE 0xa0 31 | 32 | #define ACT8846_BUCK1_CONTR_BASE 0x12 33 | #define ACT8846_BUCK2_CONTR_BASE 0x22 34 | #define ACT8846_BUCK3_CONTR_BASE 0x32 35 | #define ACT8846_BUCK4_CONTR_BASE 0x42 36 | 37 | #define ACT8846_LDO1_CONTR_BASE 0x51 38 | #define ACT8846_LDO2_CONTR_BASE 0x59 39 | #define ACT8846_LDO3_CONTR_BASE 0x61 40 | #define ACT8846_LDO4_CONTR_BASE 0x69 41 | #define ACT8846_LDO5_CONTR_BASE 0x71 42 | #define ACT8846_LDO6_CONTR_BASE 0x81 43 | #define ACT8846_LDO7_CONTR_BASE 0x91 44 | #define ACT8846_LDO8_CONTR_BASE 0xa1 45 | #define ACT8846_BUCK_SET_VOL_REG(x) (buck_set_vol_base_addr[x]) 46 | #define ACT8846_BUCK_CONTR_REG(x) (buck_contr_base_addr[x]) 47 | #define ACT8846_LDO_SET_VOL_REG(x) (ldo_set_vol_base_addr[x]) 48 | #define ACT8846_LDO_CONTR_REG(x) (ldo_contr_base_addr[x]) 49 | 50 | /* 用来表示device tree里的信息,用pdata表示 */ 51 | struct act8846_board { 52 | struct regulator_init_data *rid[ACT8846_NUM_REGULATORS]; 53 | struct device_node *np[ACT8846_NUM_REGULATORS]; 54 | 55 | /* pins */ 56 | int pmic_sleep_gpio; 57 | int pmic_hold_gpio; 58 | 59 | /* functions */ 60 | bool pmic_sleep; 61 | }; 62 | 63 | /* 自定义数据结构,用chip表示 */ 64 | struct act8846 { 65 | int num_regulators; 66 | struct regulator_dev **rdev; 67 | struct device *dev; 68 | struct i2c_client *client; 69 | struct regmap *regmap; 70 | 71 | /* pins */ 72 | int pmic_sleep_gpio; 73 | int pmic_hold_gpio; 74 | }; 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /rk3288/debug/regulator/dcdc_ldo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3288/debug/regulator/dcdc_ldo.png -------------------------------------------------------------------------------- /rk3288/debug/regulator/rk32x_LINUX3.10_pmu 20140613.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3288/debug/regulator/rk32x_LINUX3.10_pmu 20140613.pdf -------------------------------------------------------------------------------- /rk3288/debug/regulator/rk818_powertree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3288/debug/regulator/rk818_powertree.png -------------------------------------------------------------------------------- /rk3288/debug/regulator/rk818_test.dtsi: -------------------------------------------------------------------------------- 1 | &i2c0 { 2 | consumer1@5d { 3 | compatible = "Consumer1"; 4 | status = "okay"; 5 | reg = <0x5d>; 6 | VCC_TP-supply = <&rk818_ldo2_reg>; 7 | }; 8 | 9 | consumer2@5e { 10 | compatible = "Consumer2"; 11 | status = "okay"; 12 | reg = <0x5e>; 13 | VCC_TP-supply = <&rk818_ldo2_reg>; 14 | }; 15 | }; 16 | -------------------------------------------------------------------------------- /rk3288/debug/regulator/table5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3288/debug/regulator/table5.png -------------------------------------------------------------------------------- /rk3288/debug/regulator/vcc_tp_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3288/debug/regulator/vcc_tp_1.png -------------------------------------------------------------------------------- /rk3288/debug/regulator/vcc_tp_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3288/debug/regulator/vcc_tp_2.png -------------------------------------------------------------------------------- /rk3288/debug/skeleton/.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.ko 3 | *.cmd 4 | Module.symvers 5 | modules.order 6 | .tmp_versions/ 7 | *.mod.c 8 | *.mod.c 9 | -------------------------------------------------------------------------------- /rk3288/debug/skeleton/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile 2 | # Comment/uncomment the following line to disable/enable debugging 3 | # DEBUG = y 4 | 5 | # Usage 6 | # make CROSS_COMPILE= KERNEL_DIR= KERNEL_BUID_OUTPUT= 7 | # 8 | # make CROSS_COMPILE=/home/zeroway/rk3399/tool/gcc-linaro-4.9.4-2017.01-i686_aarch64-linux-gnu/bin/aarch64-linux-gnu- KERNEL_DIR=/home/zeroway/rk3399/src/firefly/kernel KERNEL_BUID_OUTPUT=/home/zeroway/rk3399/src/firefly/out/target/product/rk3399_firefly_box/obj/KERNEL 9 | 10 | # Add your debugging flag (or not) to CFLAGS 11 | ifeq ($(DEBUG),y) 12 | DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines 13 | else 14 | DEBFLAGS = -O2 15 | endif 16 | 17 | obj-m := bitmap_test.o 18 | 19 | KERNEL_DIR ?= /lib/modules/`uname -r`/build 20 | KERNEL_BUID_OUTPUT ?=$(KERNEL_DIR) 21 | CC = $(CROSS_COMPILE)gcc 22 | LD = $(CROSS_COMPILE)ld 23 | PWD := $(shell pwd) 24 | ARCH := x86_64 25 | 26 | modules: 27 | $(MAKE) -C $(KERNEL_DIR) ARCH=$(ARCH) M=$(PWD) O=$(KERNEL_DIR) modules 28 | 29 | clean: 30 | rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions modules.order Module.symvers 31 | 32 | depend .depend dep: 33 | $(CC) $(CFLAGS) -M *.c > .depend 34 | 35 | ifeq (.depend,$(wildcard .depend)) 36 | include .depend 37 | endif 38 | -------------------------------------------------------------------------------- /rk3288/debug/skeleton/README.md: -------------------------------------------------------------------------------- 1 | # 如何使用 2 | 3 | 替换VENDOR和MODULE为相应的名字 4 | 5 | %s/VENDOR/your_verdor_name/g 6 | %s/MODULE/your_module_name/g 7 | 8 | 编译说明 9 | 10 | CROSS_COMPILE指定交叉编译工具链的前缀 11 | 12 | KERNEL_DIR执行内核代码路径 13 | 14 | 编译内核时没有使用O选项指定编译生成文件的输入路径 15 | KERNEL_BUID_OUTPUT 就和内核路径一致 16 | 17 | 编译内核时有使用O选项指定编译生成文件的输入路径 18 | KERNEL_BUID_OUTPUT 就为相应的路径 19 | -------------------------------------------------------------------------------- /rk3288/debug/skeleton/skeleton.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | static int VENDOR_MODULE_init(void) 5 | { 6 | printk("%s, %d\n", __FUNCTION__, __LINE__); 7 | return 0; 8 | } 9 | 10 | static void VENDOR_MODULE_exit (void) 11 | { 12 | printk("%s, %d\n", __FUNCTION__, __LINE__); 13 | } 14 | 15 | module_init(VENDOR_MODULE_init); 16 | module_exit(VENDOR_MODULE_exit); 17 | MODULE_LICENSE("GPL"); 18 | -------------------------------------------------------------------------------- /rk3288/debug/spi/.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.ko 3 | *.cmd 4 | Module.symvers 5 | modules.order 6 | .tmp_versions/ 7 | *.mod.c 8 | *.mod.c 9 | -------------------------------------------------------------------------------- /rk3288/debug/spi/README.md: -------------------------------------------------------------------------------- 1 | # SPI 2 | 3 | ## 设备树描述 4 | 5 | 每一个spi对应一个SPI控制器(一般情况下bus和控制器配置成如下对应关系) 6 | 7 | spi0 ==> bus 0 8 | spi1 ==> bus 1 9 | spi2 ==> bus 2 10 | 11 | 其中每个SPI控制器上片选数在原理图上描述如下 12 | 在控制器描述上也可以找得到相应信息(以下是RK3288的信息) 13 | 14 | SPI0_CSn0 15 | SPI0_CSn1 16 | 17 | SPI1_CSn0 18 | 19 | SPI2_CSn0 20 | SPI2_CSn1 21 | 22 | ![spi0_cs](./spi0_cs.png) 23 | 24 | ![spi1_cs](./spi1_cs.png) 25 | 26 | ![spi2_cs](./spi2_cs.png) 27 | 28 | ## 应用实例 29 | 30 | SPI2控制器上接有两个SPI设备分别使用cs0(demoAAA),cs1(demoBBB) 31 | 32 | &spi2 { 33 | demoAAA@20 { 34 | compatible = "spi_test_bus2_cs0"; 35 | reg = <0>; 36 | }; 37 | 38 | demoBBB@21 { 39 | compatible = "spi_test_bus2_cs1"; 40 | reg = <1>; 41 | }; 42 | }; 43 | 44 | 其中注意以下两个地方 45 | 46 | @后面的地址 47 | 48 | demoAAA@20 49 | 2 : 表示bus2(spi2) 50 | 0 : 表示使用的是片选0 51 | 52 | demoBBB@21 53 | 2 : 表示bus2(spi2) 54 | 1 : 表示使用的是片选1 55 | 56 | reg表示使用的片选 57 | 58 | reg = <0> 表示使用的是片选0 59 | reg = <1> 表示使用的是片选1 60 | 61 | ## 数据结构 62 | 63 | spi_transfer 64 | 65 | struct spi_transfer - a read/write buffer pair 66 | @tx_buf: data to be written (dma-safe memory), or NULL 67 | @rx_buf: data to be read (dma-safe memory), or NULL 68 | @len: size of rx and tx buffers (in bytes) 69 | @cs_change: affects chipselect after this transfer completes 70 | 71 | ## Debug 72 | 73 | read and write test 74 | 75 | cat /dev/ttysWK0 76 | echo 1 > /dev/ttysWK0 77 | 78 | 测试脚本 79 | 80 | i=1 81 | while true 82 | do 83 | if [ $i -eq 10 ] 84 | then 85 | (( i=1 )) 86 | fi 87 | echo $i > /dev/ttysWK0 88 | sleep 1 89 | (( i+=1 )) 90 | done 91 | -------------------------------------------------------------------------------- /rk3288/debug/spi/spi0_cs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3288/debug/spi/spi0_cs.png -------------------------------------------------------------------------------- /rk3288/debug/spi/spi1_cs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3288/debug/spi/spi1_cs.png -------------------------------------------------------------------------------- /rk3288/debug/spi/spi2_cs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3288/debug/spi/spi2_cs.png -------------------------------------------------------------------------------- /rk3288/debug/timer/.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.ko 3 | *.cmd 4 | Module.symvers 5 | modules.order 6 | .tmp_versions/ 7 | *.mod.c 8 | *.mod.c 9 | -------------------------------------------------------------------------------- /rk3288/debug/timer/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile 2 | # Comment/uncomment the following line to disable/enable debugging 3 | # DEBUG = y 4 | 5 | # Usage 6 | # make CROSS_COMPILE= KERNEL_DIR= KERNEL_BUID_OUTPUT= 7 | # 8 | # make CROSS_COMPILE=/home/zeroway/rk3399/src/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin/aarch64-linux-android- KERNEL_DIR=/home/zeroway/rk3399/src/kernel KERNEL_BUID_OUTPUT=/home/zeroway/rk3399/src/out/target/product/rk3399_firefly_box/obj/KERNEL 9 | 10 | # Add your debugging flag (or not) to CFLAGS 11 | ifeq ($(DEBUG),y) 12 | DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines 13 | else 14 | DEBFLAGS = -O2 15 | endif 16 | 17 | obj-m := mytimer_test.o 18 | 19 | KERNEL_DIR ?= /lib/modules/$(shell uname -r)/build 20 | KERNEL_BUID_OUTPUT ?=$(KERNEL_DIR) 21 | CC = $(CROSS_COMPILE)gcc 22 | LD = $(CROSS_COMPILE)ld 23 | PWD := $(shell pwd) 24 | 25 | modules: 26 | $(MAKE) -C $(KERNEL_DIR) ARCH=arm64 M=$(PWD) O=$(KERNEL_BUID_OUTPUT) modules 27 | 28 | clean: 29 | rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions modules.order Module.symvers 30 | 31 | depend .depend dep: 32 | $(CC) $(CFLAGS) -M *.c > .depend 33 | 34 | ifeq (.depend,$(wildcard .depend)) 35 | include .depend 36 | endif 37 | -------------------------------------------------------------------------------- /rk3288/debug/timer/README.md: -------------------------------------------------------------------------------- 1 | # TIMER 2 | -------------------------------------------------------------------------------- /rk3288/debug/timer/mytimer_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define EXPIRES_PERIOD (5*HZ) 9 | 10 | struct self_define_struct { 11 | struct timer_list timer; 12 | }; 13 | 14 | static int g_cnt = 0; 15 | struct self_define_struct g_sds; 16 | const char *important_code = "this is a secret"; 17 | 18 | /* 19 | * printk_ratelimit函数的速率控制根据两个文件来确定,分别是: 20 | * 1. /proc/sys/kernel/printk_ratelimit 限制的时间间隔,默认值是5 21 | * 2. /proc/sys/kernel/printk_ratelimit_burst 22 | * 时间间隔内的最大打印条数,默认值是10 23 | * 所以默认的打印速率是每5秒最多打印10条 24 | */ 25 | static void timeout_handler(unsigned long tdata) 26 | { 27 | int i; 28 | const char *tmp = (const char *)tdata; 29 | 30 | for (i = 0; i < 100; i++) 31 | if(printk_ratelimit()) 32 | printk("%s got data[%s] %d times\n", __FUNCTION__, tmp, g_cnt++); 33 | 34 | g_cnt = 0; 35 | g_sds.timer.expires = jiffies + EXPIRES_PERIOD; 36 | add_timer(&g_sds.timer); 37 | } 38 | 39 | static int mytimer_test_init(void) 40 | { 41 | printk("%s, %d\n", __FUNCTION__, __LINE__); 42 | 43 | /* init timer */ 44 | init_timer(&g_sds.timer); 45 | 46 | /* setup the timer */ 47 | g_sds.timer.expires = jiffies + EXPIRES_PERIOD; 48 | g_sds.timer.function = timeout_handler; 49 | g_sds.timer.data = (unsigned long)important_code; 50 | 51 | /* add to system */ 52 | add_timer(&g_sds.timer); 53 | 54 | return 0; 55 | } 56 | 57 | static void mytimer_test_exit(void) 58 | { 59 | printk("%s, %d\n", __FUNCTION__, __LINE__); 60 | del_timer(&g_sds.timer); 61 | } 62 | 63 | module_init(mytimer_test_init) 64 | module_exit(mytimer_test_exit) 65 | -------------------------------------------------------------------------------- /rk3288/debug/timer_workq/.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.ko 3 | *.cmd 4 | Module.symvers 5 | modules.order 6 | .tmp_versions/ 7 | *.mod.c 8 | *.mod.c 9 | -------------------------------------------------------------------------------- /rk3288/debug/timer_workq/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile 2 | # Comment/uncomment the following line to disable/enable debugging 3 | # DEBUG = y 4 | 5 | # Usage 6 | # make CROSS_COMPILE= KERNEL_DIR= KERNEL_BUID_OUTPUT= 7 | # 8 | # make CROSS_COMPILE=/home/zeroway/3288/51/src/3288_5.1_v2/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/arm-eabi- KERNEL_DIR=/home/zeroway/3288/51/src/3288_5.1_v2/kernel KERNEL_BUID_OUTPUT=/home/zeroway/3288/51/src/3288_5.1_v2/out/target/product/rk3288/obj/KERNEL 9 | 10 | # Add your debugging flag (or not) to CFLAGS 11 | ifeq ($(DEBUG),y) 12 | DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines 13 | else 14 | DEBFLAGS = -O2 15 | endif 16 | 17 | obj-m := timer_workq.o 18 | KERNEL_DIR ?= /lib/modules/$(shell uname -r)/build 19 | KERNEL_BUID_OUTPUT ?=$(KERNEL_DIR) 20 | CC = $(CROSS_COMPILE)gcc 21 | LD = $(CROSS_COMPILE)ld 22 | PWD := $(shell pwd) 23 | 24 | modules: 25 | $(MAKE) -C $(KERNEL_DIR) M=$(PWD) O=$(KERNEL_BUID_OUTPUT) modules 26 | 27 | clean: 28 | rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions modules.order Module.symvers 29 | 30 | depend .depend dep: 31 | $(CC) $(CFLAGS) -M *.c > .depend 32 | 33 | ifeq (.depend,$(wildcard .depend)) 34 | include .depend 35 | endif 36 | -------------------------------------------------------------------------------- /rk3288/debug/timer_workq/README.md: -------------------------------------------------------------------------------- 1 | # TIMER AND WORKQUEUE 2 | -------------------------------------------------------------------------------- /rk3288/debug/timer_workq/timer_workq.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #define EXPIRES_PERIOD (5*HZ) 10 | 11 | struct self_define_struct { 12 | struct timer_list mytimer; 13 | struct work_struct mywork; 14 | }; 15 | 16 | static int g_cnt = 1; 17 | 18 | /* just for delete mytimer in the exit function */ 19 | struct timer_list *g_timer; 20 | 21 | /* just for free the sds */ 22 | struct self_define_struct *g_sds; 23 | 24 | static void mywork_handler(struct work_struct *work) 25 | { 26 | struct self_define_struct *sds = container_of(work, struct self_define_struct, mywork); 27 | 28 | printk("do work[%d]\n", g_cnt++); 29 | 30 | sds->mytimer.expires = jiffies + EXPIRES_PERIOD; 31 | add_timer(&sds->mytimer); 32 | } 33 | 34 | static void timeout_handler(unsigned long tdata) 35 | { 36 | struct self_define_struct *tmp = (struct self_define_struct *)tdata; 37 | 38 | printk("timeout[%d]...", g_cnt); 39 | 40 | /* do my work */ 41 | schedule_work(&tmp->mywork); 42 | } 43 | 44 | static int timer_workq_init(void) 45 | { 46 | struct self_define_struct *sds; 47 | sds = kzalloc(sizeof(struct self_define_struct), GFP_KERNEL); 48 | if (sds == NULL) 49 | return -ENOMEM; 50 | 51 | g_sds = sds; 52 | 53 | printk("%s, %d\n", __FUNCTION__, __LINE__); 54 | 55 | /* init mytimer */ 56 | init_timer(&sds->mytimer); 57 | g_timer = &sds->mytimer; 58 | 59 | /* setup the timer */ 60 | sds->mytimer.expires = jiffies + EXPIRES_PERIOD; 61 | sds->mytimer.function = timeout_handler; 62 | sds->mytimer.data = (unsigned long)sds; 63 | 64 | /* add to system */ 65 | add_timer(&sds->mytimer); 66 | 67 | /* init mywork */ 68 | INIT_WORK(&sds->mywork, mywork_handler); 69 | } 70 | 71 | static void timer_workq_exit(void) 72 | { 73 | printk("%s, %d\n", __FUNCTION__, __LINE__); 74 | del_timer(g_timer); 75 | kfree(g_sds); 76 | } 77 | 78 | module_init(timer_workq_init) 79 | module_exit(timer_workq_exit) 80 | MODULE_LICENSE("GPL"); 81 | -------------------------------------------------------------------------------- /rk3288/debug/uart/Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH:= $(call my-dir) 2 | 3 | # uart_loop 4 | include $(CLEAR_VARS) 5 | LOCAL_SYSTEM_SHARED_LIBRARIES := libc 6 | LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES) 7 | LOCAL_MODULE_TAGS := debug 8 | LOCAL_SRC_FILES := uart_loop_test.c 9 | LOCAL_MODULE := uart_loop 10 | 11 | include $(BUILD_EXECUTABLE) 12 | 13 | # record read write 14 | include $(CLEAR_VARS) 15 | LOCAL_SYSTEM_SHARED_LIBRARIES := libc 16 | LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES) 17 | LOCAL_MODULE_TAGS := debug 18 | LOCAL_SRC_FILES := uart_record_rw.c 19 | LOCAL_MODULE := uart_record_rw 20 | 21 | include $(BUILD_EXECUTABLE) 22 | -------------------------------------------------------------------------------- /rk3288/debug/usb/README.md: -------------------------------------------------------------------------------- 1 | # USB 2 | 3 | 参考文章 4 | 5 | [USB枚举过程](http://blog.csdn.net/myarrow/article/details/8270029) 6 | 7 | [图解USB枚举过程](http://blog.csdn.net/myarrow/article/details/8270060) 8 | 9 | [USB2.0速度识别](http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=30497107&id=5759712) 10 | 11 | ## 描述符 12 | 13 | 设备-配置-接口-端点关系 14 | 15 | + 一般一个设备就一个配置,一个接口,如果设备是多功能符合设备,则有多个接口.端点一般都有好几个 16 | 17 | ## 传输模式 18 | 19 | ### 控制传输 20 | 21 | + 建立阶段 22 | + 数据阶段 23 | + 确认阶段 24 | 25 | ### BULK传输 26 | 27 | ### 中断传输 28 | 29 | ### 同步传输 30 | 31 | ## USB设备的6种状态 32 | 33 | 连接(Attached) 34 | 35 | 上电(Powered) 36 | 37 | 默认状态(Default) 38 | 39 | 地址(Address) 40 | 41 | 配置状态(Configured) 42 | 43 | 挂起状态(Suspend) 44 | 45 | ## 枚举 46 | 47 | 枚举就是从设备读取一些信息,知道设备是什么样的设备,如何进行通信,这样主机就可以根据这些信息来加载合适的驱动程序 48 | 49 | ## 枚举过程 50 | 51 | USB设备插入USB端口或给系统启动时设备上电 52 | 53 | Hub监测它各个端口数据线上(D+/D-)的电压 54 | 55 | + 在hub端,数据线D+和D-都有一个阻值在14.25k到24.8k的下拉电阻Rpd,而在设备端,D+(全速,高速)和D-(低速)上有一个1.5k的上拉电阻Rpu.当设备插入到hub端口时,有上拉电阻的一根数据线被拉高到幅值的90%的电压(大致是3V).hub检测到它的一根数据线是高电平,就认为是有设备插入,并能根据是D+还是D-被拉高来判断到底是什么设备(全速/低速)插入端口 56 | 57 | Host了解连接的设备 58 | 59 | Hub检测所插入的设备是全速还是低速设备 60 | 61 | + hub通过检测USB总线空闲(Idle)时差分线的高低电压来判断所连接设备的速度类型,当host发来Get_Port_Status请求时,hub就可以将此设备的速度类型信息回复给host 62 | 63 | Hub复位设备 64 | 65 | Host检测所连接的全速设备是否是支持高速模式 66 | 67 | + 主机不断检测设备是否有发送K信号,如果没有则为全速 68 | + 主机不断检测设备是否有发送K信号,如果有且HUB也是高速则HUB必须回复KJKJKJ,设备需要断开1.5K上拉电阻,连接D+/D-上的高速终端电阻,完成进入高速模式的过程 69 | 70 | Hub建立设备和主机之间的信息通道 71 | 72 | + 设备和主机之间的通信通过控制传输,默认地址0,端点号0进行 73 | 74 | 主机发送Get_Descriptor请求获取默认管道的最大包长度 75 | 76 | + 主机此时发送的请求是默认地址0,端点0 77 | 78 | 主机给设备分配一个地址 79 | 80 | 主机获取设备的信息 81 | 82 | + 主机发送Get_Descriptor请求到新地址读取设备描述符 83 | 84 | 主机给设备挂载驱动(复合设备除外) 85 | 86 | 设备驱动选择一个配置 87 | 88 | ## USB调试 89 | 90 | [使用USB monitor抓取USB数据](android_usb.md) 91 | -------------------------------------------------------------------------------- /rk3288/debug/workqueue/.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.ko 3 | *.cmd 4 | Module.symvers 5 | modules.order 6 | .tmp_versions/ 7 | *.mod.c 8 | *.mod.c 9 | -------------------------------------------------------------------------------- /rk3288/debug/workqueue/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile 2 | # Comment/uncomment the following line to disable/enable debugging 3 | # DEBUG = y 4 | 5 | PWD := $(shell pwd) 6 | BUILD_ENV = $(PWD)/../../buildenv 7 | cross_compiler_prefix = $(shell awk -F "CROSS_COMPILE=" '/CROSS_COMPILE=/{print $$2}' $(BUILD_ENV)) 8 | kernel_output = $(shell awk -F "KERNEL_BUILD_OUTPUT=" '/KERNEL_BUILD_OUTPUT=/{print $$2}' $(BUILD_ENV)) 9 | kernel_dir = $(shell awk -F "KERNEL_DIR=" '/KERNEL_DIR=/{print $$2}' $(BUILD_ENV)) 10 | 11 | # Add your debugging flag (or not) to CFLAGS 12 | ifeq ($(DEBUG),y) 13 | DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines 14 | else 15 | DEBFLAGS = -O2 16 | endif 17 | 18 | obj-m := workq_test.o 19 | obj-m += workq_test2.o 20 | obj-m += workq_test3.o 21 | KERNEL_DIR ?= /lib/modules/$(shell uname -r)/build 22 | KERNEL_BUID_OUTPUT ?=$(KERNEL_DIR) 23 | CC = $(CROSS_COMPILE)gcc 24 | LD = $(CROSS_COMPILE)ld 25 | PWD := $(shell pwd) 26 | 27 | modules: 28 | $(MAKE) CROSS_COMPILE=$(cross_compiler_prefix) -C $(kernel_dir) O=$(kernel_output) M=$(PWD) modules 29 | 30 | clean: 31 | rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions modules.order Module.symvers 32 | 33 | depend .depend dep: 34 | $(CC) $(CFLAGS) -M *.c > .depend 35 | 36 | ifeq (.depend,$(wildcard .depend)) 37 | include .depend 38 | endif 39 | -------------------------------------------------------------------------------- /rk3288/debug/workqueue/README.md: -------------------------------------------------------------------------------- 1 | # WORKQUEUE 2 | -------------------------------------------------------------------------------- /rk3288/debug/workqueue/workq_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | struct self_define_struct *g_sds; /* just for free sds memory */ 7 | struct self_define_struct { 8 | struct work_struct mywork; 9 | }; 10 | 11 | static void mywork_handler(struct work_struct *work) 12 | { 13 | printk("%s, %d\n", __FUNCTION__, __LINE__); 14 | } 15 | 16 | static int workq_test_init(void) 17 | { 18 | struct self_define_struct *sds; 19 | 20 | sds = kzalloc(sizeof(struct self_define_struct), GFP_KERNEL); 21 | if (sds == NULL) 22 | return -ENOMEM; 23 | 24 | /* for free the memory */ 25 | g_sds = sds; 26 | 27 | printk("%s, %d\n", __FUNCTION__, __LINE__); 28 | 29 | /* init mywork */ 30 | INIT_WORK(&sds->mywork, mywork_handler); 31 | 32 | /* do my work */ 33 | schedule_work(&sds->mywork); 34 | 35 | /* make it happend imediatly, the result is unexpected ? */ 36 | flush_scheduled_work(); 37 | 38 | return 0; 39 | } 40 | 41 | static void workq_test_exit(void) 42 | { 43 | printk("%s, %d\n", __FUNCTION__, __LINE__); 44 | kfree(g_sds); 45 | } 46 | 47 | module_init(workq_test_init) 48 | module_exit(workq_test_exit) 49 | MODULE_LICENSE("GPL"); 50 | -------------------------------------------------------------------------------- /rk3288/debug/workqueue/workq_test2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | struct self_define_struct *g_sds; /* just for free sds memory */ 7 | struct self_define_struct { 8 | struct work_struct mywork; 9 | struct workqueue_struct *my_workqueue; 10 | }; 11 | 12 | static void mywork_handler(struct work_struct *work) 13 | { 14 | printk("%s, %d\n", __FUNCTION__, __LINE__); 15 | } 16 | 17 | static int workq_test_init(void) 18 | { 19 | struct self_define_struct *sds; 20 | 21 | sds = kzalloc(sizeof(struct self_define_struct), GFP_KERNEL); 22 | if (sds == NULL) 23 | return -ENOMEM; 24 | 25 | /* for free the memory */ 26 | g_sds = sds; 27 | 28 | printk("%s, %d\n", __FUNCTION__, __LINE__); 29 | 30 | /* init mywork */ 31 | INIT_WORK(&sds->mywork, mywork_handler); 32 | 33 | sds->my_workqueue = create_singlethread_workqueue("myworkq_name"); 34 | if (!sds->my_workqueue) { 35 | printk("create single thread workqueue error\n"); 36 | } 37 | 38 | /* do my work */ 39 | if (!work_pending(&sds->mywork)) 40 | queue_work(sds->my_workqueue, &sds->mywork); 41 | 42 | return 0; 43 | } 44 | 45 | static void workq_test_exit(void) 46 | { 47 | printk("%s, %d\n", __FUNCTION__, __LINE__); 48 | destroy_workqueue(g_sds->my_workqueue); 49 | kfree(g_sds); 50 | } 51 | 52 | module_init(workq_test_init) 53 | module_exit(workq_test_exit) 54 | MODULE_LICENSE("GPL"); 55 | -------------------------------------------------------------------------------- /rk3288/debug/workqueue/workq_test3.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | struct self_define_struct *g_sds; /* just for free sds memory */ 7 | struct self_define_struct { 8 | struct delayed_work mywork; 9 | }; 10 | static int g_cnt = 0; 11 | 12 | static void mywork_handler(struct delayed_work *dwork) 13 | { 14 | struct self_define_struct *sds = container_of(dwork, struct self_define_struct, mywork); 15 | 16 | printk("%s, %d[%d]\n", __FUNCTION__, __LINE__, g_cnt++); 17 | 18 | /* do work again */ 19 | schedule_delayed_work(&sds->mywork, msecs_to_jiffies(500 + g_cnt * 100)); 20 | } 21 | 22 | static int workq_test_init(void) 23 | { 24 | struct self_define_struct *sds; 25 | 26 | sds = kzalloc(sizeof(struct self_define_struct), GFP_KERNEL); 27 | if (sds == NULL) 28 | return -ENOMEM; 29 | 30 | /* for free the memory */ 31 | g_sds = sds; 32 | 33 | printk("%s, %d\n", __FUNCTION__, __LINE__); 34 | 35 | /* init mywork */ 36 | INIT_DELAYED_WORK(&sds->mywork, mywork_handler); 37 | 38 | /* do my work */ 39 | schedule_delayed_work(&sds->mywork, msecs_to_jiffies(500)); 40 | 41 | return 0; 42 | } 43 | 44 | static void workq_test_exit(void) 45 | { 46 | printk("%s, %d\n", __FUNCTION__, __LINE__); 47 | cancel_delayed_work_sync(&g_sds->mywork); 48 | kfree(g_sds); 49 | } 50 | 51 | module_init(workq_test_init) 52 | module_exit(workq_test_exit) 53 | MODULE_LICENSE("GPL"); 54 | -------------------------------------------------------------------------------- /rk3288/script/README.md: -------------------------------------------------------------------------------- 1 | # shell测试脚本(android ksh) 2 | 3 | ## 查看目录下每个文件的内容 4 | 5 | 有下面这样一个目录 6 | 7 | ```shell 8 | root@rk3288:/sys/devices/ff650000.i2c/i2c-0/0-005a/regulator # ls 9 | regulator.1 10 | regulator.10 11 | regulator.11 12 | regulator.12 13 | regulator.2 14 | regulator.3 15 | regulator.4 16 | regulator.5 17 | regulator.6 18 | regulator.7 19 | regulator.8 20 | regulator.9 21 | ``` 22 | 23 | 每个目录下有下面这些文件 24 | 25 | ```shell 26 | root@rk3288:/sys/devices/ff650000.i2c/i2c-0/0-005a/regulator # ls regulator.1 27 | device 28 | max_microvolts 29 | microvolts 30 | min_microvolts 31 | name 32 | num_users 33 | opmode 34 | power 35 | state 36 | subsystem 37 | suspend_disk_microvolts 38 | suspend_disk_state 39 | suspend_mem_microvolts 40 | suspend_mem_state 41 | suspend_standby_microvolts 42 | suspend_standby_state 43 | type 44 | uevent 45 | ``` 46 | 47 | 查看每个文件的内容(直接复制到shell中) 48 | 49 | ``` 50 | i=1 51 | while (( $i < 13 )) 52 | do 53 | for f in `ls regulator.$i/` 54 | do 55 | if [ -f regulator.$i/$f ] 56 | then 57 | echo "regulator.$i/$f =" `cat regulator.$i/$f` 58 | fi 59 | done 60 | (( i+= 1 )) 61 | done 62 | ``` 63 | 64 | ## 查看某个目录下所有的文件的内容 65 | 66 | ```shell 67 | for f in `ls` 68 | do 69 | if [ -f $f ] 70 | then 71 | echo "$f =" `cat $f` 72 | fi 73 | done 74 | ``` 75 | 76 | ## 打印所有regulator.[1-12]下num_users里的信息 77 | 78 | ```shell 79 | i=1 80 | cat_info="num_users" 81 | while (( $i < 13 )) 82 | do 83 | echo "regulator.$i/$cat_info =" `cat regulator.$i/$cat_info` 84 | (( i+=1 )) 85 | done 86 | ``` 87 | -------------------------------------------------------------------------------- /rk3399/1p8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3399/1p8.png -------------------------------------------------------------------------------- /rk3399/3p0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3399/3p0.png -------------------------------------------------------------------------------- /rk3399/apio4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3399/apio4.png -------------------------------------------------------------------------------- /rk3399/apio4_vdd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3399/apio4_vdd.png -------------------------------------------------------------------------------- /rk3399/apio5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3399/apio5.png -------------------------------------------------------------------------------- /rk3399/apps/README.md: -------------------------------------------------------------------------------- 1 | # Application test example 2 | 3 | ## lcd_test 4 | 5 | 简单的LCD测试程序,在LCD屏幕上显示彩色条纹 6 | -------------------------------------------------------------------------------- /rk3399/apps/lcd_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #ifdef ANDROID_SYSTEM 10 | #define DEFAULT_FB_DEVICE "/dev/graphics/fb0" 11 | #else 12 | #define DEFAULT_FB_DEVICE "/dev/fb0" 13 | #endif 14 | 15 | /* 16 | * Usage: 17 | * Android: 18 | * # stop 19 | * ./lcd_test 20 | * # start 21 | * Linux: 22 | * ./lcd_test 23 | */ 24 | int main(int argc, char *argv[]) 25 | { 26 | int fd = 0; 27 | struct fb_var_screeninfo vinfo; 28 | struct fb_fix_screeninfo finfo; 29 | long int screensize = 0; 30 | char *fbp = 0; 31 | int x = 0, y = 0; 32 | long int location = 0; 33 | 34 | /* Open the file for reading and writing */ 35 | fd = open(DEFAULT_FB_DEVICE, O_RDWR); 36 | if (fd == -1) { 37 | perror("Error: cannot open framebuffer device"); 38 | exit(1); 39 | } 40 | printf("The framebuffer device was opened successfully.\n"); 41 | 42 | /* Get fixed screen information */ 43 | if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1) { 44 | perror("Error reading fixed information"); 45 | exit(2); 46 | } 47 | 48 | /* Get variable screen information */ 49 | if (ioctl(fd, FBIOGET_VSCREENINFO, &vinfo) == -1) { 50 | perror("Error reading variable information"); 51 | exit(3); 52 | } 53 | 54 | printf("%dx%d, %dbpp\n", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel); 55 | 56 | /* Figure out the size of the screen in bytes */ 57 | screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8; 58 | 59 | /* Map the device to memory */ 60 | fbp = (char *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 61 | if (fbp < 0) { 62 | perror("Error: failed to map framebuffer device to memory"); 63 | exit(4); 64 | } 65 | printf("The framebuffer device was mapped to memory successfully.\n"); 66 | 67 | /* Figure out where in memory to put the pixel */ 68 | for (y = 0; y < vinfo.yres; y++) 69 | { 70 | for (x = 0; x < vinfo.xres; x++) 71 | { 72 | location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + 73 | (y+vinfo.yoffset) * finfo.line_length; 74 | 75 | if (vinfo.bits_per_pixel == 32) 76 | { 77 | *(fbp + location) = 100;// Some blue 78 | *(fbp + location + 1) = 15+(x-100)/2; // A little green 79 | *(fbp + location + 2) = 200-(y-100)/5;// A lot of red 80 | *(fbp + location + 3) = 0;// No transparency 81 | } 82 | else //assume 16bpp 83 | { 84 | int b = 10; 85 | int g = (x-100)/6; // A little green 86 | int r = 31-(y-100)/16;// A lot of red 87 | unsigned short int t = r<<11 | g << 5 | b; 88 | *((unsigned short int*)(fbp + location)) = t; 89 | } 90 | } 91 | } 92 | 93 | munmap(fbp, screensize); 94 | close(fd); 95 | return 0; 96 | } 97 | -------------------------------------------------------------------------------- /rk3399/bsp/default_storage_map.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3399/bsp/default_storage_map.png -------------------------------------------------------------------------------- /rk3399/cmdline_android: -------------------------------------------------------------------------------- 1 | FIRMWARE_VER: 6.0.1 2 | MACHINE_MODEL: RK3399 3 | MACHINE_ID: 007 4 | MANUFACTURER: RK3399 5 | MAGIC: 0x5041524B 6 | ATAG: 0x00200800 7 | MACHINE: 3399 8 | CHECK_MASK: 0x80 9 | PWR_HLD: 0,0,A,0,1 10 | #KERNEL_IMG: 0x00280000 11 | #FDT_NAME: rk-kernel.dtb 12 | #RECOVER_KEY: 1,1,0,20,0 13 | #in section; per section 512(0x200) bytes 14 | CMDLINE: androidboot.baseband=N/A androidboot.selinux=disabled androidboot.hardware=rk30board androidboot.console=ttyFIQ0 init=/linuxrc mtdparts=rk29xxnand:0x00002000@0x00002000(uboot),0x00002000@0x00004000(trust),0x00002000@0x00006000(misc),0x00008000@0x00008000(resource),0x0000A000@0x00010000(kernel),0x00010000@0x0001A000(boot),0x00010000@0x0002A000(recovery),0x00038000@0x0003A000(backup),0x00040000@0x00072000(cache),0x00200000@0x000B2000(system),0x00008000@0x002B2000(metadata),0x00002000@0x002BA000(baseparamer),-@0x002BC000(userdata) 15 | 16 | -------------------------------------------------------------------------------- /rk3399/debug/adc/keys.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3399/debug/adc/keys.png -------------------------------------------------------------------------------- /rk3399/debug/camera/camera_engine.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3399/debug/camera/camera_engine.png -------------------------------------------------------------------------------- /rk3399/debug/camera/cap-isp-yuv.sh: -------------------------------------------------------------------------------- 1 | media-ctl -d /dev/media0 --set-v4l2 '"ov13850 1-0036":0[fmt:SBGGR10_1X10/2112x1568]' 2 | media-ctl -d /dev/media0 --set-v4l2 '"rkisp1-isp-subdev":0[fmt:SBGGR10_1X10/2112x1568]' 3 | media-ctl -d /dev/media0 --set-v4l2 '"rkisp1-isp-subdev":0[crop:(0,0)/2112x1568]' 4 | media-ctl -d /dev/media0 --set-v4l2 '"rkisp1-isp-subdev":2[fmt:YUYV8_2X8/2112x1568]' 5 | media-ctl -d /dev/media0 --set-v4l2 '"rkisp1-isp-subdev":2[crop:(0,0)/2112x1568]' 6 | v4l2-ctl -d /dev/video0 \ 7 | --set-selection=target=crop,top=336,left=432,width=1920,height=1080 \ 8 | --set-fmt-video=width=1280,height=720,pixelformat=NV21 \ 9 | --stream-mmap=3 --stream-to=/tmp/mp.out --stream-count=20 --stream-poll 10 | -------------------------------------------------------------------------------- /rk3399/debug/camera/cap-sensor-raw-bayer.sh: -------------------------------------------------------------------------------- 1 | media-ctl -d /dev/media0 --set-v4l2 '"ov13850 1-0036":0[fmt:SBGGR10_1X10/2112x1568]' 2 | media-ctl -d /dev/media0 --set-v4l2 '"rkisp1-isp-subdev":0[fmt:SBGGR10_1X10/2112x1568]' 3 | media-ctl -d /dev/media0 --set-v4l2 '"rkisp1-isp-subdev":0[crop:(0,0)/2112x1568]' 4 | media-ctl -d /dev/media0 --set-v4l2 '"rkisp1-isp-subdev":2[fmt:SBGGR10_1X10/2112x1568]' 5 | media-ctl -d /dev/media0 --set-v4l2 '"rkisp1-isp-subdev":2[crop:(0,0)/2112x1568]' 6 | v4l2-ctl -d /dev/video0 --set-ctrl 'exposure=1216,analogue_gain=10' \ 7 | --set-selection=target=crop,top=0,left=0,width=2592,height=1944 \ 8 | --set-fmt-video=width=2112,height=1568,pixelformat=SBGGR10 \ 9 | --stream-mmap=3 --stream-to=/tmp/mp.raw.out --stream-count=1 --stream-poll 10 | -------------------------------------------------------------------------------- /rk3399/debug/camera/rkisp1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3399/debug/camera/rkisp1.png -------------------------------------------------------------------------------- /rk3399/debug/camera/system_connection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3399/debug/camera/system_connection.png -------------------------------------------------------------------------------- /rk3399/debug/camera/test_camera-uvc.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | export DISPLAY=:0.0 4 | #export GST_DEBUG=*:5 5 | #export GST_DEBUG_FILE=/tmp/2.txt 6 | 7 | echo "Start UVC Camera M-JPEG Preview!" 8 | 9 | su linaro -c " \ 10 | gst-launch-1.0 v4l2src device=/dev/video0 ! mppvideodec ! rkximagesink sync=false \ 11 | " 12 | 13 | # Fpr spefic size : 14 | 15 | # v4l2-ctl --list-formats-ext 16 | # gst-launch-1.0 v4l2src device=/dev/video0 ! "image/jpeg,width=640,height=480,framerate=30/1" ! \ 17 | # mppvideodec ! rkximagesink sync=false 18 | -------------------------------------------------------------------------------- /rk3399/debug/char/.gitignore: -------------------------------------------------------------------------------- 1 | *.cmd 2 | *.o 3 | *.mod.c 4 | *.ko 5 | *.order 6 | Module.symvers 7 | .tmp_versions 8 | -------------------------------------------------------------------------------- /rk3399/debug/char/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile 2 | # Comment/uncomment the following line to disable/enable debugging 3 | # DEBUG = y 4 | 5 | # Usage 6 | # make CROSS_COMPILE= KERNEL_DIR= KERNEL_BUID_OUTPUT= 7 | # 8 | # make CROSS_COMPILE=/home/zeroway/rk3399/tool/gcc-linaro-4.9.4-2017.01-i686_aarch64-linux-gnu/bin/aarch64-linux-gnu- KERNEL_DIR=/home/zeroway/rk3399/src/firefly/kernel KERNEL_BUID_OUTPUT=/home/zeroway/rk3399/src/firefly/out/target/product/rk3399_firefly_box/obj/KERNEL 9 | 10 | # Add your debugging flag (or not) to CFLAGS 11 | ifeq ($(DEBUG),y) 12 | DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines 13 | else 14 | DEBFLAGS = -O2 15 | endif 16 | 17 | obj-m := char_skeleton_drv.o 18 | obj-m += spinlock.o 19 | KERNEL_DIR ?= /lib/modules/$(shell uname -r)/build 20 | KERNEL_BUID_OUTPUT ?=$(KERNEL_DIR) 21 | CC = $(CROSS_COMPILE)gcc 22 | LD = $(CROSS_COMPILE)ld 23 | PWD := $(shell pwd) 24 | 25 | modules: 26 | $(MAKE) -C $(KERNEL_DIR) ARCH=arm64 M=$(PWD) O=$(KERNEL_BUID_OUTPUT) modules 27 | 28 | clean: 29 | rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions modules.order Module.symvers 30 | 31 | depend .depend dep: 32 | $(CC) $(CFLAGS) -M *.c > .depend 33 | 34 | ifeq (.depend,$(wildcard .depend)) 35 | include .depend 36 | endif 37 | -------------------------------------------------------------------------------- /rk3399/debug/char/README.md: -------------------------------------------------------------------------------- 1 | # 字符设备驱动 2 | 3 | ## 使用spinlock保护临界区资源 4 | 5 | ### 测试方法 6 | 7 | 首先执行 8 | 9 | cat /dev/spinlock_test & 10 | 11 | 在10秒内执行下面命令看结果 12 | 13 | echo lock > /dev/spinlock_test 14 | 15 | 在10秒内执行下面命令看结果 16 | 17 | echo trylock > /dev/spinlock_test 18 | 19 | 测试注意 20 | 21 | - 用cat读取设备文件是,传入的字节数是32768,而这里的read函数只返回msg_len = 4个字符,因此用了flag来控制读,当返回了"read"后,会立刻返回0,否则cat会不断调用spinlock_read函数,就会出现不断输出"read"的现象 22 | 23 | - 用echo写入时会自动添加"\n",所以在判断的时候也要判断"\n" 24 | -------------------------------------------------------------------------------- /rk3399/debug/char/char_skeleton_drv.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #define CHAR_SKELETON_COUNT 1 13 | 14 | static int major; 15 | static struct cdev char_skeleton_cdev; 16 | static struct class *cls; 17 | 18 | struct self_define_data 19 | { 20 | int arg1; 21 | int arg2; 22 | }; 23 | 24 | static int char_skeleton_open(struct inode *inode, struct file *file) 25 | { 26 | printk("%s, %d\n", __FUNCTION__, __LINE__); 27 | return 0; 28 | } 29 | 30 | static ssize_t char_skeleton_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos) 31 | { 32 | struct self_define_data sdd; 33 | 34 | if (copy_from_user(&sdd, buf, count) != 0) 35 | return -1; 36 | 37 | printk("char_skeleton_write, arg1= %d, arg2 = %d\n", sdd.arg1, sdd.arg2); 38 | 39 | return count; 40 | } 41 | 42 | static struct file_operations char_skeleton_fops = { 43 | .owner = THIS_MODULE, 44 | .open = char_skeleton_open, 45 | .write = char_skeleton_write, 46 | }; 47 | 48 | static int char_skeleton_init(void) 49 | { 50 | dev_t dev_id; 51 | int retval; 52 | 53 | /* 54 | * 如果有主设备号,根据主设备号得到设备ID,并注册 55 | * 如果没有主设备号,让系统随机分配一个设备ID,根据设备ID获得主设备号 56 | */ 57 | if (major) 58 | { 59 | dev_id = MKDEV(major, 0); 60 | retval = register_chrdev_region(dev_id, CHAR_SKELETON_COUNT, "char_skeleton"); 61 | } 62 | else 63 | { 64 | retval = alloc_chrdev_region(&dev_id, 0, CHAR_SKELETON_COUNT, "char_skeleton"); 65 | major = MAJOR(dev_id); 66 | } 67 | 68 | if (retval) { 69 | printk("register or alloc region error\n"); 70 | return -1; 71 | } 72 | 73 | /* 字符设备的注册 */ 74 | /* 内核在内部使用类型 struct cdev 的结构来代表字符设备 */ 75 | /* 初始化char device */ 76 | cdev_init(&char_skeleton_cdev, &char_skeleton_fops); 77 | 78 | /* 关联char devices 和 dev_id */ 79 | cdev_add(&char_skeleton_cdev, dev_id, CHAR_SKELETON_COUNT); 80 | 81 | /* 创建相关的设备节点 */ 82 | cls = class_create(THIS_MODULE, "char_skeleton"); 83 | if (IS_ERR(cls)) 84 | return -EINVAL; 85 | 86 | device_create(cls, NULL, MKDEV(major, 0), NULL, "char_skeleton");/* /dev/char_skeleton */ 87 | 88 | return 0; 89 | } 90 | 91 | static void char_skeleton_exit(void) 92 | { 93 | dev_t dev_id = MKDEV(major, 0); 94 | 95 | device_destroy(cls, dev_id); 96 | class_destroy(cls); 97 | cdev_del(&char_skeleton_cdev); 98 | unregister_chrdev_region(dev_id, CHAR_SKELETON_COUNT); 99 | } 100 | 101 | module_init(char_skeleton_init); 102 | module_exit(char_skeleton_exit); 103 | MODULE_LICENSE("GPL"); 104 | -------------------------------------------------------------------------------- /rk3399/debug/char/char_skeleton_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define SKELETON_DEVICE_NAME "/dev/char_skeleton" 7 | 8 | struct self_define_data 9 | { 10 | int arg1; 11 | int arg2; 12 | }; 13 | 14 | void print_usage(const char *name) 15 | { 16 | printf("%s \n", name); 17 | } 18 | 19 | int main(int argc, char *argv[]) 20 | { 21 | int fd; 22 | struct self_define_data sdd; 23 | int wBytes; 24 | 25 | if (argc < 3) 26 | { 27 | print_usage(argv[0]); 28 | return 1; 29 | } 30 | 31 | fd = open(SKELETON_DEVICE_NAME, O_RDWR); 32 | if (fd < 0) 33 | { 34 | printf("Can't open %s\n", SKELETON_DEVICE_NAME); 35 | return -1; 36 | } 37 | sdd.arg1 = atoi(argv[1]); 38 | sdd.arg2 = atoi(argv[2]); 39 | printf("argv1 = %d, argv2 = %d\n", sdd.arg1, sdd.arg2); 40 | 41 | wBytes = write(fd, &sdd, sizeof(sdd)); 42 | printf("wBytes = %dbytes\n", wBytes); 43 | close(fd); 44 | 45 | return 0; 46 | } 47 | -------------------------------------------------------------------------------- /rk3399/debug/char/spinlock.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #define DEVICE_NAME "spinlock_test" 11 | 12 | static char *data = "read\n"; 13 | static char flag = 1; 14 | static DEFINE_SPINLOCK(lock); 15 | 16 | void do_some_working(int ms) 17 | { 18 | mdelay(ms); 19 | } 20 | 21 | /* 22 | * 用cat读取设备文件是,传入的字节数是32768 23 | * 而这里的read函数只返回msg_len = 4个字符 24 | * 因此用了flag来控制读,当返回了"read"后 25 | * 会立刻返回0,否则cat会不断调用spinlock_read函数 26 | * 就会出现不断输出"read"的现象 27 | */ 28 | static ssize_t spinlock_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) 29 | { 30 | int msg_len = strlen(data); 31 | 32 | if (copy_to_user(buf, (void *)data, msg_len)) 33 | return -EINVAL; 34 | 35 | if (flag) 36 | { 37 | flag = 0; 38 | if (spin_trylock(&lock)) 39 | { 40 | /* do 10s the working */ 41 | printk("reading...occupy the lock\n"); 42 | do_some_working(10000); 43 | spin_unlock(&lock); 44 | } 45 | else 46 | { 47 | return -EBUSY; 48 | } 49 | return msg_len; 50 | } 51 | else 52 | { 53 | flag = 1; 54 | return 0; 55 | } 56 | } 57 | 58 | /* 59 | * 测试: 60 | * echo lock > /dev/spinlock_test 61 | * echo trylock > /dev/spinlock_test 62 | * 用echo写入文件时会自动添加"\n" 63 | * 所以在判断的时候也要判断"\n" 64 | */ 65 | static ssize_t spinlock_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) 66 | { 67 | char data[10]; 68 | 69 | memset(data, 0 , 10); 70 | 71 | if (copy_from_user(data, buf, count)) 72 | return -EINVAL; 73 | 74 | /* if write data is "lock" */ 75 | if (strcmp("lock\n", data) == 0) 76 | { 77 | spin_lock(&lock); 78 | 79 | /* do 10s the working */ 80 | printk("writing...occupy the lock\n"); 81 | do_some_working(10000); 82 | 83 | spin_unlock(&lock); 84 | } 85 | else if (strcmp("trylock\n", data) == 0) 86 | { 87 | if (spin_trylock(&lock)) 88 | { 89 | /* do 10s the working */ 90 | do_some_working(10000); 91 | 92 | spin_unlock(&lock); 93 | } 94 | else 95 | { 96 | printk("spin lock unavaliable\n"); 97 | return -EBUSY; 98 | } 99 | } 100 | 101 | return count; 102 | } 103 | 104 | static struct file_operations spinlock_fops = { 105 | .owner = THIS_MODULE, 106 | .read = spinlock_read, 107 | .write = spinlock_write 108 | }; 109 | 110 | static struct miscdevice spinlock_misc = { 111 | .minor = MISC_DYNAMIC_MINOR, 112 | .name = DEVICE_NAME, 113 | .fops = &spinlock_fops 114 | }; 115 | 116 | static int spinlock_init(void) 117 | { 118 | int ret; 119 | 120 | ret = misc_register(&spinlock_misc); 121 | printk("%s, %d\n", __FUNCTION__, __LINE__); 122 | return ret; 123 | } 124 | 125 | static void spinlock_exit(void) 126 | { 127 | printk("%s, %d\n", __FUNCTION__, __LINE__); 128 | misc_deregister(&spinlock_misc); 129 | } 130 | 131 | module_init(spinlock_init); 132 | module_exit(spinlock_exit); 133 | MODULE_LICENSE("GPL"); 134 | -------------------------------------------------------------------------------- /rk3399/debug/fiq_debugger/README.md: -------------------------------------------------------------------------------- 1 | # FIQ-Debugger 2 | 3 | [参考文章:Linux/Android常用调试工具](http://blog.csdn.net/azloong/article/details/45768633) 4 | 5 | ## 代码实现 6 | 7 | 参考 kernel/drivers/staging/android/fiq_debugger/fiq_debugger.c 8 | 9 | ## 内核配置 10 | 11 | CONFIG_FIQ_DEBUGGER // 使能fiq debugger 12 | CONFIG_FIQ_DEBUGGER_CONSOLE // fiq debugger与console可以互相切换 13 | CONFIG_FIQ_DEBUGGER_CONSOLE_DEFAULT_ENABLE // 启动时默认串口在console模式 14 | 15 | ## 进入FIQ Debugger 16 | 17 | 使用minicom进入FIQ Debug mode 18 | (在RK3399上按完ctrl+a+f后还要按fiq才能进入debug模式,在函数fiq_debugger_handle_uart_interrupt中设置的) 19 | 20 | ctrl+a+z+f 或 ctrl+a+f 21 | 22 | 退出debug模式 23 | 24 | 输入console 25 | 26 | ## Process/Thread状态 27 | 28 | "R (running)", /* 0 */ 29 | "S (sleeping)", /* 1 */ 30 | "D (disk sleep)", /* 2 */ 31 | "T (stopped)", /* 4 */ 32 | "t (tracing stop)", /* 8 */ 33 | "Z (zombie)", /* 16 */ 34 | "X (dead)", /* 32 */ 35 | "x (dead)", /* 64 */ 36 | "K (wakekill)", /* 128 */ 37 | "W (waking)", /* 256 */ 38 | 39 | 通常一般的Process处于的状态都是S(sleeping),而如果一旦发现处于如D(disk sleep)、T(stopped)、Z(zombie)等就要认真审查 40 | -------------------------------------------------------------------------------- /rk3399/debug/gpio/README.md: -------------------------------------------------------------------------------- 1 | 假设现在想要查看GPIO1_A0的mux状态 2 | 3 | GPIO1对应的寄存器名为PMUGRF_GPIO1A_IOMUX(offset 0x10) 4 | 5 | ![GPIO1 MUX](./pmugrf_gpio1a_iomux.png) 6 | 7 | 查看手册知道PMUGRF的基地址如下截图(FF32_0000 - FF33_0000) 8 | 9 | ![PMUGRF BASE ADDR](./pmugrf.png) 10 | 11 | 查看该寄存器的值 12 | 13 | io -4 -r 0xff320010 14 | 15 | 查看该IO口是高电平还是低电平 16 | 17 | GPIO1对应的寄存器基地址为(FF73_0000 - FF74_0000) 18 | 19 | ![GPIO1 BASE ADDR](./gpio1.png) 20 | 21 | IO口的值保存在GPIO_SWPORTA_DR(offset 0x0)寄存器中 22 | 23 | 查看该寄存器的值(其中最低位对应GPIO1_A0) 24 | 25 | io -4 -r 0xff730000 26 | 27 | 将GPIO1_A0拉高 28 | 29 | io -4 -w 0xff730000 0x01822401 30 | 31 | 将GPIO1_A0拉低 32 | 33 | io -4 -w 0xff730000 0x01822400 34 | -------------------------------------------------------------------------------- /rk3399/debug/gpio/gpio1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3399/debug/gpio/gpio1.png -------------------------------------------------------------------------------- /rk3399/debug/gpio/pmugrf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3399/debug/gpio/pmugrf.png -------------------------------------------------------------------------------- /rk3399/debug/gpio/pmugrf_gpio1a_iomux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3399/debug/gpio/pmugrf_gpio1a_iomux.png -------------------------------------------------------------------------------- /rk3399/debug/i2c/.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.ko 3 | *.cmd 4 | Module.symvers 5 | modules.order 6 | .tmp_versions/ 7 | *.mod.c 8 | *.mod.c 9 | -------------------------------------------------------------------------------- /rk3399/debug/i2c/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile 2 | # Comment/uncomment the following line to disable/enable debugging 3 | # DEBUG = y 4 | 5 | # Usage 6 | # make CROSS_COMPILE= KERNEL_DIR= KERNEL_BUID_OUTPUT= 7 | # 8 | # make CROSS_COMPILE=/home/zeroway/rk3399/tool/gcc-linaro-4.9.4-2017.01-i686_aarch64-linux-gnu/bin/aarch64-linux-gnu- KERNEL_DIR=/home/zeroway/rk3399/src/firefly/kernel KERNEL_BUID_OUTPUT=/home/zeroway/rk3399/src/firefly/out/target/product/rk3399_firefly_box/obj/KERNEL 9 | 10 | # Add your debugging flag (or not) to CFLAGS 11 | ifeq ($(DEBUG),y) 12 | DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines 13 | else 14 | DEBFLAGS = -O2 15 | endif 16 | 17 | obj-m := i2c_regmap.o 18 | 19 | KERNEL_DIR ?= /lib/modules/$(shell uname -r)/build 20 | KERNEL_BUID_OUTPUT ?=$(KERNEL_DIR) 21 | CC = $(CROSS_COMPILE)gcc 22 | LD = $(CROSS_COMPILE)ld 23 | PWD := $(shell pwd) 24 | 25 | modules: 26 | $(MAKE) -C $(KERNEL_DIR) ARCH=arm64 M=$(PWD) O=$(KERNEL_BUID_OUTPUT) modules 27 | 28 | clean: 29 | rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions modules.order Module.symvers 30 | 31 | depend .depend dep: 32 | $(CC) $(CFLAGS) -M *.c > .depend 33 | 34 | ifeq (.depend,$(wildcard .depend)) 35 | include .depend 36 | endif 37 | -------------------------------------------------------------------------------- /rk3399/debug/i2c/README.md: -------------------------------------------------------------------------------- 1 | # I2C 2 | 3 | ## 读写时序 4 | 5 | ![timing](./i2c_timing.png) 6 | 7 | ## regmap i2c 8 | 9 | ### Intro 10 | 11 | Regmap主要目的是减少慢速I/O驱动上的重复逻辑,提供一种通用的接口来操作底层硬件上的寄存器.Regmap除了能做到统一的I/O接口,还可以在驱动和硬件IC之间做一层缓存,从而能减少底层I/O的操作次数 12 | 13 | Regmap拓扑结构 14 | 15 | ![regmap](../regmap/regmap.png) 16 | 17 | ### 应用实例 18 | 19 | 以rk808驱动为例子讲解i2c regmap方式读写 20 | 21 | 使用配置文件初始化i2c的regmap 22 | 23 | devm_regmap_init_i2c(client, pdata->rk8xx_regmap_config); 24 | 25 | 配置文件如下 26 | 27 | static const struct regmap_config rk808_regmap_config = { 28 | .reg_bits = 8, 29 | .val_bits = 8, 30 | .max_register = RK808_IO_POL_REG, 31 | .cache_type = REGCACHE_RBTREE, 32 | .volatile_reg = rk808_is_volatile_reg, 33 | }; 34 | 35 | 初始化完后就可以使用regmap的API来操作I2C读写 36 | 37 | regmap_read(chip->regmap, RK818_LDO_EN_REG, &ldo_en); 38 | regmap_write(chip->regmap, RK818_LDO_EN_REG, 0xf7); 39 | -------------------------------------------------------------------------------- /rk3399/debug/i2c/i2c_timing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3399/debug/i2c/i2c_timing.png -------------------------------------------------------------------------------- /rk3399/debug/misc/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile 2 | # Comment/uncomment the following line to disable/enable debugging 3 | # DEBUG = y 4 | 5 | # Usage 6 | # make CROSS_COMPILE= KERNEL_DIR= KERNEL_BUID_OUTPUT= 7 | # 8 | # make CROSS_COMPILE=/home/zeroway/rk3399/tool/gcc-linaro-4.9.4-2017.01-i686_aarch64-linux-gnu/bin/aarch64-linux-gnu- KERNEL_DIR=/home/zeroway/rk3399/src/firefly/kernel KERNEL_BUID_OUTPUT=/home/zeroway/rk3399/src/firefly/out/target/product/rk3399_firefly_box/obj/KERNEL 9 | 10 | # Add your debugging flag (or not) to CFLAGS 11 | ifeq ($(DEBUG),y) 12 | DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines 13 | else 14 | DEBFLAGS = -O2 15 | endif 16 | 17 | obj-m := vfs_rw.o 18 | 19 | KERNEL_DIR ?= /lib/modules/$(shell uname -r)/build 20 | KERNEL_BUID_OUTPUT ?=$(KERNEL_DIR) 21 | CC = $(CROSS_COMPILE)gcc 22 | LD = $(CROSS_COMPILE)ld 23 | PWD := $(shell pwd) 24 | ARCH := x86_64 25 | 26 | modules: 27 | $(MAKE) -C $(KERNEL_DIR) ARCH=arm64 M=$(PWD) O=$(KERNEL_BUID_OUTPUT) modules 28 | 29 | clean: 30 | rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions modules.order Module.symvers 31 | 32 | depend .depend dep: 33 | $(CC) $(CFLAGS) -M *.c > .depend 34 | 35 | ifeq (.depend,$(wildcard .depend)) 36 | include .depend 37 | endif 38 | -------------------------------------------------------------------------------- /rk3399/debug/misc/README.md: -------------------------------------------------------------------------------- 1 | # DVFS Usser Guide 2 | 3 | [参考文章DVFS User Guide](http://processors.wiki.ti.com/index.php/DVFS_User_Guide) 4 | 5 | ## What is DVFS 6 | 7 | ``` 8 | Dynamic Voltage and Frequency scaling is a framework to change the frequency 9 | and/or operating voltage of a processor(s) based on system performance 10 | requirements at the given point of time 11 | ``` 12 | 13 | ## CPUFreq consists two elements 14 | 15 | - The Governor - that makes decisions 16 | - The Driver - acts based on the decisions made by the governor 17 | 18 | ## Usage 19 | 20 | To list all available governors 21 | 22 | cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors 23 | 24 | To see current active governor 25 | 26 | cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor 27 | 28 | To switch to a different governor(e.g. to switch to 'userspace' governor) 29 | 30 | echo -n "userspace" > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor 31 | 32 | Show current frequency of a cpu 33 | 34 | cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_cur_freq 35 | 36 | Show All available frequencies 37 | 38 | cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies 39 | 40 | when the frequency is changed, system voltage is also changed to meet the new 41 | requirements as part of scaling: This is done in two ways 42 | 43 | - when new frequency is higher (moving to high power state/opp) Voltage is increased first then the frequency, 44 | - when new frequency is lower (moving to low power state/opp) Frequency is reduced first then the voltage. 45 | -------------------------------------------------------------------------------- /rk3399/debug/misc/vfs_rw.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | /* read write buffer */ 7 | static char wbuf[] = "this is a kernel read write test"; 8 | static char rbuf[1024]; 9 | 10 | #define FILE_NAME "/tmp/vfs_rw_test" 11 | 12 | /* 13 | * 在内核中一般不容易生成用户空间的指针 14 | * 或者不方便独立使用用户空间内存 15 | * 而vfs_read,vfs_write的参数buffer都是用户空间指针 16 | * 所以需要调用set_fs目的是为了让内核改变对内存地址检查的处理方式 17 | * set_fs参数只有两个USER_DS和KERNEL_DS 18 | * USER_DS代表用户空间,set_fs 19 | * KERNEL_DS代表内核空间 20 | */ 21 | static int vfs_rw_init(void) 22 | { 23 | struct file *fp; 24 | mm_segment_t fs; 25 | loff_t pos; 26 | 27 | printk("%s, %d\n", __FUNCTION__, __LINE__); 28 | 29 | /* open file */ 30 | fp = filp_open(FILE_NAME, O_RDWR | O_CREAT, 0644); 31 | if (IS_ERR(fp)) 32 | { 33 | printk("create file error\n"); 34 | return -1; 35 | } 36 | 37 | /* write file */ 38 | 39 | /* get current fs*/ 40 | fs = get_fs(); 41 | 42 | /* 即对内核空间地址检查并做变换 */ 43 | set_fs(KERNEL_DS); 44 | pos = 0; 45 | printk("=> %s\n", wbuf); 46 | vfs_write(fp, wbuf, sizeof(wbuf), &pos); 47 | 48 | /* read file */ 49 | pos = 0; 50 | vfs_read(fp, rbuf, sizeof(wbuf), &pos); 51 | printk("<= %s\n", rbuf); 52 | 53 | /* close file */ 54 | filp_close(fp, NULL); 55 | set_fs(fs); 56 | 57 | return 0; 58 | } 59 | 60 | static void vfs_rw_exit(void) 61 | { 62 | printk("%s, %d\n", __FUNCTION__, __LINE__); 63 | } 64 | 65 | module_init(vfs_rw_init); 66 | module_exit(vfs_rw_exit); 67 | MODULE_LICENSE("GPL"); 68 | -------------------------------------------------------------------------------- /rk3399/debug/mmc/README.md: -------------------------------------------------------------------------------- 1 | # SD/MMC 2 | 3 | |内核中eMMC编号|内核中SD编号|uboot中eMMC编号|uboot中SD编号| 4 | |--|--|--|-- 5 | |1(mmcblk1, mmc1)|0(mmcblk0, mmc0)|0|1 6 | -------------------------------------------------------------------------------- /rk3399/debug/platform_driver_test/.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.ko 3 | *.cmd 4 | Module.symvers 5 | modules.order 6 | .tmp_versions/ 7 | *.mod* 8 | -------------------------------------------------------------------------------- /rk3399/debug/platform_driver_test/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile 2 | # Comment/uncomment the following line to disable/enable debugging 3 | # DEBUG = y 4 | 5 | # Usage 6 | # make CROSS_COMPILE= KERNEL_DIR= KERNEL_BUID_OUTPUT= 7 | # 8 | # make CROSS_COMPILE=/home/zeroway/rk3399/tool/gcc-linaro-4.9.4-2017.01-i686_aarch64-linux-gnu/bin/aarch64-linux-gnu- KERNEL_DIR=/home/zeroway/rk3399/src/firefly/kernel KERNEL_BUID_OUTPUT=/home/zeroway/rk3399/src/firefly/out/target/product/rk3399_firefly_box/obj/KERNEL 9 | 10 | # Add your debugging flag (or not) to CFLAGS 11 | ifeq ($(DEBUG),y) 12 | DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines 13 | else 14 | DEBFLAGS = -O2 15 | endif 16 | 17 | obj-m := skeleton_ss.o 18 | obj-m += kset_skeleton.o 19 | obj-m += seq_test.o 20 | obj-m += seq_test2.o 21 | obj-m += seq_test3.o 22 | obj-m += pid2task.o 23 | 24 | KERNEL_DIR ?= /lib/modules/$(shell uname -r)/build 25 | KERNEL_BUID_OUTPUT ?=$(KERNEL_DIR) 26 | CC = $(CROSS_COMPILE)gcc 27 | LD = $(CROSS_COMPILE)ld 28 | PWD := $(shell pwd) 29 | 30 | modules: 31 | $(MAKE) -C $(KERNEL_DIR) ARCH=arm64 M=$(PWD) O=$(KERNEL_BUID_OUTPUT) modules 32 | 33 | clean: 34 | rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions modules.order Module.symvers 35 | 36 | depend .depend dep: 37 | $(CC) $(CFLAGS) -M *.c > .depend 38 | 39 | ifeq (.depend,$(wildcard .depend)) 40 | include .depend 41 | endif 42 | -------------------------------------------------------------------------------- /rk3399/debug/platform_driver_test/README.md: -------------------------------------------------------------------------------- 1 | # Usage 2 | 3 | 把dtsi文件包含到所使用的dts里 4 | 5 | #include "skeleton_ss.dtsi" 6 | 7 | ## debug 8 | 9 | 拉高pin_a_name(GPIO1_B2) 10 | 11 | echo 0 1 > /sys/devices/platform/skeleton_gpios/egpios_debug 12 | 13 | 拉低pin_a_name(GPIO1_B2) 14 | 15 | echo 0 0 > /sys/devices/platform/skeleton_gpios/egpios_debug 16 | 17 | 查看相应管脚状态 18 | 19 | cat /sys/devices/platform/skeleton_gpios/egpios_debug 20 | cat /sys/kernel/debug/gpio | grep pin_ 21 | -------------------------------------------------------------------------------- /rk3399/debug/platform_driver_test/skeleton_ss.dtsi: -------------------------------------------------------------------------------- 1 | / { 2 | skeleton_gpios { 3 | compatible = "skeleton, compatible"; 4 | 5 | pin_a_name = <&gpio1 B2 GPIO_ACTIVE_HIGH>; 6 | pin_b_name = <&gpio1 A7 GPIO_ACTIVE_HIGH>; 7 | pin_c_name = <&gpio1 B4 GPIO_ACTIVE_HIGH>; 8 | pin_d_name = <&gpio1 B1 GPIO_ACTIVE_HIGH>; 9 | pin_e_name = <&gpio1 B0 GPIO_ACTIVE_HIGH>; 10 | pin_f_name = <&gpio4 D5 GPIO_ACTIVE_HIGH>; 11 | }; 12 | }; 13 | -------------------------------------------------------------------------------- /rk3399/debug/platform_driver_test/skeleton_ss.h: -------------------------------------------------------------------------------- 1 | #ifndef _SKELETON_H_ 2 | #define _SKELETON_H_ 3 | 4 | /* 5 | * Describe a pin 6 | * gpio_pin : gpio pin number 7 | * name : gpio name 8 | */ 9 | struct pin_desc { 10 | int gpio_pin; 11 | int gpio_active_flag; 12 | char name[20]; 13 | }; 14 | 15 | /* skeleton gpios, pdata or chip */ 16 | struct skeleton_chip { 17 | char name[20]; 18 | int pin_name_index; 19 | int value; 20 | 21 | /* a struct point array which contain of gpio_nr struct point */ 22 | struct pin_desc **pd; 23 | 24 | /* kobject */ 25 | struct kobject kobj; 26 | }; 27 | 28 | /* equal to dts pin name which is low case in pcb file */ 29 | const char *dts_name[] = { 30 | "pin_a_name", 31 | "pin_b_name", 32 | "pin_c_name", 33 | "pin_d_name", 34 | "pin_e_name", 35 | "pin_f_name", 36 | }; 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /rk3399/debug/regmap/.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.ko 3 | *.cmd 4 | Module.symvers 5 | modules.order 6 | .tmp_versions/ 7 | *.mod.c 8 | *.mod.c 9 | -------------------------------------------------------------------------------- /rk3399/debug/regmap/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile 2 | # Comment/uncomment the following line to disable/enable debugging 3 | # DEBUG = y 4 | 5 | # Usage 6 | # make CC= KERNELDIR= 7 | # 8 | # make CC=/home/zeroway/3288/src/3288_4.4/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/arm-eabi-gcc KERNELDIR=/home/zeroway/3288/src/3288_4.4/kernel 9 | 10 | # Add your debugging flag (or not) to CFLAGS 11 | ifeq ($(DEBUG),y) 12 | DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines 13 | else 14 | DEBFLAGS = -O2 15 | endif 16 | 17 | obj-m := i2c_regmap.o 18 | KERNELDIR ?= /lib/modules/$(shell uname -r)/build 19 | CC ?= gcc 20 | PWD := $(shell pwd) 21 | 22 | modules: 23 | $(MAKE) -C $(KERNELDIR) M=$(PWD) modules 24 | 25 | clean: 26 | rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions modules.order Module.symvers 27 | 28 | depend .depend dep: 29 | $(CC) $(CFLAGS) -M *.c > .depend 30 | 31 | ifeq (.depend,$(wildcard .depend)) 32 | include .depend 33 | endif 34 | -------------------------------------------------------------------------------- /rk3399/debug/regmap/README.md: -------------------------------------------------------------------------------- 1 | # Regmap 2 | 3 | [参考链接http://www.tinylab.org/kernel-explore-regmap-framework/](http://www.tinylab.org/kernel-explore-regmap-framework/) 4 | 5 | Regmap主要目的是减少慢速I/O驱动上的重复逻辑,提供一种通用的接口来操作底层硬件上的寄存器.Regmap除了能做到统一的I/O接口,还可以在驱动和硬件IC之间做一层缓存,从而能减少底层I/O的操作次数 6 | 7 | ![regmap](./regmap.png) 8 | 9 | [I2C Regmap example0](../i2c/i2c_regmap.c) 10 | 11 | [I2C Regmap example1](./i2c_regmap.c) 12 | -------------------------------------------------------------------------------- /rk3399/debug/regmap/regmap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3399/debug/regmap/regmap.png -------------------------------------------------------------------------------- /rk3399/debug/spi/README.md: -------------------------------------------------------------------------------- 1 | # SPI 2 | 3 | 4 | ## 软件基础 5 | 6 | 在设备树中每一个spi节点对应一个SPI控制器(一般情况下软件将bus和控制器配置成如下对应关系) 7 | 8 | spi0 <==> bus 0 9 | spi1 <==> bus 1 10 | spi2 <==> bus 2 11 | 12 | 其中每个SPI控制器上片选数有一个或多个,具体看芯片 13 | 14 | SPI0_CSN0 15 | SPI0_CSN1 16 | 17 | SPI1_CSN0 18 | 19 | SPI2_CSN0 20 | SPI2_CSN1 21 | 22 | ## SPI工作方式 23 | 24 | SPI以主从方式工作,这种模式通常有一个主设备和一个或多个从设备,需要至少4根线 25 | 26 | CS 片选信号 27 | SCLK 时钟信号 28 | MOSI 主设备数据输出,从设备数据输入 29 | MISO 主设备数据输入,从设备数据输出 30 | 31 | Linux内核用CPOL和CPHA的组合来表示当前SPI的四种工作模式 32 | 33 | CPOL=0,CPHA=0 SPI_MODE_0 34 | CPOL=0,CPHA=1 SPI_MODE_1 35 | CPOL=1,CPHA=0 SPI_MODE_2 36 | CPOL=1,CPHA=1 SPI_MODE_3 37 | 38 | CPOL:表示时钟信号的初始电平的状态,0为低电平,1为高电平 39 | 40 | CPHA:表示在哪个时钟沿采样,0为第一个时钟沿采样,1为第二个时钟沿采样 41 | 42 | SPI的四种工作模式波形图如下 43 | 44 | ![spi mode](./spi4mode.png) 45 | 46 | ## 硬件连接(以W25Q128FV为例子介绍) 47 | 48 | |w25q128fv|Firefly-RK3399| 49 | |----|----- 50 | |CS |SPI1_CSN0 51 | |VCC | VCC3V3_SYS 52 | |DO |SPI1_RXD 53 | |DI |SPI1_TXD 54 | |GND | GND 55 | |HOLD |TP_RST(需要拉高到3V) 56 | |CLK |SPI1_CLK 57 | 58 | ## DeviceTree 59 | 60 | &spi1 { 61 | status = "okay"; 62 | max-freq = <48000000>; 63 | dev-port = <1>; 64 | 65 | w25q128fv@10{ 66 | status = "okay"; 67 | compatible = "firefly,w25q128fv"; 68 | reg = <0x0>; 69 | spi-max-frequency = <48000000>; 70 | }; 71 | }; 72 | 73 | dev-port 74 | 75 | 表示bus_num,因为这里用的是spi1,所以配置为1 76 | 77 | @10的含义 78 | 79 | 1表示bus_num,需要和dev-port一致, 0表示spi设备使用CSN0作为片选 80 | 81 | reg = <0x0> 82 | 83 | 表示spi设备使用的片选,需要和上面一致,即CSN0 84 | -------------------------------------------------------------------------------- /rk3399/debug/spi/spi4mode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3399/debug/spi/spi4mode.png -------------------------------------------------------------------------------- /rk3399/debug/spi/w25q128fv.dtsi: -------------------------------------------------------------------------------- 1 | &spi1 { 2 | status = "okay"; 3 | max-freq = <48000000>; 4 | dev-port = <1>; 5 | 6 | w25q128fv@10{ 7 | status = "okay"; 8 | #address-cells = <1>; 9 | #size-cells = <1>; 10 | compatible = "firefly,w25q128fv"; 11 | reg = <0x0>; 12 | spi-max-frequency = <48000000>; 13 | m25p,fast-read; 14 | 15 | partition@0 { 16 | label = "Bootloader"; 17 | reg = <0 0x200000>; 18 | }; 19 | partition@200000 { 20 | label = "U-boot Env"; 21 | reg = <0x200000 0x10000>; 22 | }; 23 | partition@210000 { 24 | label = "Linux"; 25 | reg = <0x210000 0xDF0000>; 26 | }; 27 | }; 28 | }; 29 | -------------------------------------------------------------------------------- /rk3399/debug/timer/.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.ko 3 | *.cmd 4 | Module.symvers 5 | modules.order 6 | .tmp_versions/ 7 | *.mod.c 8 | *.mod.c 9 | -------------------------------------------------------------------------------- /rk3399/debug/timer/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile 2 | # Comment/uncomment the following line to disable/enable debugging 3 | # DEBUG = y 4 | 5 | # Usage 6 | # make CROSS_COMPILE= KERNEL_DIR= KERNEL_BUID_OUTPUT= 7 | # 8 | # make CROSS_COMPILE=/home/zeroway/rk3399/src/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin/aarch64-linux-android- KERNEL_DIR=/home/zeroway/rk3399/src/kernel KERNEL_BUID_OUTPUT=/home/zeroway/rk3399/src/out/target/product/rk3399_firefly_box/obj/KERNEL 9 | 10 | # Add your debugging flag (or not) to CFLAGS 11 | ifeq ($(DEBUG),y) 12 | DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines 13 | else 14 | DEBFLAGS = -O2 15 | endif 16 | 17 | obj-m := mytimer_test.o 18 | 19 | KERNEL_DIR ?= /lib/modules/$(shell uname -r)/build 20 | KERNEL_BUID_OUTPUT ?=$(KERNEL_DIR) 21 | CC = $(CROSS_COMPILE)gcc 22 | LD = $(CROSS_COMPILE)ld 23 | PWD := $(shell pwd) 24 | 25 | modules: 26 | $(MAKE) -C $(KERNEL_DIR) ARCH=arm64 M=$(PWD) O=$(KERNEL_BUID_OUTPUT) modules 27 | 28 | clean: 29 | rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions modules.order Module.symvers 30 | 31 | depend .depend dep: 32 | $(CC) $(CFLAGS) -M *.c > .depend 33 | 34 | ifeq (.depend,$(wildcard .depend)) 35 | include .depend 36 | endif 37 | -------------------------------------------------------------------------------- /rk3399/debug/timer/README.md: -------------------------------------------------------------------------------- 1 | # TIMER 2 | -------------------------------------------------------------------------------- /rk3399/debug/timer/mytimer_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define EXPIRES_PERIOD (5*HZ) 9 | 10 | struct self_define_struct { 11 | struct timer_list timer; 12 | }; 13 | 14 | static int g_cnt = 0; 15 | struct self_define_struct g_sds; 16 | const char *important_code = "this is a secret"; 17 | 18 | /* 19 | * printk_ratelimit函数的速率控制根据两个文件来确定,分别是: 20 | * 1. /proc/sys/kernel/printk_ratelimit 限制的时间间隔,默认值是5 21 | * 2. /proc/sys/kernel/printk_ratelimit_burst 22 | * 时间间隔内的最大打印条数,默认值是10 23 | * 所以默认的打印速率是每5秒最多打印10条 24 | */ 25 | static void timeout_handler(unsigned long tdata) 26 | { 27 | int i; 28 | const char *tmp = (const char *)tdata; 29 | 30 | for (i = 0; i < 100; i++) 31 | if(printk_ratelimit()) 32 | printk("%s got data[%s] %d times\n", __FUNCTION__, tmp, g_cnt++); 33 | 34 | g_cnt = 0; 35 | g_sds.timer.expires = jiffies + EXPIRES_PERIOD; 36 | add_timer(&g_sds.timer); 37 | } 38 | 39 | static int mytimer_test_init(void) 40 | { 41 | printk("%s, %d\n", __FUNCTION__, __LINE__); 42 | 43 | /* init timer */ 44 | init_timer(&g_sds.timer); 45 | 46 | /* setup the timer */ 47 | g_sds.timer.expires = jiffies + EXPIRES_PERIOD; 48 | g_sds.timer.function = timeout_handler; 49 | g_sds.timer.data = (unsigned long)important_code; 50 | 51 | /* add to system */ 52 | add_timer(&g_sds.timer); 53 | 54 | return 0; 55 | } 56 | 57 | static void mytimer_test_exit(void) 58 | { 59 | printk("%s, %d\n", __FUNCTION__, __LINE__); 60 | del_timer(&g_sds.timer); 61 | } 62 | 63 | module_init(mytimer_test_init) 64 | module_exit(mytimer_test_exit) 65 | -------------------------------------------------------------------------------- /rk3399/debug/uart/README.md: -------------------------------------------------------------------------------- 1 | # UART 2 | 3 | ## Firefly_RK3399 4 | 5 | 开发板默认使用uart2作为调试串口,在bootargs中有如下设置 6 | 7 | bootargs = "earlycon=uart8250,mmio32,0xff1a0000"; 8 | 9 | 其中0xff1a0000就是uart2的地址 10 | 11 | uart2: serial@ff1a0000 12 | 13 | 在cmdline中设置了console使用节点ttyFIQ0(等价与ttyS2) 14 | 15 | androidboot.console=ttyFIQ0 16 | 17 | ttyFIQ0节点驱动对应的dts如下 18 | 19 | fiq_debugger: fiq-debugger { 20 | compatible = "rockchip,fiq-debugger"; 21 | rockchip,serial-id = <2>; 22 | rockchip,signal-irq = <182>; 23 | rockchip,wake-irq = <0>; 24 | rockchip,irq-mode-enable = <1>; /* If enable uart uses irq instead of fiq */ 25 | rockchip,baudrate = <115200>; /* Only 115200 and 1500000 */ 26 | pinctrl-names = "default"; 27 | pinctrl-0 = <&uart2c_xfer>; 28 | }; 29 | 30 | 其中设置了对应的串口为uart2 31 | 32 | rockchip,serial-id = <2>; 33 | 34 | 所以如果要将调试串口改成其它串口,比如uart4 35 | 36 | 只需要fiq的dts和bootargs,内核日志就将在uart4上输出 37 | 38 | rockchip,serial-id = <4>; 39 | pinctrl-0 = <&uart4_xfer>; 40 | bootargs = "earlycon=uart8250,mmio32,ff370000"; 41 | -------------------------------------------------------------------------------- /rk3399/debug/usb/.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.ko 3 | *.cmd 4 | Module.symvers 5 | modules.order 6 | .tmp_versions/ 7 | *.mod.c 8 | *.mod.c 9 | -------------------------------------------------------------------------------- /rk3399/debug/usb/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile 2 | # Comment/uncomment the following line to disable/enable debugging 3 | # DEBUG = y 4 | 5 | # Usage 6 | # make CROSS_COMPILE= KERNEL_DIR= KERNEL_BUID_OUTPUT= 7 | # 8 | # make CROSS_COMPILE=/home/zeroway/rk3399/tool/gcc-linaro-4.9.4-2017.01-i686_aarch64-linux-gnu/bin/aarch64-linux-gnu- KERNEL_DIR=/home/zeroway/rk3399/src/firefly/kernel KERNEL_BUID_OUTPUT=/home/zeroway/rk3399/src/firefly/out/target/product/rk3399_firefly_box/obj/KERNEL 9 | 10 | # Add your debugging flag (or not) to CFLAGS 11 | ifeq ($(DEBUG),y) 12 | DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines 13 | else 14 | DEBFLAGS = -O2 15 | endif 16 | 17 | obj-m := usbmouse_as_key.o 18 | 19 | KERNEL_DIR ?= /lib/modules/$(shell uname -r)/build 20 | KERNEL_BUID_OUTPUT ?=$(KERNEL_DIR) 21 | CC = $(CROSS_COMPILE)gcc 22 | LD = $(CROSS_COMPILE)ld 23 | PWD := $(shell pwd) 24 | 25 | modules: 26 | $(MAKE) -C $(KERNEL_DIR) ARCH=arm64 M=$(PWD) O=$(KERNEL_BUID_OUTPUT) modules 27 | 28 | clean: 29 | rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions modules.order Module.symvers 30 | 31 | depend .depend dep: 32 | $(CC) $(CFLAGS) -M *.c > .depend 33 | 34 | ifeq (.depend,$(wildcard .depend)) 35 | include .depend 36 | endif 37 | -------------------------------------------------------------------------------- /rk3399/debug/usb/USB_Debugging_and_Profiling_Techniques.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3399/debug/usb/USB_Debugging_and_Profiling_Techniques.pdf -------------------------------------------------------------------------------- /rk3399/debug/usb/architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3399/debug/usb/architecture.png -------------------------------------------------------------------------------- /rk3399/debug/usb/mass_storage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3399/debug/usb/mass_storage.png -------------------------------------------------------------------------------- /rk3399/debug/usb/sequenceDiagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3399/debug/usb/sequenceDiagram.png -------------------------------------------------------------------------------- /rk3399/debug/usb/sequenceDiagram.txt: -------------------------------------------------------------------------------- 1 | @startuml 2 | 3 | participant "Host(rkflashtool)" as host 4 | participant "Slave(rockusb)" as slave 5 | 6 | host -> slave : send_cbw 7 | note right : usb_read 8 | slave -> host : recv_data 9 | slave -> host : recv_csw 10 | 11 | host -> slave : send_cbw 12 | note right : usb_write 13 | host -> slave : send_data 14 | slave -> host : recv_csw 15 | 16 | @enduml 17 | -------------------------------------------------------------------------------- /rk3399/debug/usb/tx_in_busy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3399/debug/usb/tx_in_busy.png -------------------------------------------------------------------------------- /rk3399/debug/usb/tx_in_error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3399/debug/usb/tx_in_error.png -------------------------------------------------------------------------------- /rk3399/debug/usb/tx_in_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3399/debug/usb/tx_in_normal.png -------------------------------------------------------------------------------- /rk3399/debug/usb/tx_out_busy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3399/debug/usb/tx_out_busy.png -------------------------------------------------------------------------------- /rk3399/debug/usb/tx_out_error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3399/debug/usb/tx_out_error.png -------------------------------------------------------------------------------- /rk3399/debug/usb/tx_out_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3399/debug/usb/tx_out_normal.png -------------------------------------------------------------------------------- /rk3399/debug/usb/tx_setup_busy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3399/debug/usb/tx_setup_busy.png -------------------------------------------------------------------------------- /rk3399/debug/usb/tx_setup_error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3399/debug/usb/tx_setup_error.png -------------------------------------------------------------------------------- /rk3399/debug/usb/tx_setup_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3399/debug/usb/tx_setup_normal.png -------------------------------------------------------------------------------- /rk3399/debug/usb/usbmon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3399/debug/usb/usbmon.png -------------------------------------------------------------------------------- /rk3399/debug/wdog/README.md: -------------------------------------------------------------------------------- 1 | # 看门狗(watchdog) 2 | 3 | 设备节点信息(watchdog和watchdog0) 4 | 5 | crw------- 1 root root 10, 130 Jan 18 08:52 /dev/watchdog 6 | crw------- 1 root root 247, 0 Jan 18 08:52 /dev/watchdog0 7 | 8 | 这两给设备节点对应的是同一个设备(硬狗或是软狗) 9 | 10 | watchdog是为了兼容老的API接口保留的 11 | 12 | ## 使用方法 13 | 14 | 使能看门狗 15 | 16 | fd = open("/dev/watchdog", O_WRONLY) 17 | 18 | 设置超时时间 19 | 20 | ioctl(fd, WDIOC_SETTIMEOUT, &timeout); 21 | ioctl(fd, WDIOC_GETTIMEOUT, &timeout); 22 | 23 | 喂狗操作 24 | 25 | ioctl(fd, WDIOC_KEEPALIVE, 0); 26 | 或 27 | write(fd, "\0", 1); 28 | -------------------------------------------------------------------------------- /rk3399/debug/wdog/wdt_driver_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define WDT_DEV_NODE "/dev/watchdog" 9 | 10 | void help_info(void) 11 | { 12 | printf("Usage: wdt_driver_test \n"); 13 | printf(" timeout: value in seconds to cause wdt timeout/reset\n"); 14 | printf(" sleep: value in seconds to service the wdt\n"); 15 | printf(" test: 0 - Service wdt with ioctl(), 1 - with write()\n"); 16 | } 17 | 18 | int main(int argc, const char *argv[]) 19 | { 20 | int fd, timeout, sleep_sec, test; 21 | 22 | if (argc < 2) { 23 | help_info(); 24 | return 1; 25 | } 26 | 27 | timeout = atoi(argv[1]); 28 | sleep_sec = atoi(argv[2]); 29 | if (sleep_sec <= 0) { 30 | sleep_sec = 1; 31 | printf("correct 0 or negative sleep time to %d seconds\n", 32 | sleep_sec); 33 | } 34 | test = atoi(argv[3]); 35 | printf("Starting wdt_driver (timeout: %d, sleep: %d, test: %s)\n", 36 | timeout, sleep_sec, (test == 0) ? "ioctl" : "write"); 37 | fd = open(WDT_DEV_NODE, O_WRONLY); 38 | if (fd == -1) { 39 | perror("watchdog"); 40 | exit(1); 41 | } 42 | printf("Trying to set timeout value=%d seconds\n", timeout); 43 | ioctl(fd, WDIOC_SETTIMEOUT, &timeout); 44 | printf("The actual timeout was set to %d seconds\n", timeout); 45 | ioctl(fd, WDIOC_GETTIMEOUT, &timeout); 46 | printf("Now reading back -- The timeout is %d seconds\n", timeout); 47 | 48 | while (1) 49 | { 50 | if (test == 0) 51 | { 52 | ioctl(fd, WDIOC_KEEPALIVE, 0); 53 | } 54 | else 55 | { 56 | write(fd, "\0", 1); 57 | } 58 | 59 | sleep(sleep_sec); 60 | } 61 | 62 | return 0; 63 | } 64 | -------------------------------------------------------------------------------- /rk3399/drm.md: -------------------------------------------------------------------------------- 1 | # Rockchip DRM 2 | 3 | [rockchip drm](https://markyzq.gitbooks.io/rockchip_drm_integration_helper/content/zh/) 4 | 5 | ## modetest 6 | 7 | modetest是libdrm源码自带的调试工具, 可以对drm进行一些基础的调试 8 | 9 | android平: 10 | 11 | mmm external/libdrm/tests 12 | 13 | linux平台(在开发主机上编译) 14 | 15 | git clone git://anongit.freedesktop.org/mesa/drm && cd drm 16 | CC=aarch64-linux-gnu-gcc ./autogen.sh --host=aarch64-linux --disable-freedreno --disable-cairo-tests --enable-install-test-programs 17 | make -j8 && make install DESTDIR=`pwd`/out 18 | adb push out/usr/local /usr/local 19 | -------------------------------------------------------------------------------- /rk3399/fw_bcm4356a2_ag.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3399/fw_bcm4356a2_ag.bin -------------------------------------------------------------------------------- /rk3399/gst.md: -------------------------------------------------------------------------------- 1 | # Gstreamer使用 2 | 3 | ## 视频播放 4 | 5 | 使用gstreamer播放本地视频 6 | 7 | export DISPLAY=:0.0 8 | gst-launch-1.0 uridecodebin uri=file:///usr/local/test.mp4 ! rkximagesink 9 | 10 | 如果是root用户执行则要切换到普通用户 11 | 12 | su linaro -c "gst-launch-1.0 uridecodebin uri=file:///usr/local/test.mp4 ! rkximagesink" 13 | 14 | ## 编解码测试 15 | 16 | 编解码测试[参考代码](./test_enc.sh) 17 | 18 | export DISPLAY=:0.0 19 | su linaro -c "gst-launch-1.0 videotestsrc num-buffers=512 ! video/x-raw,format=NV12,width=1920,height= 1080,framerate=30/1 ! queue ! mpph264enc ! queue ! h264parse ! mpegtsmux ! filesink location=/home/linaro/2k.ts" 20 | su linaro -c "gst-launch-1.0 uridecodebin uri=file:///home/linaro/2k.ts ! rkximagesink" 21 | 22 | 23 | JPEG解码测试 24 | 25 | export DISPLAY=:0.0 26 | su linaro -c 'gst-launch-1.0 -v videotestsrc ! "video/x-raw,width=1920,height=1080" ! queue ! jpegenc ! queue ! jpegparse ! queue ! mppvideodec ! rkximagesink' 27 | -------------------------------------------------------------------------------- /rk3399/input_event.md: -------------------------------------------------------------------------------- 1 | # User Buttons 2 | 3 | 使用evtest来查看输入设备和输入事件 4 | 5 | For example, on the sapphire-excavator-board(buildroot) 6 | 7 | [root@rk3399:/]# evtest 8 | No device specified, trying to scan all of /dev/input/event* 9 | Available devices: 10 | /dev/input/event0: gsl3673 11 | /dev/input/event1: adc-keys 12 | /dev/input/event2: gpio-keys 13 | Select the device event number [0-2]: 1 14 | Input driver version is 1.0.1 15 | Input device ID: bus 0x19 vendor 0x1 product 0x1 version 0x100 16 | Input device name: "adc-keys" 17 | Supported events: 18 | Event type 0 (EV_SYN) 19 | Event type 1 (EV_KEY) 20 | Event code 1 (KEY_ESC) 21 | Event code 114 (KEY_VOLUMEDOWN) 22 | Event code 115 (KEY_VOLUMEUP) 23 | Event code 139 (KEY_MENU) 24 | Event code 158 (KEY_BACK) 25 | Properties: 26 | Testing ... (interrupt to exit) 27 | Event: time 1358512388.027673, type 1 (EV_KEY), code 115 (KEY_VOLUMEUP), value 1 28 | Event: time 1358512388.027673, -------------- SYN_REPORT ------------ 29 | Event: time 1358512388.127788, type 1 (EV_KEY), code 115 (KEY_VOLUMEUP), value 0 30 | Event: time 1358512388.127788, -------------- SYN_REPORT ------------ 31 | -------------------------------------------------------------------------------- /rk3399/io_domain.md: -------------------------------------------------------------------------------- 1 | # IO-Domain 2 | 3 | RK3399一共有5组GPIO(gpio0~gpio4) 4 | 5 | 每组gpio都会有不同的电源域,组划分如下(可在RK3399 TRM中找到对应的描述) 6 | 7 | - pmuio1_gpio0ab 8 | - pmu1830_gpio1abcd 9 | - gmac_gpio3abc 10 | - bt656_gpio2ab 11 | - wifi/bt_gpio2cd 12 | - gpio1830_gpio4cd 13 | - audio_gpio3d_gpio4a 14 | - sdmmc_gpio4b 15 | 16 | ## FireflyRK3399开发板情况 17 | 18 | 下图是Firefly-RK3399开发板的PowerDomainMap 19 | 20 | ![power domain map](./pdmap.png) 21 | 22 | DeviceTree中配置如下 23 | 24 | &io_domains { 25 | status = "okay"; 26 | 27 | bt656-supply = <&vcc1v8_dvp>; /* bt656_gpio2ab_ms */ 28 | audio-supply = <&vcca1v8_codec>; /* audio_gpio3d4a_ms */ 29 | sdmmc-supply = <&vcc_sd>; /* sdmmc_gpio4b_ms */ 30 | gpio1830-supply = <&vcc_3v0>; /* gpio1833_gpio4cd_ms */ 31 | }; 32 | 33 | &pmu_io_domains { 34 | status = "okay"; 35 | pmu1830-supply = <&vcc_3v0>; 36 | }; 37 | 38 | PMU(PMIC)对应的电源节点如下 39 | 40 | vcc1v8_dvp: LDO_REG1 { 41 | regulator-always-on; 42 | regulator-boot-on; 43 | regulator-min-microvolt = <1800000>; 44 | regulator-max-microvolt = <1800000>; 45 | regulator-name = "vcc1v8_dvp"; 46 | regulator-state-mem { 47 | regulator-off-in-suspend; 48 | }; 49 | }; 50 | 51 | vcca1v8_codec: LDO_REG7 { 52 | regulator-always-on; 53 | regulator-boot-on; 54 | regulator-min-microvolt = <1800000>; 55 | regulator-max-microvolt = <1800000>; 56 | regulator-name = "vcca1v8_codec"; 57 | regulator-state-mem { 58 | regulator-off-in-suspend; 59 | }; 60 | }; 61 | 62 | vcc_sd: LDO_REG4 { 63 | regulator-always-on; 64 | regulator-boot-on; 65 | regulator-min-microvolt = <1800000>; 66 | regulator-max-microvolt = <3000000>; 67 | regulator-name = "vcc_sd"; 68 | regulator-state-mem { 69 | regulator-on-in-suspend; 70 | regulator-suspend-microvolt = <3000000>; 71 | }; 72 | }; 73 | 74 | vcc_3v0: LDO_REG8 { 75 | regulator-always-on; 76 | regulator-boot-on; 77 | regulator-min-microvolt = <3000000>; 78 | regulator-max-microvolt = <3000000>; 79 | regulator-name = "vcc_3v0"; 80 | regulator-state-mem { 81 | regulator-on-in-suspend; 82 | regulator-suspend-microvolt = <3000000>; 83 | }; 84 | }; 85 | 86 | 举例说明 87 | 88 | ![apio5_vdd](./apio5.png) 89 | 90 | APIO5_VDD<-->VCCA1V8_CODEC(VLDO7) 91 | 92 | 对于没有PMIC的情况 93 | 94 | 设备树中可以如下配置几个(fixed)固定的regulator 95 | 96 | io-domains { 97 | status = "okay"; 98 | vccio1-supply = <&vccio_3v3_reg>; 99 | vccio2-supply = <&vccio_1v8_reg>; 100 | vccio4-supply = <&vccio_3v3_reg>; 101 | }; 102 | 103 | regulators { 104 | compatible = "simple-bus"; 105 | #address-cells = <1>; 106 | #size-cells = <0>; 107 | vccio_1v8_reg: regulator@0 { 108 | compatible = "regulator-fixed"; 109 | regulator-name = "vccio_1v8"; 110 | regulator-min-microvolt = <1800000>; 111 | regulator-max-microvolt = <1800000>; 112 | regulator-always-on; 113 | }; 114 | vccio_3v3_reg: regulator@1 { 115 | compatible = "regulator-fixed"; 116 | regulator-name = "vccio_3v3"; 117 | regulator-min-microvolt = <3300000>; 118 | regulator-max-microvolt = <3300000>; 119 | regulator-always-on; 120 | }; 121 | }; 122 | -------------------------------------------------------------------------------- /rk3399/lp079qx1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3399/lp079qx1.png -------------------------------------------------------------------------------- /rk3399/parameter_android: -------------------------------------------------------------------------------- 1 | FIRMWARE_VER: 6.0.1 2 | MACHINE_MODEL: RK3399 3 | MACHINE_ID: 007 4 | MANUFACTURER: RK3399 5 | MAGIC: 0x5041524B 6 | ATAG: 0x00200800 7 | MACHINE: 3399 8 | CHECK_MASK: 0x80 9 | PWR_HLD: 0,0,A,0,1 10 | #KERNEL_IMG: 0x00280000 11 | #FDT_NAME: rk-kernel.dtb 12 | #RECOVER_KEY: 1,1,0,20,0 13 | #in section; per section 512(0x200) bytes 14 | CMDLINE: androidboot.baseband=N/A androidboot.selinux=disabled androidboot.hardware=rk30board androidboot.console=ttyFIQ0 init=/init mtdparts=rk29xxnand:0x00002000@0x00002000(uboot),0x00002000@0x00004000(trust),0x00002000@0x00006000(misc),0x00008000@0x00008000(resource),0x0000A000@0x00010000(kernel),0x00010000@0x0001A000(boot),0x00010000@0x0002A000(recovery),0x00038000@0x0003A000(backup),0x00040000@0x00072000(cache),0x00200000@0x000B2000(system),0x00008000@0x002B2000(metadata),0x00002000@0x002BA000(baseparamer),-@0x002BC000(userdata) 15 | -------------------------------------------------------------------------------- /rk3399/parameter_linux: -------------------------------------------------------------------------------- 1 | FIRMWARE_VER: 6.0.1 2 | MACHINE_MODEL: RK3399 3 | MACHINE_ID: 007 4 | MANUFACTURER: RK3399 5 | MAGIC: 0x5041524B 6 | ATAG: 0x00200800 7 | MACHINE: 3399 8 | CHECK_MASK: 0x80 9 | PWR_HLD: 0,0,A,0,1 10 | #KERNEL_IMG: 0x00280000 11 | #FDT_NAME: rk-kernel.dtb 12 | #RECOVER_KEY: 1,1,0,20,0 13 | #in section; per section 512(0x200) bytes 14 | CMDLINE: androidboot.baseband=N/A androidboot.selinux=disabled androidboot.hardware=rk30board androidboot.console=ttyS2 init=/sbin/init root=/dev/mmcblk1p5 rw rootwait mtdparts=rk29xxnand:0x00002000@0x00002000(uboot),0x00002000@0x00004000(trust),0x00010000@0x00006000(boot),0x00002000@0x00016000(backup),-@0x00018000(linuxroot) 15 | -------------------------------------------------------------------------------- /rk3399/pdmap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3399/pdmap.png -------------------------------------------------------------------------------- /rk3399/port1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3399/port1.png -------------------------------------------------------------------------------- /rk3399/port2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3399/port2.png -------------------------------------------------------------------------------- /rk3399/port3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3399/port3.png -------------------------------------------------------------------------------- /rk3399/ramdiskfs/etc/fstab: -------------------------------------------------------------------------------- 1 | #device mount-point type options dump fsck order 2 | proc /proc proc defaults 0 0 3 | tmpfs /tmp tmpfs defaults 0 0 4 | sysfs /sys sysfs defaults 0 0 5 | tmpfs /dev tmpfs defaults 0 0 6 | -------------------------------------------------------------------------------- /rk3399/ramdiskfs/etc/group: -------------------------------------------------------------------------------- 1 | root:*:0: 2 | daemon:*:1: 3 | bin:*:2: 4 | sys:*:3: 5 | adm:*:4: 6 | tty:*:5: 7 | disk:*:6: 8 | lp:*:7:lp 9 | mail:*:8: 10 | news:*:9: 11 | uucp:*:10: 12 | proxy:*:13: 13 | kmem:*:15: 14 | dialout:*:20: 15 | fax:*:21: 16 | voice:*:22: 17 | cdrom:*:24: 18 | floppy:*:25: 19 | tape:*:26: 20 | sudo:*:27: 21 | audio:*:29: 22 | ppp:x:99: 23 | -------------------------------------------------------------------------------- /rk3399/ramdiskfs/etc/init.d/rcS: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | mount -a 4 | mkdir /dev/pts 5 | mount -t devpts devpts /dev/pts 6 | echo /sbin/mdev > /proc/sys/kernel/hotplug 7 | /sbin/mdev -s 8 | -------------------------------------------------------------------------------- /rk3399/ramdiskfs/etc/inittab: -------------------------------------------------------------------------------- 1 | ::sysinit:/etc/init.d/rcS 2 | console::askfirst:-/bin/sh 3 | ::ctrlaltdel:/sbin/reboot 4 | ::shutdown:/bin/umount -a -r 5 | -------------------------------------------------------------------------------- /rk3399/ramdiskfs/etc/passwd: -------------------------------------------------------------------------------- 1 | root:x:0:0:root:/:/bin/sh 2 | ftp::14:50:FTP User:/var/ftp: 3 | bin:*:1:1:bin:/bin: 4 | daemon:*:2:2:daemon:/sbin: 5 | nobody:*:99:99:Nobody:/: 6 | -------------------------------------------------------------------------------- /rk3399/ramdiskfs/etc/profile: -------------------------------------------------------------------------------- 1 | # Ash profile 2 | # vim: syntax=sh 3 | 4 | # No core files by default 5 | ulimit -S -c 0 > /dev/null 2>&1 6 | 7 | USER="`id -un`" 8 | LOGNAME=$USER 9 | PS1='[\u@\h \W]\# ' 10 | PATH=$PATH:/usr/local/bin 11 | 12 | HOSTNAME=`/bin/hostname` 13 | 14 | export USER LOGNAME PS1 PATH 15 | -------------------------------------------------------------------------------- /rk3399/ramdiskfs/etc/sysconfig/HOSTNAME: -------------------------------------------------------------------------------- 1 | rk3399 2 | -------------------------------------------------------------------------------- /rk3399/replace_gpio.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #Usage 4 | #replace_gpio 5 | 6 | # gpio map 7 | GPIO_OFFSET=( 8 | A0 A1 A2 A3 A4 A5 A6 A7 9 | B0 B1 B2 B3 B4 B5 B6 B7 10 | C0 C1 C2 C3 C4 C5 C6 C7 11 | D0 D1 D2 D3 D4 D5 D6 D7) 12 | 13 | # must do it from 31->0 :), in case of suck thing happen 14 | for (( offset = 31; offset >= 0; offset-- )) 15 | do 16 | sed -i "/&gpio/s/\ $offset/\ ${GPIO_OFFSET[offset]}/g" $1 17 | done 18 | -------------------------------------------------------------------------------- /rk3399/replace_pin.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #Usage 4 | #replace_gpio 5 | 6 | # gpio map 7 | GPIO_OFFSET=( 8 | A0 A1 A2 A3 A4 A5 A6 A7 9 | B0 B1 B2 B3 B4 B5 B6 B7 10 | C0 C1 C2 C3 C4 C5 C6 C7 11 | D0 D1 D2 D3 D4 D5 D6 D7) 12 | 13 | # must do it from 31->0 :), in case of suck thing happen 14 | for (( offset = 31; offset >= 0; offset-- )) 15 | do 16 | for (( bank = 4; bank >= 0; bank-- )) 17 | do 18 | #sed -i "/&gpio/s/\ $offset/\ ${GPIO_OFFSET[offset]}/g" $1 19 | sed -i "/RK_FUNC_/s/<$bank $offset/; 19 | pinctrl-names = "default"; 20 | pinctrl-0 = <&led_power>; 21 | }; 22 | user { 23 | label = "firefly:yellow:user"; 24 | linux,default-trigger = "ir-user-click"; 25 | default-state = "off"; 26 | gpios = <&gpio0 B5 GPIO_ACTIVE_HIGH>; 27 | pinctrl-names = "default"; 28 | pinctrl-0 = <&led_user>; 29 | }; 30 | }; 31 | ``` 32 | 33 | 其中注意两个宏设置,和名字意思相反 34 | 35 | #define GPIO_ACTIVE_HIGH 0 36 | #define GPIO_ACTIVE_LOW 1 37 | 38 | 在uboot的板级驱动文件rk33xx.c中添加如下代码, 39 | 后在board_late_init函数中调用power_led_init即可 40 | 41 | ```c 42 | static struct fdt_gpio_state power_led_gpio; 43 | static struct fdt_gpio_state user_led_gpio; 44 | int power_led_parse_dt(const void *blob) 45 | { 46 | int power_node = 0; 47 | int user_node = 0; 48 | int node = 0; 49 | 50 | /* 通过compatible获取leds的node */ 51 | node = fdt_node_offset_by_compatible(blob, 0, "gpio-leds"); 52 | if (node < 0) { 53 | printf("can't find dts node for led\n"); 54 | return -ENODEV; 55 | } 56 | 57 | /* 获取leds下power和user的node */ 58 | power_node = fdt_subnode_offset(blob, node, "power"); 59 | user_node = fdt_subnode_offset(blob, node, "user"); 60 | 61 | /* 获取power和user里管脚配置 */ 62 | fdtdec_decode_gpio(blob, power_node, "gpios", &power_led_gpio); 63 | fdtdec_decode_gpio(blob, user_node, "gpios", &user_led_gpio); 64 | 65 | /* 打印出相关信息 */ 66 | printf("power_led_gpio: %s,%d-%d\n", power_led_gpio.name, power_led_gpio.gpio, power_led_gpio.flags); 67 | printf("user_led_gpio: %s,%d-%d\n", user_led_gpio.name, user_led_gpio.gpio, user_led_gpio.flags); 68 | 69 | return 0; 70 | } 71 | 72 | void power_led_init(void) 73 | { 74 | power_led_parse_dt(gd->fdt_blob); 75 | if (power_led_gpio.name != NULL) 76 | { 77 | /* 由于GPIO_ACTIVE_HIGH宏定义反了,所以这里需要取反flags */ 78 | gpio_direction_output(power_led_gpio.gpio, !power_led_gpio.flags); 79 | gpio_direction_output(user_led_gpio.gpio, !user_led_gpio.flags); 80 | } 81 | } 82 | ``` 83 | -------------------------------------------------------------------------------- /rk3399/uboot/leds.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/rk3399/uboot/leds.png -------------------------------------------------------------------------------- /tiny4412/debug/buttons/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile 2 | # Comment/uncomment the following line to disable/enable debugging 3 | # DEBUG = y 4 | 5 | # Usage 6 | # make KERNEL_DIR=/home/zeroway/github/4412dt/new_kernel/linux-4.4 KERNEL_BUID_OUTPUT=/home/zeroway/github/4412dt/new_kernel/linux-4.4/out ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- 7 | 8 | # Add your debugging flag (or not) to CFLAGS 9 | ifeq ($(DEBUG),y) 10 | DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines 11 | else 12 | DEBFLAGS = -O2 13 | endif 14 | 15 | obj-m := buttons.o 16 | KERNEL_DIR ?= /lib/modules/$(shell uname -r)/build 17 | KERNEL_BUID_OUTPUT ?=$(KERNEL_DIR) 18 | CC = $(CROSS_COMPILE)gcc 19 | LD = $(CROSS_COMPILE)ld 20 | PWD := $(shell pwd) 21 | 22 | modules: 23 | $(MAKE) -C $(KERNEL_DIR) M=$(PWD) O=$(KERNEL_BUID_OUTPUT) modules 24 | 25 | clean: 26 | rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions modules.order Module.symvers 27 | 28 | depend .depend dep: 29 | $(CC) $(CFLAGS) -M *.c > .depend 30 | 31 | ifeq (.depend,$(wildcard .depend)) 32 | include .depend 33 | endif 34 | -------------------------------------------------------------------------------- /tiny4412/debug/buttons/README.md: -------------------------------------------------------------------------------- 1 | # 按键驱动 2 | 3 | ## 硬件连接 4 | 5 | 当按键按下后电平由高变低 6 | 7 | ![button1](./button1.png) 8 | 9 | ![button2](./button2.png) 10 | 11 | ## 使用方法 12 | 13 | 在主设备树文件里包含下面的文件 14 | 15 | #include "buttons.dtsi" 16 | 17 | ## 测试 18 | 19 | 按下每个按键后会打印日志 20 | -------------------------------------------------------------------------------- /tiny4412/debug/buttons/button1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/tiny4412/debug/buttons/button1.png -------------------------------------------------------------------------------- /tiny4412/debug/buttons/button2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/tiny4412/debug/buttons/button2.png -------------------------------------------------------------------------------- /tiny4412/debug/buttons/buttons.dtsi: -------------------------------------------------------------------------------- 1 | /{ 2 | interrupt_buttons { 3 | compatible = "tiny4412,buttons"; 4 | tiny4412,int_gpio1 = <&gpx3 2 GPIO_ACTIVE_HIGH>; 5 | tiny4412,int_gpio2 = <&gpx3 3 GPIO_ACTIVE_HIGH>; 6 | tiny4412,int_gpio3 = <&gpx3 4 GPIO_ACTIVE_HIGH>; 7 | tiny4412,int_gpio4 = <&gpx3 5 GPIO_ACTIVE_HIGH>; 8 | }; 9 | }; 10 | -------------------------------------------------------------------------------- /tiny4412/debug/leds/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile 2 | # Comment/uncomment the following line to disable/enable debugging 3 | # DEBUG = y 4 | 5 | # Usage 6 | # make KERNEL_DIR=/home/zeroway/github/4412dt/new_kernel/linux-4.4 KERNEL_BUID_OUTPUT=/home/zeroway/github/4412dt/new_kernel/linux-4.4/out ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- 7 | 8 | # Add your debugging flag (or not) to CFLAGS 9 | ifeq ($(DEBUG),y) 10 | DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines 11 | else 12 | DEBFLAGS = -O2 13 | endif 14 | 15 | obj-m := leds.o 16 | KERNEL_DIR ?= /lib/modules/$(shell uname -r)/build 17 | KERNEL_BUID_OUTPUT ?=$(KERNEL_DIR) 18 | CC = $(CROSS_COMPILE)gcc 19 | LD = $(CROSS_COMPILE)ld 20 | PWD := $(shell pwd) 21 | 22 | modules: 23 | $(MAKE) -C $(KERNEL_DIR) M=$(PWD) O=$(KERNEL_BUID_OUTPUT) modules 24 | 25 | clean: 26 | rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions modules.order Module.symvers 27 | 28 | depend .depend dep: 29 | $(CC) $(CFLAGS) -M *.c > .depend 30 | 31 | ifeq (.depend,$(wildcard .depend)) 32 | include .depend 33 | endif 34 | -------------------------------------------------------------------------------- /tiny4412/debug/leds/README.md: -------------------------------------------------------------------------------- 1 | # LED驱动 2 | 3 | ## 硬件连接 4 | 5 | 硬件连接如下图,四个LED由GPM4上4个GPIO控制,低电平点亮LED 6 | 7 | ![led1](./led1.png) 8 | 9 | ![led2](./led2.png) 10 | 11 | ## 寄存器配置 12 | 13 | GPM4的基地址是0x11000000 14 | 15 | ![reg1](./reg1.png) 16 | 17 | ![reg2](./reg2.png) 18 | 19 | 20 | ## 使用方法 21 | 22 | 在主设备树文件里包含下面的文件 23 | 24 | #include "leds.dtsi" 25 | 26 | ## 测试 27 | 28 | 加载驱动后 29 | 30 | cd /sys/bus/platform/drivers/leds/11000000.leds 31 | 32 | 查看状态 33 | 34 | cat leds 35 | 36 | 切换到active配置 37 | 38 | echo active > leds 39 | 40 | 41 | 切换到sleep配置 42 | 43 | echo sleep > leds 44 | 45 | 拉高拉低管脚 46 | 47 | echo 1 > leds 48 | echo 0 > leds 49 | -------------------------------------------------------------------------------- /tiny4412/debug/leds/led1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/tiny4412/debug/leds/led1.png -------------------------------------------------------------------------------- /tiny4412/debug/leds/led2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/tiny4412/debug/leds/led2.png -------------------------------------------------------------------------------- /tiny4412/debug/leds/leds.dtsi: -------------------------------------------------------------------------------- 1 | /{ 2 | leds { 3 | compatible = "tiny4412,leds"; 4 | reg = <0x11000000 0x300>; 5 | tiny4412,gpio = <&gpm4 0 GPIO_ACTIVE_HIGH 6 | &gpm4 1 GPIO_ACTIVE_HIGH 7 | &gpm4 2 GPIO_ACTIVE_HIGH 8 | &gpm4 3 GPIO_ACTIVE_HIGH>; 9 | pinctrl-names = "default", "gpio_sleep", "gpio_active"; 10 | pinctrl-0 = <&led_gpio_default>; 11 | pinctrl-1 = <&led_gpio_sleep>; 12 | pinctrl-2 = <&led_gpio_active>; 13 | }; 14 | }; 15 | 16 | &pinctrl_1 { 17 | led_gpio_default: leds_default { 18 | samsung,pins = "gpm4-0", "gpm4-1", "gpm4-2", "gpm4-3"; 19 | samsung,pin-function = <1>; 20 | samsung,pin-pud = <1>; 21 | samsung,pin-drv = <2>; 22 | }; 23 | 24 | led_gpio_sleep: leds_sleep { 25 | samsung,pins = "gpm4-0", "gpm4-1", "gpm4-2", "gpm4-3"; 26 | samsung,pin-function = <1>; 27 | samsung,pin-pud = <0>; 28 | samsung,pin-drv = <0>; 29 | }; 30 | 31 | led_gpio_active: leds_active { 32 | samsung,pins = "gpm4-0", "gpm4-1", "gpm4-2", "gpm4-3"; 33 | samsung,pin-function = <1>; 34 | samsung,pin-pud = <3>; 35 | samsung,pin-drv = <3>; 36 | }; 37 | }; 38 | -------------------------------------------------------------------------------- /tiny4412/debug/leds/reg1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/tiny4412/debug/leds/reg1.png -------------------------------------------------------------------------------- /tiny4412/debug/leds/reg2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/tiny4412/debug/leds/reg2.png -------------------------------------------------------------------------------- /x86/README.md: -------------------------------------------------------------------------------- 1 | [A BPF introduction example](./bpf) 2 | 3 | [Virtual Crypto device and driver](./crypto) 4 | 5 | [USB device driver](./usb) 6 | -------------------------------------------------------------------------------- /x86/bitmap/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile 2 | # Comment/uncomment the following line to disable/enable debugging 3 | # DEBUG = y 4 | 5 | # Usage 6 | # make CROSS_COMPILE= KERNEL_DIR= KERNEL_BUID_OUTPUT= 7 | # 8 | # make CROSS_COMPILE=/home/zeroway/rk3399/tool/gcc-linaro-4.9.4-2017.01-i686_aarch64-linux-gnu/bin/aarch64-linux-gnu- KERNEL_DIR=/home/zeroway/rk3399/src/firefly/kernel KERNEL_BUID_OUTPUT=/home/zeroway/rk3399/src/firefly/out/target/product/rk3399_firefly_box/obj/KERNEL 9 | 10 | # Add your debugging flag (or not) to CFLAGS 11 | ifeq ($(DEBUG),y) 12 | DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines 13 | else 14 | DEBFLAGS = -O2 15 | endif 16 | 17 | obj-m := bitmap_test.o 18 | 19 | KERNEL_DIR ?= /lib/modules/`uname -r`/build 20 | KERNEL_BUID_OUTPUT ?=$(KERNEL_DIR) 21 | CC = $(CROSS_COMPILE)gcc 22 | LD = $(CROSS_COMPILE)ld 23 | PWD := $(shell pwd) 24 | ARCH := x86_64 25 | 26 | modules: 27 | $(MAKE) -C $(KERNEL_DIR) ARCH=$(ARCH) M=$(PWD) O=$(KERNEL_DIR) modules 28 | 29 | clean: 30 | rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions modules.order Module.symvers 31 | 32 | depend .depend dep: 33 | $(CC) $(CFLAGS) -M *.c > .depend 34 | 35 | ifeq (.depend,$(wildcard .depend)) 36 | include .depend 37 | endif 38 | -------------------------------------------------------------------------------- /x86/bitmap/bitmap_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* https://www.cnblogs.com/schips/p/10674687.html */ 5 | 6 | #define BITMAP_LEN 10 7 | 8 | #define USING_UNLONG 9 | #ifdef USING_UNLONG 10 | unsigned long mybm[1]; 11 | #else 12 | DECLARE_BITMAP(mybm, BITMAP_LEN); 13 | #endif 14 | 15 | static int bitmap_test_init(void) 16 | { 17 | int bit; 18 | 19 | /* architecture specifiy API */ 20 | /* 21 | * non atomic version 22 | * include/asm-generic/bitops/instrumented-non-atomic.h 23 | */ 24 | __set_bit(1, mybm); 25 | /* 26 | * arch___set_bit(nr, addr); 27 | * asm volatile(__ASM_SIZE(bts) " %1,%0" : : ADDR, "Ir" (nr) : "memory"); 28 | */ 29 | if (!test_bit(1, mybm)) 30 | printk(KERN_ALERT" bit 1 tested not set\n"); 31 | else 32 | printk(KERN_ALERT" bit 1 tested set\n"); 33 | 34 | __clear_bit(1, mybm); 35 | if (!test_bit(1, mybm)) 36 | printk(KERN_ALERT" bit 1 tested not set\n"); 37 | else 38 | printk(KERN_ALERT" bit 1 tested set\n"); 39 | 40 | /* 41 | * atomic version 42 | * include/asm-generic/bitops/atomic.h 43 | * arch/x86/boot/bitops.h 44 | */ 45 | set_bit(2, mybm); 46 | if (!test_bit(2, mybm)) 47 | printk(KERN_ALERT" bit 2 tested not set\n"); 48 | else 49 | printk(KERN_ALERT" bit 2 tested set\n"); 50 | 51 | clear_bit(2, mybm); 52 | if (!test_bit(2, mybm)) 53 | printk(KERN_ALERT" bit 2 tested not set\n"); 54 | else 55 | printk(KERN_ALERT" bit 2 tested set\n"); 56 | 57 | /* Generic API */ 58 | bitmap_zero(mybm, BITMAP_LEN); 59 | if (!test_bit(3, mybm)) 60 | printk(KERN_ALERT" bit 3 tested not set\n"); 61 | else 62 | printk(KERN_ALERT" bit 3 tested set\n"); 63 | 64 | bitmap_fill(mybm, BITMAP_LEN); 65 | if (!test_bit(3, mybm)) 66 | printk(KERN_ALERT" bit 3 tested not set\n"); 67 | else 68 | printk(KERN_ALERT" bit 3 tested set\n"); 69 | 70 | /* clear all before test */ 71 | bitmap_zero(mybm, BITMAP_LEN); 72 | set_bit(4, mybm); 73 | set_bit(8, mybm); 74 | set_bit(9, mybm); 75 | /* iterator all the setted bit */ 76 | for_each_set_bit(bit, mybm, BITMAP_LEN) 77 | printk(KERN_ALERT" %d\n", bit); 78 | printk(KERN_ALERT"===========\n"); 79 | 80 | /* iterator all the no setted bit */ 81 | for_each_clear_bit(bit, mybm, BITMAP_LEN) 82 | printk(KERN_ALERT" %d\n", bit); 83 | printk(KERN_ALERT"===========\n"); 84 | 85 | printk(KERN_ALERT"BitMap test Done\n"); 86 | 87 | return 0; 88 | } 89 | 90 | static void bitmap_test_exit(void) 91 | { 92 | printk(KERN_ALERT"BitMap test Exit\n"); 93 | } 94 | 95 | MODULE_LICENSE("Dual BSD/GPL"); 96 | module_init(bitmap_test_init); 97 | module_exit(bitmap_test_exit); 98 | -------------------------------------------------------------------------------- /x86/bpf/.gitignore: -------------------------------------------------------------------------------- 1 | demo 2 | -------------------------------------------------------------------------------- /x86/bpf/demo_kern.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | /* 10 | * /sys/kernel/debug/tracing/events/syscalls/sys_enter_execve 11 | * 通过监控内核中系统调用execve 12 | * 当系统中调用了这个系统调用的话就会调用mybpfprog函数 13 | * 14 | * 编译好程序后执行./demo 15 | * 16 | * 然后打开一个新终端,输入一些命令即可看到结果 17 | */ 18 | SEC("tracepoint/syscalls/sys_enter_execve") 19 | int mybpfprog(struct pt_regs *ctx) 20 | { 21 | char msg[] = "Hello, BPF World!"; 22 | 23 | bpf_trace_printk(msg, sizeof(msg)); 24 | 25 | return 0; 26 | } 27 | 28 | char _license[] SEC("license") = "GPL"; 29 | u32 _version SEC("version") = LINUX_VERSION_CODE; 30 | -------------------------------------------------------------------------------- /x86/bpf/demo_user.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include "trace_helpers.h" 11 | 12 | int main(int argc, char *argv[]) 13 | { 14 | struct bpf_link *link = NULL; 15 | struct bpf_program *prog; 16 | struct bpf_object *obj; 17 | char filename[256]; 18 | 19 | snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); 20 | obj = bpf_object__open_file(filename, NULL); 21 | if (libbpf_get_error(obj)) { 22 | fprintf(stderr, "ERROR: opening BPF object file failed\n"); 23 | return 0; 24 | } 25 | 26 | prog = bpf_object__find_program_by_name(obj, "mybpfprog"); 27 | if (!prog) { 28 | printf("finding a prog in obj file failed\n"); 29 | goto cleanup; 30 | } 31 | 32 | /* load BPF program */ 33 | if (bpf_object__load(obj)) { 34 | fprintf(stderr, "ERROR: loading BPF object file failed\n"); 35 | goto cleanup; 36 | } 37 | 38 | link = bpf_program__attach(prog); 39 | if (libbpf_get_error(link)) { 40 | fprintf(stderr, "ERROR: bpf_program__attach failed\n"); 41 | link = NULL; 42 | goto cleanup; 43 | } 44 | 45 | read_trace_pipe(); 46 | 47 | cleanup: 48 | bpf_link__destroy(link); 49 | bpf_object__close(obj); 50 | return 0; 51 | } 52 | -------------------------------------------------------------------------------- /x86/bpf/trace_helpers.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include "trace_helpers.h" 13 | 14 | #define DEBUGFS "/sys/kernel/debug/tracing/" 15 | 16 | #define MAX_SYMS 300000 17 | static struct ksym syms[MAX_SYMS]; 18 | static int sym_cnt; 19 | 20 | static int ksym_cmp(const void *p1, const void *p2) 21 | { 22 | return ((struct ksym *)p1)->addr - ((struct ksym *)p2)->addr; 23 | } 24 | 25 | int load_kallsyms(void) 26 | { 27 | FILE *f = fopen("/proc/kallsyms", "r"); 28 | char func[256], buf[256]; 29 | char symbol; 30 | void *addr; 31 | int i = 0; 32 | 33 | if (!f) 34 | return -ENOENT; 35 | 36 | while (fgets(buf, sizeof(buf), f)) { 37 | if (sscanf(buf, "%p %c %s", &addr, &symbol, func) != 3) 38 | break; 39 | if (!addr) 40 | continue; 41 | syms[i].addr = (long) addr; 42 | syms[i].name = strdup(func); 43 | i++; 44 | } 45 | fclose(f); 46 | sym_cnt = i; 47 | qsort(syms, sym_cnt, sizeof(struct ksym), ksym_cmp); 48 | return 0; 49 | } 50 | 51 | struct ksym *ksym_search(long key) 52 | { 53 | int start = 0, end = sym_cnt; 54 | int result; 55 | 56 | /* kallsyms not loaded. return NULL */ 57 | if (sym_cnt <= 0) 58 | return NULL; 59 | 60 | while (start < end) { 61 | size_t mid = start + (end - start) / 2; 62 | 63 | result = key - syms[mid].addr; 64 | if (result < 0) 65 | end = mid; 66 | else if (result > 0) 67 | start = mid + 1; 68 | else 69 | return &syms[mid]; 70 | } 71 | 72 | if (start >= 1 && syms[start - 1].addr < key && 73 | key < syms[start].addr) 74 | /* valid ksym */ 75 | return &syms[start - 1]; 76 | 77 | /* out of range. return _stext */ 78 | return &syms[0]; 79 | } 80 | 81 | long ksym_get_addr(const char *name) 82 | { 83 | int i; 84 | 85 | for (i = 0; i < sym_cnt; i++) { 86 | if (strcmp(syms[i].name, name) == 0) 87 | return syms[i].addr; 88 | } 89 | 90 | return 0; 91 | } 92 | 93 | /* open kallsyms and read symbol addresses on the fly. Without caching all symbols, 94 | * this is faster than load + find. 95 | */ 96 | int kallsyms_find(const char *sym, unsigned long long *addr) 97 | { 98 | char type, name[500]; 99 | unsigned long long value; 100 | int err = 0; 101 | FILE *f; 102 | 103 | f = fopen("/proc/kallsyms", "r"); 104 | if (!f) 105 | return -EINVAL; 106 | 107 | while (fscanf(f, "%llx %c %499s%*[^\n]\n", &value, &type, name) > 0) { 108 | if (strcmp(name, sym) == 0) { 109 | *addr = value; 110 | goto out; 111 | } 112 | } 113 | err = -ENOENT; 114 | 115 | out: 116 | fclose(f); 117 | return err; 118 | } 119 | 120 | void read_trace_pipe(void) 121 | { 122 | int trace_fd; 123 | 124 | trace_fd = open(DEBUGFS "trace_pipe", O_RDONLY, 0); 125 | if (trace_fd < 0) 126 | return; 127 | 128 | while (1) { 129 | static char buf[4096]; 130 | ssize_t sz; 131 | 132 | sz = read(trace_fd, buf, sizeof(buf) - 1); 133 | if (sz > 0) { 134 | buf[sz] = 0; 135 | puts(buf); 136 | } 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /x86/bpf/vmexit_kern.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | /* 10 | * 自定义一个hash类型的bpfmap 11 | * 用进程pid作为key 12 | * 每个进程的vmexit次数作为value 13 | */ 14 | struct { 15 | __uint(type, BPF_MAP_TYPE_HASH); 16 | __type(key, int); 17 | __type(value, int); 18 | __uint(max_entries, 1000); 19 | } my_map SEC(".maps"); 20 | 21 | SEC("tracepoint/kvm/kvm_exit") 22 | int mybpfprog(struct pt_regs *ctx) 23 | { 24 | int *value; 25 | int exit_count = 0; 26 | char fmt[] = "pid: %d %d %d\n"; 27 | int pid; 28 | 29 | pid = bpf_get_current_pid_tgid(); 30 | 31 | /* 用pid这个作为key在bpfmap里查找对应的value */ 32 | value = bpf_map_lookup_elem(&my_map, &pid); 33 | if (value) 34 | { 35 | /* increse vmexit in each call */ 36 | exit_count = ++(*value); 37 | bpf_trace_printk(fmt, sizeof(fmt), pid, exit_count, *value); 38 | } 39 | 40 | /* 将pid作为key, exit_count作为value进行更新bpfmap */ 41 | bpf_map_update_elem(&my_map, &pid, &exit_count, BPF_ANY); 42 | 43 | return 0; 44 | } 45 | 46 | char _license[] SEC("license") = "GPL"; 47 | u32 _version SEC("version") = LINUX_VERSION_CODE; 48 | -------------------------------------------------------------------------------- /x86/bpf/vmexit_user.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include "trace_helpers.h" 11 | 12 | #define NR_VCPU 4 13 | 14 | #define ITERAT_ALL 15 | 16 | int main(int argc, char *argv[]) 17 | { 18 | struct bpf_link *link = NULL; 19 | struct bpf_program *prog; 20 | struct bpf_object *obj; 21 | char filename[256]; 22 | int fd; 23 | int cur; 24 | #ifdef ITERAT_ALL 25 | int next_key, lookup_key; 26 | #else 27 | /* 28 | * pstree can print out each vcpu thread id 29 | * pstree -t -p `vminfo -n demo-3 -p` 30 | * qemu-system-x86(3286)─┬─{CPU 0/KVM}(3345) 31 | * ├─{CPU 1/KVM}(3355) 32 | * ├─{CPU 2/KVM}(3366) 33 | * ├─{CPU 3/KVM}(3373) 34 | */ 35 | int pids[NR_VCPU] = {3345, 3355, 3366, 3373}; 36 | int prev[NR_VCPU] = {0, 0, 0, 0}; 37 | int sum = 0, delta = 0; 38 | int i; 39 | #endif 40 | 41 | snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); 42 | obj = bpf_object__open_file(filename, NULL); 43 | if (libbpf_get_error(obj)) { 44 | fprintf(stderr, "ERROR: opening BPF object file failed\n"); 45 | return 0; 46 | } 47 | 48 | prog = bpf_object__find_program_by_name(obj, "mybpfprog"); 49 | if (!prog) { 50 | printf("finding a prog in obj file failed\n"); 51 | goto cleanup; 52 | } 53 | 54 | /* load BPF program */ 55 | if (bpf_object__load(obj)) { 56 | fprintf(stderr, "ERROR: loading BPF object file failed\n"); 57 | goto cleanup; 58 | } 59 | 60 | link = bpf_program__attach(prog); 61 | if (libbpf_get_error(link)) { 62 | fprintf(stderr, "ERROR: bpf_program__attach failed\n"); 63 | link = NULL; 64 | goto cleanup; 65 | } 66 | 67 | /* 68 | * iterating over elements in a BPF Map 69 | * 70 | * use `bpf_map_get_next_key` with a lookup key that doesn't exist in the map 71 | * This forces BPF to start from the beginning of the map 72 | */ 73 | #if 1 74 | fd = bpf_object__find_map_fd_by_name(obj, "my_map"); 75 | while (1) 76 | { 77 | #ifdef ITERAT_ALL 78 | lookup_key = -1; /* key not exsit in map */ 79 | while (bpf_map_get_next_key(fd, &lookup_key, &next_key) == 0) 80 | { 81 | bpf_map_lookup_elem(fd, &lookup_key, &cur); 82 | lookup_key = next_key; 83 | printf("%d:%d\n", lookup_key, cur); 84 | } 85 | #else 86 | for (i = 0; i < NR_VCPU; i++) 87 | { 88 | bpf_map_lookup_elem(fd, &pids[i], &cur); 89 | delta = cur - prev[i]; 90 | sum += delta; 91 | prev[i] = cur; 92 | } 93 | printf("vmexit total: %d\n", sum); 94 | sum = 0; 95 | #endif 96 | sleep(1); 97 | } 98 | #else 99 | read_trace_pipe(); 100 | #endif 101 | 102 | cleanup: 103 | bpf_link__destroy(link); 104 | bpf_object__close(obj); 105 | return 0; 106 | } 107 | -------------------------------------------------------------------------------- /x86/crypto/Makefile: -------------------------------------------------------------------------------- 1 | # Add your debugging flag (or not) to CFLAGS 2 | ifeq ($(DEBUG),y) 3 | DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines 4 | else 5 | DEBFLAGS = -O2 6 | endif 7 | 8 | obj-m := crypto-drv.o 9 | KERNELDIR ?= /usr/src/linux 10 | CC ?= gcc 11 | PWD := $(shell pwd) 12 | 13 | modules: 14 | $(MAKE) -C $(KERNELDIR) M=$(PWD) modules 15 | 16 | clean: 17 | rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions modules.order Module.symvers 18 | 19 | depend .depend dep: 20 | $(CC) $(CFLAGS) -M *.c > .depend 21 | 22 | ifeq (.depend,$(wildcard .depend)) 23 | include .depend 24 | endif 25 | -------------------------------------------------------------------------------- /x86/crypto/README.md: -------------------------------------------------------------------------------- 1 | # qemu中虚拟设备实现 2 | 3 | 参考书:How to Develop Embedded Software Using The QEMU Machine Emulator.pdf 4 | 5 | ## 设备和驱动对应的代码(环境参考huc) 6 | 7 | crypto.c : virtual device in qemu 8 | crypto-drv.c : driver for crypto 9 | Run qemu in ubuntu 22.04 host 10 | 11 | ## 代码准备 12 | 13 | ### 将设备添加到qemu中 14 | 15 | Compile and run qemu 16 | 17 | git clone -b huc git@gitee.com:zeroway/qemu.git 18 | git submodule init 19 | git submodule sync 20 | git submodule update 21 | 22 | drun -v /data/qemu:/code qemudev 23 | 24 | /usr/local/bin/qemu-system-x86_64 \ 25 | -drive file=/root/huc.qcow2 \ 26 | -smp 2 -m 1024 -enable-kvm \ 27 | -device e1000,netdev=ssh \ 28 | -display none \ 29 | -serial mon:stdio \ 30 | -vnc 0.0.0.0:0 \ 31 | -device pci-crypto,aes_cbc_256="abc" \ 32 | -device pci-hellodev \ 33 | -device virtio-mini,disable-legacy=on \ 34 | -netdev user,id=ssh,hostfwd=tcp::2222-:22 35 | 36 | ### 编译对应的设备驱动(guest using ubuntu 20.04 kernel 5.4) 37 | 38 | cd ${HOME}/src/linux 39 | git checkout v5.4 -b v5p4 40 | docker run --rm -it --privileged \ 41 | -v ${PWD}:/code \ 42 | -v ${HOME}/src/linux:/usr/src/linux bpf2004 make 43 | 44 | ## 调试 45 | 46 | ### PCI寄存器的查看和修改(使用setpci) 47 | 48 | 进系统后查看pci设备寄存器(通用) 49 | 50 | setpci --dumpregs 51 | 52 | 00 W VENDOR_ID 53 | 02 W DEVICE_ID 54 | 04 W COMMAND 55 | 06 W STATUS 56 | 08 B REVISION 57 | 09 B CLASS_PROG 58 | ... 59 | 10 L BASE_ADDRESS_0 60 | 61 | 用lspci -n 找到对应设备的BDF值(在驱动中定义了vendorId 0x2222, deviceId 0x1111) 62 | 63 | 00:03.0 00ff: 1111:2222 64 | 65 | 查看设备对应寄存器的值(比如查看VENDOR_ID, 由dumpregs可知寄存器偏移量为00) 66 | 67 | setpci -s 00:03.0 00.w 68 | 69 | 再比如查看device id 70 | 71 | setpci -s 00:03.0 02.w 72 | 73 | 查看设备的bar0的地址 74 | 75 | setpci -s 00:03.0 10.l 76 | 77 | 或者使用lspci查看(下面的0xfebf1000就是bar0地址, 即mmio的地址) 78 | 79 | lspci -vvvv -xxxx -s 00:03.0 80 | Region 0: Memory at febf1000 (32-bit, non-prefetchable) [size=4K] 81 | 82 | 或者通过qemu monitor查看也能查看到该地址 83 | 84 | (qemu) info qtree 85 | (qemu) info mtree 86 | 87 | ### 使用[devmem](https://github.com/VCTLabs/devmem2)工具来调试 88 | 89 | 编译工具 90 | 91 | gcc devmem2.c -o devmem 92 | 93 | 下面命令会调用到mmio的read函数 94 | 95 | ./devmem 0xfebf1000 b 96 | ./devmem 0xfebf1000 w 97 | ./devmem 0xfebf1000 l 98 | 99 | 写mmio空间的第二个地址0xfebf1000 + 2,命令是1:对应的是reset 100 | 101 | ./devmem 0xfebf1002 b 1 102 | 103 | Encrypt:命令是2 104 | 105 | ./devmem 0xfebf1002 b 2 106 | 107 | Decrypt:命令是3 108 | 109 | ./devmem 0xfebf1002 b 3 110 | 111 | Enable interrupt 112 | 113 | ./devmem 0xfebf1003 b 2 114 | 115 | Disable interrupt 116 | 117 | ./devmem 0xfebf1003 b 0 118 | 119 | ### 其它信息查看 120 | 121 | 查看设备对应的io空间 122 | 123 | grep mycrypto /proc/iomem 124 | febf1000-febf1fff : mycrypto 125 | 126 | 查看驱动对应的符号表 127 | 128 | grep crypto_drv /proc/kallsyms 129 | -------------------------------------------------------------------------------- /x86/hlist/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile 2 | # Comment/uncomment the following line to disable/enable debugging 3 | # DEBUG = y 4 | 5 | # Usage 6 | # make CROSS_COMPILE= KERNEL_DIR= KERNEL_BUID_OUTPUT= 7 | # 8 | # make CROSS_COMPILE=/home/zeroway/rk3399/tool/gcc-linaro-4.9.4-2017.01-i686_aarch64-linux-gnu/bin/aarch64-linux-gnu- KERNEL_DIR=/home/zeroway/rk3399/src/firefly/kernel KERNEL_BUID_OUTPUT=/home/zeroway/rk3399/src/firefly/out/target/product/rk3399_firefly_box/obj/KERNEL 9 | 10 | # Add your debugging flag (or not) to CFLAGS 11 | ifeq ($(DEBUG),y) 12 | DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines 13 | else 14 | DEBFLAGS = -O2 15 | endif 16 | 17 | obj-m := demo.o 18 | 19 | KERNEL_DIR ?= /lib/modules/`uname -r`/build 20 | KERNEL_BUID_OUTPUT ?=$(KERNEL_DIR) 21 | CC = $(CROSS_COMPILE)gcc 22 | LD = $(CROSS_COMPILE)ld 23 | PWD := $(shell pwd) 24 | ARCH := x86_64 25 | 26 | modules: 27 | $(MAKE) -C $(KERNEL_DIR) ARCH=$(ARCH) M=$(PWD) O=$(KERNEL_DIR) modules 28 | 29 | clean: 30 | rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions modules.order Module.symvers *.mod 31 | 32 | depend .depend dep: 33 | $(CC) $(CFLAGS) -M *.c > .depend 34 | 35 | ifeq (.depend,$(wildcard .depend)) 36 | include .depend 37 | endif 38 | -------------------------------------------------------------------------------- /x86/hlist/demo.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | /* refercence with kernel module zd1201 */ 7 | /* https://zhuanlan.zhihu.com/p/82375193 */ 8 | struct AAAAA { 9 | /* hash table implement in list address */ 10 | struct hlist_head nodelist; 11 | }; 12 | 13 | struct AAAAA_node { 14 | struct hlist_node fnode; 15 | char name[20]; 16 | }; 17 | 18 | struct AAAAA *module5a; 19 | static int hlist_test_init(void) 20 | { 21 | struct AAAAA_node *node1; 22 | struct AAAAA_node *node2; 23 | struct AAAAA_node *pos; 24 | 25 | /* another hlist_node to use as temporary storage */ 26 | struct hlist_node *tmp_node; 27 | 28 | module5a = kmalloc(sizeof(struct AAAAA), GFP_ATOMIC); 29 | if (!module5a) 30 | return -1; 31 | 32 | node1 = kmalloc(sizeof(*node1), GFP_ATOMIC); 33 | if (!node1) 34 | return -1; 35 | strcpy(node1->name, "Node1"); 36 | 37 | node2 = kmalloc(sizeof(*node2), GFP_ATOMIC); 38 | if (!node2) 39 | return -1; 40 | strcpy(node2->name, "Node2"); 41 | 42 | /* init hash table */ 43 | INIT_HLIST_HEAD(&module5a->nodelist); 44 | 45 | /* add node to hash table */ 46 | hlist_add_head(&node1->fnode, &module5a->nodelist); 47 | hlist_add_head(&node2->fnode, &module5a->nodelist); 48 | 49 | hlist_for_each_entry_safe(pos, tmp_node, &module5a->nodelist, fnode) { 50 | printk(KERN_ALERT"Iter node : %s\n", pos->name); 51 | } 52 | 53 | return 0; 54 | } 55 | 56 | static void hlist_test_exit(void) 57 | { 58 | struct AAAAA_node *pos; 59 | struct hlist_node *tmp_node; 60 | 61 | hlist_for_each_entry_safe(pos, tmp_node, &module5a->nodelist, fnode) { 62 | printk(KERN_ALERT"Delete node : %s\n", pos->name); 63 | hlist_del_init(&pos->fnode); 64 | kfree(pos); 65 | } 66 | kfree(module5a); 67 | } 68 | 69 | MODULE_LICENSE("Dual BSD/GPL"); 70 | module_init(hlist_test_init); 71 | module_exit(hlist_test_exit); 72 | -------------------------------------------------------------------------------- /x86/usb/comp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/x86/usb/comp.png -------------------------------------------------------------------------------- /x86/usb/mouse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/x86/usb/mouse.png -------------------------------------------------------------------------------- /x86/usb/rd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/x86/usb/rd.png -------------------------------------------------------------------------------- /x86/usb/reportid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/x86/usb/reportid.png -------------------------------------------------------------------------------- /x86/usb/rid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/x86/usb/rid.png -------------------------------------------------------------------------------- /x86/usb/send0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/x86/usb/send0.png -------------------------------------------------------------------------------- /x86/usb/send3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/x86/usb/send3.png -------------------------------------------------------------------------------- /x86/usb/sr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/x86/usb/sr.png -------------------------------------------------------------------------------- /x86/usb/srr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/54shady/kernel_drivers_examples/d1d8d3bfbfb73bba835e2d919e38b9aa9ecbe56a/x86/usb/srr.png --------------------------------------------------------------------------------