S3C2440 development board practice (10): signal & async asynchronous communication

Publisher:静逸心境Latest update time:2022-07-15 Source: csdnKeywords:S3C2440 Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

Sending signals between processes

Here we use the kill command to transmit signals between processes.

For example, killing a process is also done by sending signals between processes:


#kill -9 pid

Correspondingly, if you want to send a signal, you need to register a signal processing function (similar to registering an interrupt service function), write a signal service function, and then write a function that sleeps all the time. The application signal.c code is as follows:


#include

#include


void mysignal_fun(int signum){

    static int count = 0;

    printf("signal = %d, %d timesn", signum, count++);

}


int main(int argc, char **argv){

    signal(SIGUSR1, mysignal_fun);// input: "kill -10(-USR1) pid" 

    while(1)        

        sleep(1000);

    return 0;

}


After running in the background through "&", use the process kill to pass the signal running in the background.


#ps //Get PID

#kill -USR1 signal_pid //pid obtained from ps      


From the above, we can see that in this method, we still have to manually obtain the pid number. In subsequent experiments, we will use functions to obtain the pid number.

The running results are:


# kill -USR1 752

signal = 10, 0 times

# kill -USR1 752

signal = 10, 1 times

# kill -10 752

signal = 10, 2 times

# kill -USR1 752

signal = 10, 3 times

# kill -10 752

signal = 10, 4 times


The driver sends a signal to the application

Key points:


Register signal function Use the signal function to register the signal processing function in the application.

Who sends the signal function sent from the driver

Which function is this signal sent to? It is sent to the app. The app needs to tell the driver pid

How to send kill_fasyn function

The driver notifies the application when a key is pressed


The method of sending signals from the driver to the application is similar to interrupts, and there are four problems:


Register signal function

Initialization signal function

The driver sends a signal function

This signal is sent by the driver to the application, that is, the application should tell the signal process PID number

Step 1: Register signal processing function

This step is to initialize the signal processing function through the signal() function, which is used to set the corresponding action for a certain signal. The declaration of the signal function is as follows:


#include

typedef void (*sighandler_t)(int);

sighandler_t signal(int signum, sighandler_t sig_handler);


The values ​​of signum are shown in the following table:

image.png

image.png

image.png

The handler describes the action associated with the signal and can take one of three values:

SIG_IGN This symbol means to ignore the signal. For example:

#include

#include

int main(int argc, char *argv[]){    

    signal(SIGINT, SIG_IGN);    

    while(1)

        sleep(1000);

    return 0;

}


The SIGINT signal is generated by InterruptKey, usually CTRL + C or DELETE. When executing the above code, the program does not respond when pressing CTRL + C. That's right, if we want to end the program, we can press CTRL + to end it. When we press the CTRL + key combination, a SIGQUIT signal is generated, and this signal is not ignored.


SIG_DFL This symbol indicates restoring the system default processing of the signal. If this processing function is not written, the system default operation will be executed by default. For example:

#include

#include

int main(int argc, char *argv[]){    

    signal(SIGINT, SIG_DFL);    

    while(1)

        sleep(1000);

    return 0;

}


At this time, you can press CTRL + C to terminate the process. Remove the sentence signal(SIGINT, SIG_DFL); and the effect is the same.


The sighandler_t type function pointer is our signal processing function. Following the above two examples:

#include

#include

typedef void (*signal_handler)(int); 

void signal_handler_fun(int signum) {

    printf("catch signal %dn", signum);

int main(int argc, char *argv[]) {

    signal(SIGINT, signal_hander_fun);

    while(1)

        sleep(1000);

    return 0;

}


In this way, we can execute a specific function when a signal comes. When ctrl+c is entered, the program will execute the signal processing function and output:


catch signal 2

Since asynchronous communication is used, the signal is selected as SIGIO, and the read operation is performed in the signal service function (although the printing of my key value is completed in the interrupt function, I just print a read here to go through the motions):


int fd;

void my_fasyn_signal_fun(int signum){

    unsigned char key_val;

    read(fd, &key_val, 1);

    printf("read!n");

}

int main(int argc, char **argv)

{

    signal(SIGIO, my_fasyn_signal_fun);    

    fd = open("/dev/buttons", O_RDWR);

    while(1)

        sleep(1000);

    return 0;

}


Step 2: Drive the signal sending function

The driver sends a SIGIO signal to the application via kill_fasync(&async, SIGIO, POLL_IN); and the application calls the response function installed by itself to handle it. async is a signal sequence structure, which needs to be defined and initialized (the initialization part is done in step 3, and it is assumed that it has been initialized here). POLL_IN means that data can be written.

Therefore, the modification of the driver program in the sending part is very simple. It only needs to communicate in the interrupt function:


static irqreturn_t button_irq(int irq, void *dev_id)

{

    struct pin_desc *pindesc = (struct pin_desc *)dev_id;

    key_val = ((*(pindesc -> key_Register)) & (1<<(pindesc -> key_pin))) ? 0 : 1;

    if(key_val){

    //    printk("%d", pindesc -> key_num);

    }     

    printk("%d  ",key_val);

    printk("%dn",pindesc->key_num);

    ev_press = 1; /* Indicates that an interrupt has occurred*/

    wake_up_interruptible(&button_waitq); /* wake up the sleeping process*/

    

    kill_fasync(&button_async_queue, SIGIO, POLL_IN);  // async signal to APP

 

    return IRQ_HANDLED;

}


step3: Initialization

This is the most important step in asynchronous communication.


Initialization consists of two parts:


Initialization of button_async_queue (pit in step 2)

You need to tell the kernel the PID of the application

In general, the following three lines of commands can summarize these two parts:


fcntl(fd, F_SETOWN, getpid()); // acquire the PID & tell kernal the PID

oflags = fcntl(fd, F_GETFL);   

fcntl(fd, F_SETFL, oflags | FASYNC); // change fasync_flag to call frv_fasync


The function of fcntl() is to operate the characteristics of the file according to the file descriptor. Its definition is as follows:


#include

#include  

int fcntl(int fd, int cmd); 

int fcntl(int fd, int cmd, long arg); 

int fcntl(int fd, int cmd, struct flock *lock);


fcntl() provides control over (file) descriptors. The parameter fd is the descriptor operated by the parameter cmd. fcntl can accept a third parameter int arg for the value of cmd.

The cmd value can be taken as the following macro definition:

image.png

Locking is an important function of fcntl! The asynchronous communication setting used here is just a flag to get the status of the setting file.


After understanding the fcntl function, it is not difficult to analyze the functions of these three lines, as shown in the following figure:

insert image description here

Initialization of button_async_queue


The definition of this structure is as follows:


static struct fasync_struct  *button_async_queue;

There is a special function in the kernel to initialize it: fasync_helper(). This function allocates memory and sets properties, and finally frees the things initialized by fasync_helper in the driver release.


From the above analysis, the drv_fasync() function in the driver will be called during initialization, so the initialization operation of button_async_queue is performed in this function. It corresponds to the .fasync in the file structure, so the driver file is rewritten as follows:


int button_drv_fasync(struct file *fd, struct file *filp, int on){

    printk("dirver: Initialize fasyncn");

    return fasync_helper(fd, filp, on, &button_async_queue); // Initialize button_async_queue

}

static struct file_operations button_drv_fops = {

    .owner = THIS_MODULE, /* This is a macro that pushes to the __this_module variable that is automatically created when compiling the module*/

    .open    =   button_drv_open,     

    .read    =   button_drv_read,

    .release =   EINTkey_close,

    .poll    =   botton_drv_poll,

    .fasync  =   button_drv_fasync,

};


The driver sends a signal to the application.

driver

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

//#include

#include

#include

#include


#define DEV_NAME "button_drv"  // device name


static struct class *buttondrv_class;

static struct class_device    *buttondrv_class_dev;


static DECLARE_WAIT_QUEUE_HEAD(button_waitq);

/* Interrupt event flag, the interrupt service routine sets it to 1, and third_drv_read clears it to 0 */

static volatile int ev_press = 0;


/* Key value: when pressed, 0x01, 0x02, 0x03, 0x04 */

/* Key value: when released, 0x81, 0x82, 0x83, 0x84 */

static unsigned char key_val;


static struct fasync_struct  *button_async_queue;


volatile unsigned long *gpfcon = NULL;

volatile unsigned long *gpfdat = NULL;

volatile unsigned long *gpgcon = NULL;

volatile unsigned long *gpgdat = NULL;


struct pin_desc{

    volatile unsigned long *key_Register;

    int key_pin;

    int key_num;

};


struct pin_desc pins_desc[4] = {

    {0x01, 0,  1},

    {0x02, 2,  2},

    {0x03, 3,  3},

    {0x04, 11, 4},

};


static irqreturn_t button_irq(int irq, void *dev_id)

{

    struct pin_desc *pindesc = (struct pin_desc *)dev_id;

[1] [2]
Keywords:S3C2440 Reference address:S3C2440 development board practice (10): signal & async asynchronous communication

Previous article:S3C2440 development board practice (11): synchronization and mutual exclusion
Next article:S3C2440 development board practice (9): poll mechanism

Recommended ReadingLatest update time:2024-11-23 03:00

s3c2440 bare metal touch screen
1.0, Touch screen and LCD The touch screen and LCD are two independent screens, but there is a correspondence between them. Simply put, a coordinate point on the touch screen corresponds to a pixel point on the LCD. When we press the touch screen, the system calculates the coordinates of the location, and then finds
[Microcontroller]
S3c2440 code relocation details 4 --- copy code and link script improvements
This section improves the copy code and link script. When relocating previously, the ldrb command is required to read 1 byte of data from the Nor Flash, and then the strb command is used to write the 1 byte of data to the SDRAM. cpy:     ldrb r4, /*First read a byte from flash*/      strb r4, /*Write the data to S
[Microcontroller]
S3c2440 code relocation details 4 --- copy code and link script improvements
A brief discussion on the interrupt register and interrupt process of S3C2440
S3C2440 has a total of 60 interrupt sources, of which 15 are sub-interrupt sources, which correspond to each bit in the SUBSRCPND register, and the other 45 interrupt sources correspond to each bit in SRCPND. It should be noted that EINT4~7 correspond to the same bit SRCPND , and EINT8~23 also correspond to SRCPND .
[Microcontroller]
A brief discussion on the interrupt register and interrupt process of S3C2440
Memory Management Unit MMU
The Memory Management Unit (MMU) is responsible for mapping virtual addresses to physical addresses and provides hardware-based memory access permission checks. Modern multi-user, multi-process operating systems use MMU to allow each user process to have its own independent address space: the address mapping function
[Microcontroller]
Memory Management Unit MMU
uboot-2011.12 ported to S3C2440 (Sequence 1) - ELF executable file and its composition
We can divide executable files into two situations: storage state and running state 1. Storage state: The executable file is burned to the storage medium (flash or disk). At this time, the executable file usually consists of two parts, the code segment and the data segment. The code segment is divided into the executa
[Microcontroller]
S3C2440 transplantation uboot supports NANDFLASH operation
In the previous section, we transplanted uboot to support NORFLASH for S3C2440. In this section, we will continue transplanting to support NANDFLASH. Table of contents Compile error Copy s3c2410_nand.c and modify the macro definition to support SC32440 Modify NFCONF, NFCONT in s3c2440_nand.c to support S3C2440 Mod
[Microcontroller]
S3C2440 transplantation uboot supports NANDFLASH operation
The process of porting u-boot-2010.12.tar.bz2 version to s3c2440
1. tar decompression 2. Modify the cross-compilation in the makefile file in the root directory to arm-linux- 3. make distclean 4, make trab_bigflash_connect 5. Modify /uboot/include/config.h, add two macros such as CONFIG_SYS_SDRAM_BASE=0, if not add make will report an error, so add it accordin
[Microcontroller]
Design of LED backlight power saving system based on S3C2440
introduction Energy-saving and environmental protection technology is the focus of the world's current attention. In LCD display modules, the power consumption of the backlight can account for more than 50% of the total power consumption. Especially in display products below 10in, such as mobile phones, PDAs, MP3s and
[Power Management]
Design of LED backlight power saving system based on S3C2440
Latest Microcontroller Articles
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号