1. A pipeline can achieve maximum efficiency only when it is filled with instructions, meaning that one instruction is executed per clock cycle (this refers only to single-cycle instructions). If a jump occurs in the program, the pipeline will be cleared, and it will take several clock cycles to refill the pipeline. Therefore, minimizing the use of jump instructions can improve program execution efficiency. A solution is to utilize the “conditional execution” feature of instructions as much as possible.
2. In the LPC2200 series:
You can delay for 10 milliseconds using the following program:
for(i=0;i<200;i++)
{
for(j=0;j<200;j++);
}
3. The following statement places a 16-bit variable into two 8-bit variables.
// High byte of IP datagram total length
IpHeadUint8[10]=(IpHead.e_ip.Crc&0xff00)>>8;
// Low byte of IP datagram total length
IpHeadUint8[11]=IpHead.e_ip.Crc&0x00ff;
4. When initializing all elements of an array, you do not need to specify the array length.
eg; int a[]={1,2,3,4,5};
However, if you attempt to access elements beyond a[5], the system will return random values, so when using this method, do not access elements beyond the initialized values.
5. Due to the inherent lack of support for printf in ADS, debugging can be inconvenient. You can use serial output as a substitute for printf for debugging.
6. Using the OR operation can set a specific bit to 1 while leaving other bits unchanged.
PINSEL0 |= 0x00000005; // Set serial port pins
This sets the 0th and 2nd bits to 1, leaving other bits unchanged.
7. Function pointers
1> In C, the function name directly corresponds to the address of the instruction code generated by the function in memory, so the function name can be directly assigned to a pointer to the function.
2> Calling a function is essentially equivalent to “calling the instruction + parameter passing + return address pushed onto the stack”. The core operation is assigning the starting address of the function’s generated target code to the CPU’s PC register.
3> Since the essence of a function call is to jump to a specific address to execute code, it is possible to “call a function that does not exist”.
4> int (*p)(); defines p as a pointer variable pointing to a function that returns an integer. The parentheses around *p cannot be omitted, indicating that p is a pointer variable, which is then combined with the following () to indicate that this pointer points to a function.
Difference: int *p() indicates that the return value of this function is a pointer to an integer variable.
Explanation:
(1) The general definition form of a pointer variable pointing to a function is:
Data type (*pointer variable name)();
1> Here, “data type” refers to the type of the function’s return value.
(2) A function that returns a pointer:
Type name *function name(parameter list)
eg: int * func(int x,int y)
func is the function name, and calling it will return a pointer to an integer data. x and y are the parameters of func.
Method to distinguish:
a. Find the first parenthesis from right to left; the contents inside the parentheses are the function’s parameters.
b. The first identifier outside the parentheses is the function’s name, and the preceding part indicates the function’s return value.
8. Array pointers
1> int (*p)[4]
Indicates that *p has 4 elements, each of which is an integer. This means that p points to an array with 4 integer elements, making p a row pointer.
2> Pointer arrays
Ø An array whose elements are all pointer types is called a pointer array; each element in the pointer array is equivalent to a pointer variable.
Ø The definition form of a one-dimensional pointer array is:
Type name *array name[array length]
eg: int *p[4]:
Purpose: It is used to point to several strings, making string processing more convenient and flexible. It is suitable for a two-dimensional string array where each row’s character array length is different.
eg: char * name[]={“Follow me”,”BASIC”,”GreatWall”};
9. Structures
1> A structure variable can be used as an actual parameter. However, when using a structure variable as an actual parameter, it is passed by “value”, meaning that the contents of the memory unit occupied by the structure variable are sequentially passed to the formal parameter. The formal parameter must also be a structure variable of the same type.
eg: pint(su);// Note that su is a structure
Note: This passing method incurs significant space and time overhead, especially if the structure is large.
2> Using a pointer to a structure variable (or array) as an actual parameter passes the address of the structure variable (or array) to the formal parameter.
eg: print(&su);// Note that su is a structure
10. Unions
1> A union stores several different data types in the same memory block. The variables in a union share the same memory space.
2> The general form for defining a union type variable is:
union union name
{
Member list;
} variable list;
3> In a union, the same memory space can be used to store several different types of data, but at any given time, only one member variable can be stored. The active member in the union variable is the last one that was stored.
eg: union data
{
int i;
char c;
double d;
};
union data a;
The members i, c, and d of the union variable a are stored starting from the same address in memory. If the following assignments are made:
a.i = 100;
a.c = ‘A’;
Then at this point, the member i of the union variable a no longer has a value because the memory that stored that value is now being used to store the value of member c.
3> The length of a union variable depends on the maximum length of its members:
Explanation:
The length of memory occupied by a structure variable is the sum of the lengths of its members, with each member occupying its own storage space. The length of memory occupied by a union variable is the length of its longest member. Of course, compilers often perform alignment operations when allocating storage space to improve access efficiency.
Alignment operations are based on the largest basic type. That is, the largest basic type is treated as the basic unit. If the actual calculated length is not a multiple of the basic unit, then its actual length should be a multiple of the basic unit.
(In TurboC, no alignment is performed; in Linux, alignment is performed)
11. Handling inconsistencies between CPU word length and memory width
For example: using a union to resolve this conflict:
union send_temp{
uint16 words;
uint8 bytes[2];
}send_buff;
eg: send_buff.bytes[0]=a;// Here a is 8 bits
send_buff.bytes[1]=b;// Here b is 8 bits;
This combines the 8-bit words into a 16-bit word for storage.
When sending, send(send_buff.words) can send a 16-bit data at a time.
12. C language operator precedence:
1> Compound assignment operators:
a+=3*5;
is equivalent to a=a+(3*5);
13. A common debugging strategy is to scatter some printf function calls throughout the program to determine the exact location of an error. However, the output of these function calls is written to a buffer and does not immediately display on the screen. In fact, if the program fails, the buffered output may not be actually written, leading to an incorrect error location. The solution is to immediately call the fflush function after each printf used for debugging.
printf(“something or other”);
fflush(stdout);
14. Usage of the volatile keyword
Volatile variables may be used in the following situations:
1> Hardware registers of devices (e.g., status registers)
2> Global variables accessed by an interrupt service routine
3> Variables shared by several tasks in multi-threaded applications.
15. Usage of the register keyword:
When a variable is frequently read and written, it requires repeated access to memory, which can consume a lot of access time. To address this, C provides a type of variable called a register variable. This variable is stored in the CPU’s registers, allowing direct read and write from the register without accessing memory, thus improving efficiency. The specifier for register variables is register. Loop control variables and variables used repeatedly within loops are good candidates for defining as register variables.
(1) Only local automatic variables and formal parameters can be defined as register variables. This is because register variables belong to dynamic storage, and any variable that requires static storage cannot be defined as a register variable, including: global variables between modules, global variables within a module, and local static variables;
(2) Register is a “suggestive” keyword, meaning that the program suggests that the variable be placed in a register, but ultimately, the variable may not become a register variable due to unmet conditions and may instead be placed in memory, without causing an error in the compiler (in C++, there is another “suggestive” keyword: inline).
16. For program code that has already been burned into FLASH or ROM, we can let the CPU read the code directly from there, but this is usually not a good approach. It is better to copy the target code from FLASH or ROM into RAM after the system starts and then execute it to improve instruction fetch speed;
The access speed of various memory types by the CPU is generally:
CPU internal RAM > external synchronous RAM > external asynchronous RAM > FLASH/ROM
17. Macro definitions
In C, macros are the only way to produce inline code. For embedded systems, macros are a great alternative to functions to meet performance requirements.
1> Macro definitions “look like” functions;
2> Macro definitions are not functions, so all “parameters” need to be enclosed in parentheses;
3> Macro definitions may produce side effects. Therefore, do not pass parameters with side effects to macro definitions.
1. The pros and cons of embedding an operating system in microcontrollers
2.Disassembling a DJI drone, a core component that shocks 99% of engineers!
3.Linux tips from a ten-year veteran
4.Today’s headlines Zhang Yiming: I interviewed 2000 young people, and those who did well all have these 5 traits!
5.How I self-taught software testing?
6.6.1, Recalling the “childhood” story from a monthly salary of 300 yuan to a net worth of tens of millions with the technical CEO!
Disclaimer: This article is a network reprint, and the copyright belongs to the original author. If there are any copyright issues, please contact us, and we will confirm the copyright based on the materials you provide and pay for the manuscript or delete the content.