Seventh chapter LED will blink for me: Control the Light emitting diode

Source: Internet
Author: User

The Linux driver is used to control the 4 LEDs on the Development Board, which means that the LEDs can be controlled by sending data to the Linux driver. LED drivers offer two ways to interact: command and read and write device files.

Connect the Development board with a USB cable before testing the LED driver and open the Development Board. After successful startup, execute the build.sh script file to compile and install the LED driver. The build.sh script file automatically uploads the S3c6410_leds.ko file to the Development Board and installs it. LED drivers can only be installed on the Development Board, BUILD.SH executes the build_s3c6410.sh script file for compilation and installation. The LED driver creates a/dev/s3c6410_leds device file that controls 4 LEDs, and the 4 LEDs can be controlled by sending a string of 1 to 4 to the device file. 1 means open, 0 is off. The string length is less than 4, which is equivalent to 0 of the following. Execute command

"# adb Shell" echo ' 1 ' >/dev/s3c6410_leds "#打开第一个LED, others are off

# adb Shell "Echo ' 1010 ' >/dev/s3c6410_leds" #第一个和第三个LED打开, second and fourth off

# adb Shell "echo ' 1111 ' >/dev/s3c6410_leds" #打开所有的LED "controls the LEDs on the Development Board. You can use the command "# sh ~/drivers/s3c6410_leds/test_leds.sh" to perform test_leds.sh script file test LEDs. After executing the script file, the 4 LEDs on the board will control the LEDs according to the binary form of 0 to 15, the first one being the lowest bit. The script file uses the standard bash Shell, which cannot be executed successfully under Ubuntu because it takes dash as the default script parser. You can use the command "# dpkg-reconfigure Dash" To change the default script parser to bash, when the Settings screen appears, select "No" and then enter.

Create LED-driven device files as follows; 1. Describing device files requires the use of a cdev struct, which is defined in the <linux kernel source code >/include/linux/cdev.h file. Most of these member variables can be initialized by simply calling Cdev_init (), which is in the <linux kernel source code >/fs/char_dev.c file. To create multiple device files in a Linux drive, the value of the Cdev.count variable is the number of device files to be established. The corresponding Cdev structures of these device files are connected by Cdev.list.prev and Cdev.list.next pointer variables to form a doubly linked list. The Cdev.owner variable is not initialized in the Cdev.init function, using the statement "Leds_cdev.owner=this_module;" To initialize 2. The device number of the Linux device file is the primary device number and the secondary device number. represented by an int type, where the first 12 bits represent the main device number, and the last 20 bits represent the secondary device number. There are two ways to specify a device number: Specify it directly in your code and assign it dynamically. The first method is more intuitive, but if the main device number and the secondary device number already exist, the setup file will fail. Just in case, you can use Alloc_chrdev_region () to automatically assign an unused master device number. The customary secondary device number is set to 0. The function prototype is int alloc_chrdev_region (dev_t*dev,unsigned baseminor,unsigned count,const char *name), where Dev represents the device number pointer, The function randomly assigns an unused master device number and assigns the secondary device number according to the Baseminor parameter value. Count represents the assigned secondary device number range. Name indicates the device file name. Multiple Linux device files can have the same main device number, but the primary and secondary device numbers for two devices cannot be the same. When using a function to automatically assign a device number, the Baseminor and count parameters are not set too large, or the secondary device number will overflow, and the main device number will be rounded up to become the next main device number. To specify the device number directly, use Register_chrdev_region () to register the character device area, which is implemented in the <linux kernel source code >/fs/char_dev.c file, with the following prototype: int Register_chrdev _region (dev_t from,unsigned count,const char *name), from represents the device number, count indicates the secondary device number range, nameRepresents the device file name. You typically specify the device number by specifying the main device number and the secondary device number separately, requiring the MKDEV macro to combine the main device number and the secondary device number into the device number-"int dev_number=mkdev (Major,minor);". You can also use the major and minor macros to get the main device number and the secondary device number from the device number, the code is: "int major=major (dev_number); int minor=major (dev_number); " 3.cdev_add () is used to add a character device to the probes array. The function is implemented in the <linux kernel source code >/fs/char_dev.c file, and the prototype is

"Int cdev_add (struct Cdev *p,dev_t dev,unsigned count) {

p->dev=dev;

p->count=count;

Return Kobj_map (CDEV_MAP,DEV,COUNT,NULL,EXACT_MATCH,EXACT_LOCK,P);

} ", call this function to specify the device file pointer p, the device number dev, and the number of device files count. This function also calls an important function, Kobj_map, which is responsible for adding information about the device file to the probes array that holds the established device files. The Kobj_map () and probes arrays are in the <linux kernel source >/drivers/base/map.c file, 4.struct class contains some variables related to device files and some callback function pointer variables, using CLASS_ The Create macro creates a struct class with the code

"Struct class *leds_class=null;

Leds_class=class_create (This_module, "Dev_name"); ", Dev_name is the device file name. The Class_create macro actually uses _class_create () to create the struct class. This function is implemented in the <linux kernel source code >/drivers/base/class.c file 5.device_create () is used to create the device file, which is <linux the kernel source code >/include/linux The/device.h file is defined in the <linux kernel source code >/drivers/base/core.c file. You can use the Code "device_create (leds_class,null,dev_number,null,device_name);" Call Device_create () to create a device file where Leds_class represents a struct class,dev_number represents a device number and device_name represents the name of the device file. When writing Leds_create_device (), it should be understood that the second parameter of ①device_count indicates the number of device files established ②alloc_chrdev_region () represents the starting device number assigned. If the value of the third parameter is greater than 1, the function assigns the secondary device number ③ to create the device file using the automatic assignment of the device number, and the major and minor macros are recommended to get the main device number and the secondary device number, respectively, in the major and minor variables. In case the device number used to ④led drive is saved in the Dev_number variable, assign the value of the Leds_cdev.dev variable to the Dev_number variable. Leds_init () is an initialization function of the LED driver that calls Leds_create_device () directly in the function. If the s3c6410_leds_major is set to 0, the system automatically assigns an unused master device number, and the secondary device number is still 10. The main device number may be different each time the LED driver is loaded, but the secondary device number is always 10.

Uninstalling the LED-driven device files: The unload operation is slightly simpler, calling Device_destroy, Class_destroy, and Unregister_chrdev_region () in turn. Leds_destroy_device () is used to uninstall the LED driver's device file, Leds_exit () is the LED driver unloading function, which is done by calling Leds_destroy_device () to complete the uninstallation of the LED drive device files.

Set register and initialize LED driver: ARM processor has multiple registers, by setting the values of different registers. You can set the status of the LED pins, turn on or off the pull-up circuitry, and control the light and off of the LEDs. What we must know is: The ①led has two pins: GPB0 and GPB1, one of which is connected to the GPI0 port of the ARM processor, and the other pin is connected to the power VCC3 by a current-limiting resistor. When the GPI0 port is low, the LEDs produce a voltage difference at both ends, and the LEDs have current through the glow, whereas when the GPI0 port is high, there is no current in the LED and the lamp goes out. Switching between high and low levels is very fast, led on a certain delay between the ② control led needs to be completed through 3 registers, Gpmcon port configuration register, gpmdat port data register and Gpmpud Port pull-up circuit register ③ each register can use 4 bytes, That is, the space used by an int type of data ④ the two ports GPB0, GPB1 of the LEDs with the lower 16 bits of the Gpmcon register to output. A total of 4 LEDs are set for each 4-bit led. The value of output is 0001, and if hexadecimal is used, the low 16-bit value of the register is 0x1111⑤, which uses the low 4-bit gpmdat register to control the light and off of 4 LEDs. Each one controls an LED, and the lowest bit controls the nearest led from the battery. 0 indicates bright, 1 means that the ⑥ uses the low 8 bits of the GPMPUD register to turn on the 4 LEDs of the pull-up circuit respectively. Each of the two control the pull-up circuit of an LED. 10 to open the pull-up circuit. With Hex, the low 8 bits of the GPMPUD register are 0xAA to open the 4 led pull-up circuitry at the same time. The above 3 registers have a virtual address in memory. When the data is written to these addresses, the ARM processor uses a set of algorithms to map the virtual address to a physical address, and writes the data to the appropriate hardware port based on the physical address. The virtual addresses of gpmcom, Gpmdat, and Gpmpud in the ARM processor use macro definitions in the Linux kernel. To keep track of these macros, add two additional include paths:/root/kernel/linux_kernel_2.6.36/arch/arm/mach-s3c64xx/include and/root/kernel/linux_ Kernel_2.6.36/arch/arm/plat-samsung/include. The virtual addresses for these three registers are S3c64xx_gpmcon, S3c64xx_gpmpud, S3c64xx_gpmdat, respectively. The three macros involved 4 header files with a total of 9 macros. The value of the s3c64xx_gpm_base that can be rolled out is 0xf04500820,gpmcon, Gpmdat and Gpmpud registers are 0xf04500820, 0xf04500824, and 0xf04500828, respectively, and these three virtual addresses are fixed and can write data to these three addresses. It is better to use S3c64xx_gpmcon, S3c64xx_gpmpud, S3c64xx_gpmdat to operate these 3 addresses. It is generally necessary to initialize the above 3 registers when the LED driver is loaded. The initialization of the Register can be done as long as the LEDS_INIT_GPM () is called in Leds_init ().

The control led:led driver can control LEDs in two ways: through string control LEDs and through I/O commands. To control LEDs in either of these ways, the driver must receive the appropriate data. If you are using a string to control LEDs, you need to use File_operations.write () to receive data written to the device file. If controlled by the I/O command, File_operations.ioctl () is used to receive commands and parameters sent to the character device. S3c6410_leds_write () is used to receive data to the LED driver to write the control led to the device file, in the implementation of its functions to write code to understand: ① 4 LEDs for the light off with a 4-length mem array. 1 indicates that a lit led,0 indicates an off led. The meaning of the low 4-bit representation of the Gpmdat register is exactly the opposite of the ② if the string length written is less than or equal to 4, the string is written directly. If the length is greater than 4, only the first 4 strings are written. S3c6410_leds_write () to return the length of the string passed in the function, otherwise the system calls multiple times the function writes the string ③ the prior mem array has been zeroed, to write a string that is less than 4 long, is equivalent to the following characters are ④ to the Gpmdat register before writing to the data is best to read the current value of the Gpmdat register, and through the bitwise and, or the operation to retain the value unrelated to this operation ⑤ioread32, iowrite32 for reading and writing the virtual address of the 32-bit data. Using commands

"# adb Shell ' echo 1101 >/dev/s3c6410_leds '

# adb Shell ' echo 1 >/dev/s3c6410_leds ' "Can control the light and off of LEDs via a string. The I/o command cannot be tested using the command line method.

LED Driver Module parameters: If you want to specify a default state value when loading the LED driver, use the module parameter. Specifying a module parameter for the Linux driver requires the use of the Module_param (NAME,TYPE,PERM) macro. The name represents the parameter name, type represents the parameter types, and perm represents read/write permissions. The types of parameters supported by Module_param include Byte, short, ushort, int, uint, long, charp, bool, and Invbool. When you use the Module_param macro to specify a module parameter, you generate and drive a directory with the same name as the device file in the/sys/module directory. If a parameter is not specified when loading a Linux drive, the contents of the parameter file are the default values specified by this parameter in the Linux drive source code. The Module_param macro allows you to specify access permissions for the parameter file. S_irugo means that all users can access the contents of the parameter file, but cannot modify it. s_irugo| S_iwusr means that all users are allowed to read, and the user who created the file is written. The Linux kernel also provides more macros that define access rights. S_irwxugo means that all users can read, write, and execute files. Iwugo indicates that all users have write access to the file. The LED driver code needs to be modified to add a module parameter for the LED driver, which stores the initial state of 4 LEDs with the parameter type int. Parameter values range from 0 to 15. The rule of the parameter value control LEDs is the same as the rule for the Gpmdat register low 4-bit control LEDs. Adding module parameters to the LED driver first define a variable that holds the parameter values of the module, and then use the Module_param macro to specify information about the module parameters. Finally, modify the Leds_init () code to change the parameter value of LEDS_INIT_GPM () to ~leds_state. Use the command "# adb shell Insmod/data/local/s3c6410_leds.ko leds_state=3" to test the module parameters of the LED driver. After executing the command, a leds_state file is generated in the/sys/module/s3c6410_leds/parameters directory, using the command

"# adb shell cat/sys/module/s3c6410_leds/parameters/leds_state" can see the file content is 3. Use the command "# adb shell ' echo 5 >/sys/module/s3c6410_leds/parameters/leds_state '" To change the file contents to 5. After modifying the contents of the Leds_state file, the value of the leds_state variable in the LED driver code becomes 5. The Linux driver writes the specified parameter value to the parameter file when it is loaded, and if no parameter value is specified, the Linux driver writes the default value of the parameter to the parameter file. During the Linux driver operation, the parameter values are synchronized with the contents of the parameter file. Use the Module_param_array (NAME,TYPE,NUMP,PERM) macro to specify module parameters in the form of arrays for Linux drivers. Nump represents a pointer to a variable that stores the length of an array, and perm represents the access rights for the parameter file. The params parameter value can be specified by command "# adb shell Insmod/data/local/s3c6410_leds.ko ' leds_state=11 param=str1,str2,str3 '". If the params parameter specifies a value that is less than the array length, the following array element uses the default value. If it is larger than the array length, the LED driver fails to load and outputs information in the log. Use module parameters Note: ① uses pointer-type data when specifying the array length through the 3rd parameter of the Module_param_array macro ② if the Linux driver contains multiple module parameters, enclose them in single or double quotation marks ③ the parameter values of the specified array type. You cannot have spaces before commas.

Seventh chapter LED will blink for me: Control the Light emitting diode

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.