MCU multiple interrupt call sub-function

Publisher:科技徜徉Latest update time:2015-11-16 Source: eefocusKeywords:MCU Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere
1. Sub-functions can be called in interrupts.

2. Under normal circumstances, ensure that this sub-function (and the functions called by this sub-function) are not called by other functions.
3. If this sub-function does need to be called by other functions, make this sub-function a re-entrant function.
* All problems with calling sub-functions in interrupts are caused by the re-entrant function problem.

   In Keil  C, if you want to call other functions in an interrupt, it does not matter if this function is not called by other programs outside the interrupt. Otherwise, you need to set the called function to be reentrant. In this case, the function's entry and exit addresses and parameters are saved in the stack.

 

Function: Screen display positioning show_sit
******************************************/
void show_sit(uchar screen,uchar row,uchar x_sit,uchar y_sit)reentrant{

 select_screen(screen);
 set_line(row);
 set_page(x_sit);
 set_column(y_sit);

Note: reentrant Keyword

================The following comes from the Internet and I think it’s very good========================

Let me tell you the answer! 1. Reentrant functions
1) What is reentrancy?
Reentrant functions can be used concurrently by more than one task without worrying about data errors. In contrast, non-reentrant functions cannot be shared by more than one task unless mutual exclusion of the function is ensured (either by using semaphores or disabling interrupts in critical sections of the code). Reentrant functions can be interrupted at any time and resumed later without losing data. Reentrant functions either use local variables or protect their own data when using global variables.
2) Reentrant functions:
Do not hold static data for consecutive calls.
Do not return pointers to static data; all data is provided by the caller of the function.
Use local data or protect global data by making local copies of global data.
If you must access global variables, remember to use mutual exclusion semaphores to protect global variables.
Never call any non-reentrant functions.
3) Non-reentrant functions:
Static variables are used in the function, whether they are global static variables or local static variables.
The function returns static variables.
Non-reentrant functions are called in the function.
The function body uses static data structures;
the function body calls malloc() or free() functions;
the function body calls other standard I/O functions.
The function is a member function of a singleton and uses member variables that do not use thread-independent storage.
In general, if a function uses unprotected shared resources under reentrant conditions, it is not reentrant.
===============================================================

Mainly used in a multi-tasking environment, a reentrant function is simply a function that can be interrupted, that is, it can be interrupted at any time when it is executed, and transferred to the OS schedule to execute another section of code, and no errors will occur when returning control; non-reentrant functions use some system resources, such as the global variable area, interrupt vector table, etc., so if it is interrupted, problems may occur, and this type of function cannot run in a multi-tasking environment.

It can also be understood that reentry means repeated entry. First, it means that the function can be interrupted. Second, it means that it does not rely on any environment (including static) except for using the variables on its own stack. Such a function is purecode (pure code) reentrant, which allows multiple copies of the function to run. Since they use separate stacks, they will not interfere with each other. If you really need to access global variables (including static), you must pay attention to the implementation of mutual exclusion. Reentrant functions are very important in a parallel running environment, but generally you have to pay some performance cost for accessing global variables.

When writing a reentrant function, if global variables are used, they should be protected by disabling interrupts and semaphores (i.e. P, V operations).

 Note: If the global variables used are not protected, this function will not be reentrant, that is, when multiple processes call this function, it is very likely that the relevant global variables will become an unknown state.

 

Example: Assume Exam is a global variable of type int, and the function Squre_Exam returns the square of Exam. Then the following function is not reentrant.

unsigned int example( int para )

{

   unsigned int temp;
       Exam = para; //  (**)
       temp = Square_Exam() );
       return temp;
   }
   If this function is called by multiple processes, the result may be unknown, because when the (**) statement is just executed, another process using this function may be activated. Then when the newly activated process executes this function, it will assign a different para value to Exam. Therefore, when the control returns to "temp = Square_Exam()", the calculated temp may not be the expected result. This function should be improved as follows.

   unsigned int example( int para ) {
       unsigned int temp;
       [Apply for semaphore operation] //(1)
       Exam = para;
       temp = Square_Exam() );
       [Release semaphore operation]
       return temp;
   }
   (1) If the "semaphore" cannot be applied, it means that another process is in the process of assigning a value to Exam and calculating its square (that is, it is using this semaphore). This process must wait for it to release the semaphore before continuing to execute. If the signal is applied for, the execution can continue, but other processes must wait for the current process to release the semaphore before they can use the signal.

   Methods to ensure the reentrancy of functions:
   When writing functions, try to use local variables (such as variables in registers and stacks), and protect the global variables to be used (such as disabling interrupts, semaphores, etc.). In this way, the function must be a reentrant function. The reentrant
   technologies adopted in VxWorks are:
   * Dynamic stack variables (each sub-function has its own independent stack space)
   * Protected global variables and static variables
   * Task variables


--------------------------------------------------
   In the design of real-time systems, it is often the case that multiple tasks call the same function. If this function is unfortunately designed to be a non-reentrant function, then different tasks may modify the data of other tasks calling this function when calling this function, resulting in unpredictable consequences. So what is a reentrant function? The so-called reentrant function refers to a process that can be called by multiple tasks, and the tasks do not have to worry about whether the data will be wrong when calling it. Non-reentrant functions are considered unsafe functions in real-time system design. Most functions that meet the following conditions are not reentrant:
   1) Static data structures are used in the function body;
   2) Malloc() or free() functions are called in the function body;
   3) Standard I/O functions are called in the function body.

   The following examples are given to illustrate.
   A. Reentrant function
   void strcpy(char *lpszDest, char *lpszSrc)

 {
       while(*lpszDest++=*lpszSrc++);
       *dest=0;
   }

   B.  Non-reentrant function 1
   charcTemp; //global variable
   void SwapChar1(char *lpcX, char *lpcY)

 {
       cTemp=*lpcX;
       *lpcX=*lpcY;
       lpcY=cTemp; //Accessed global variables
   }

   C.  Non-reentrant function 2
   void SwapChar2(char *lpcX,char *lpcY)

 {
       static char cTemp; // static local variable
       cTemp = *lpcX;
       *lpcX = *lpcY;
       lpcY = cTemp; // static local variables are used
   }

   Question 1, how to write a reentrant function?
   Answer: Do not access global variables in the function body, do not use static local variables, insist on using only local variables, and the function you write will be reentrant. If you must access global variables, remember to use mutex semaphores to protect global variables.

   Question 2, how to rewrite a non-reentrant function into a reentrant function?
   Answer: The only way to make a non-reentrant function reentrant is to rewrite it using reentrant rules. In fact, it is very simple. As long as you follow a few easy-to-understand rules, the function you write will be reentrant.
   1) Do not use global variables. Because other code is likely to overwrite the values ​​of these variables.
   2) When interacting with hardware, remember to execute operations such as disinterrupt(), which is to turn off hardware interrupts. After completing the interaction, remember to turn on interrupts. In some series, this is called "enter/exit core".
   3) Do not call any other non-reentrant functions.
   4) Use the stack with caution. It is best to OS_ENTER_KERNAL before using it.

   Stack operations involve memory allocation, which can cause overflows and overwrite data of other tasks if you are not careful, so please use the stack with caution! It is best not to use it! Many hacker programs take advantage of this so that the system can execute illegal code and easily gain control of the system. There are some other rules. In short, always remember one sentence: Make sure interrupts are safe!

   Example question: I once designed the following function. When reviewing the code, I was reminded that there was a bug because this function is non-reentrant. Why?
   unsigned int sum_int( unsigned int base )

{
       unsigned int index;
       static unsigned int sum = 0; //  Note that it is of static type
       for (index = 1; index <= base; index++)
           sum += index;
       return sum;
   }

   Analysis: The so-called function is reentrant (or predictable), that is, as long as the input data is the same, the same output should be generated. The reason why this function is unpredictable is that static variables are used in the function. Because of the characteristics of static variables, such functions are called: functions with "internal memory" functions. Therefore, if a reentrant function is required, it is necessary to avoid using static variables in the function. The principle of using static variables in such functions is to avoid using them as much as possible.
   Modify the above function to a reentrant function. As long as the static keyword in the declaration of the sum variable is removed, the variable sum becomes an auto type variable, and the function becomes a reentrant function.
   Of course, sometimes, static variables must be used in functions. For example, when the return value of a function is a pointer type, the address of a static local variable must be used as the return value. If it is an auto type, the return value is an incorrect pointer.

Keywords:MCU Reference address:MCU multiple interrupt call sub-function

Previous article:Frequency and Duty Cycle
Next article:Differences between embedded C, standard C, and single-chip C

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号