C Language | Embedded C Language |
---|---|
C is a general-purpose programming language used to design any desktop-based applications. | Embedded C is nothing but an extension C programming language, and it is used to develop micro-controller based applications. |
C is a type of high-level programming language. | Embedded C is an extension of the C programming language. |
C programming language is the hardware-independent language. | Embedded C is a completely hardware-dependent language. |
C is a simple language, and it is easy to read and modify. | Embedded C is comparatively tough, and it is not easy to read and modify the Embedded C language. |
The compilers of the C programming language are OS-dependent. | The compilers of Embedded C are OS independent. |
In the C programming language, the standard compilers are used to compile and execute the program. | In Embedded C language, a specific compiler that can generate particular hardware/micro-controller based output is used to compile the code. |
Some popular compilers used to execute a C language program are: GCC (GNU Compiler collection) Borland Turbo C Intel C++ |
Some popular compilers used to execute an Embedded C language program are: Keil compiler BiPOM ELECTRONIC Green Hill software |
C programming language has a free format of program coding. | In Embedded C language, formatting depends upon the type of microprocessor used in the application. |
Bug fixing is easy in a C language program. | Bug fixing is complicated in an Embedded C language program. |
C language also supports other various programming languages during application. | Embedded C language supports only the required processor of the application and not the programming languages. |
C programming language must require an operating system. | Embedded C may or may not require an operating system. |
In the C programming language, we can give input to the program while it is running. | In Embedded C language, we can give only the pre-defined inputs to the running program. |
The C programming language supports normal optimization. | Embedded C supports the high level of optimization. |
C programming language generally uses the resources of a desktop PC like memory, OS, etc. | Embedded C language has to use with the limited resources, such as RAM, ROM, I/Os on an embedded processor. |
Some examples of the C Program applications: Logical programs System software programs etc. |
Some examples of the Embedded C Program applications: DVD TV Digital camera etc. |
int num1 = 20; //variable of int datatype
void *ptr; //Void Pointer
*ptr = &num1; //Point the pointer to int data
print("%d",(*(int*)ptr)); //Dereferencing requires specific data type
char c = 'a';
*ptr = &c; //Same void pointer can be used to point to data of different type -> reusability
print("%c",(*(char*)ptr));
volatile
is used to prevent the compiler to optimize any variable.volatile
is used to prevent the compiler for any type of optimization on the variable. Volatile variables are used with those variables which are used to communicate with the computer hardware, signals, handlers etc.//global declaration
unsigned char isDeviceAttached = 0;
//other code segment
int main()
{
//system configuration
//other code segment
//any loop/condition which is using the variable
which(isDeviceAttached)
{
//code to handle particular device
}
//other code
return 0;
}
isDeviceAtteched
is declared globally and is using frequently in the program. The compiler may optimize it and keep its ‘0’ in the memory to serve it faster.isDeviceAtteched
may change when we attached the device to signal/handler/interrupt function.volatile
above condition loop’s condition will be false always. And if we make it volatile
variable, the actual value will be served to the program.volatile unsigned char isDeviceAttaced;
volatile unsigned char isDeviceAtteched =0;
extern volatile unsigned char isDeviceAtteched;
const | volatile |
---|---|
The keyword “const” is enforced by the compiler and tells it that no changes can be made to the value of that object/variable during program execution. | The keyword “volatile” tells the compiler to not perform any optimization on the variables and not to assume anything about the variables against which it is declared. |
Example: const int x=20; , here if the program attempts to modify the value of x, then there would be a compiler error as there is const keyword assigned which makes the variable x non-modifiable. |
Example: volatile int x; , here the compiler is told to not assume anything regarding the variable x and avoid performing optimizations on it. Every time the compiler encounters the variable, fetch it from the memory it is assigned to. |
Processors | Cycles with zero wait state memory |
---|---|
Cortex-M0 | 16 |
Cortex-M0+ | 15 |
Cortex-M3 | 12 |
Cortex-M4 | 12 |
Cortex-M7 | 12 |
##
. It is used in macros to perform concatenation of the arguments in the macro. We need to keep note that only the arguments are concatenated, not the values of those arguments.#define CUSTOM_MACRO(x, y) x##y
main(){
int xValue = 20;
printf(“%d”, CUSTOM_MACRO(x, Value)); //Prints 20
}
x
and y
are passed, then the macro just returns xy ->
The concatenation of x
and y
.extern
keyboard can be to declare a variable which allows accessing the variable in another file./*include header file "file2.h"
where variable is declare*/
#include "file2.h"
...
/*Access the variable, where it is
Required*/
if(flgUSB){
...;
}
/*define variable in global scope*/
unsigned char flgUSB=0;
/*while defining a variable,
you can assign a default value to it*/
/*declare variable in global scope*/
extern unsigned char flgUSB;
/*do not use default value here, it will generate an error*/
extern
in the header file and then include it file in "file1.c" or wherever you want to access the variable.const char*
) prevents the unnecessary modifications with the pointer address in the string.///declaration
const char *str;
//we can reassign the pointer
//string will be declared somewhere in the memory and
//its address will be assigned to the "str"
str = "Hello world";
//but, we cannot modify the data
//that is pointing by the pointer
*str = 'P';//not allowed
Category | Macro Function | Inline Function |
---|---|---|
Compile-time expansion | Macro functions are expanded by the preprocessor at the compile time. | Inline functions are expanded by the compiler. |
Argument Evaluation | Expressions passed to the Macro functions might get evaluated more than once. | Expressions passed to Inline functions get evaluated once. |
Parameter Checking | Macro functions do not follow strict parameter data type checking. | Inline functions follow strict data type checking of the parameters. |
Ease of debugging | Macro functions are hard to debug because it is replaced by the pre-processor as a textual representation which is not visible in the source code. | Easier to debug inline functions which is why it is recommended to be used over macro functions. |
Example | #define SQUARENUM(A) A * A -> The macro functions are expanded at compile time. Hence, if we pass, the output will be evaluated to 3+2*3+2 which gets evaluated to 11. This might not be as per our expectations. |
inline squareNum(int A){return A * A;} -> If we have printf(squareNum(3+2)); , the arguments to the function are evaluated first to 5 and passed to the function, which returns a square of 5 = 25. |
while(1)
{
...;
...;
}
for(;;)
{
...;
...;
}
Void main( void)
{
//prepare run function x
X_Init();
While(1) // ‘for ever’ (super loop)
{
X(); // Run function x()
}
}
RISC | CISC |
---|---|
RISC stands for Reduced Instruction Set Computer. | CISC stands for Complex Instruction Set Computer. |
RISC does not consist of a memory unit. | CISC consists of a memory unit. |
RISC is a relatively faster processor than CISC in terms of calculations. | CISC is a comparatively slower processor than RISC in terms of calculations. |
RISC is used to ensure the simple decoding of operations. | CISC doesn't ensure simple decoding of operations. |
The execution time is RISC is low. | The execution time is CISC is high. |
--operand
) is used for decrementing the value of the variable by 1 before assigning the variable value.#include < stdio.h >
int main(){
int x = 100, y;
y = --x; //pre-decrememt operators -- first decrements the value and then it is assigned
printf("y = %d\n", y); // Prints 99
printf("x = %d\n", x); // Prints 99
return 0;
}
operand--
) is used for decrementing the value of a variable by 1 after assigning the variable value.#include < stdio.h >
int main(){
int x = 100, y;
y = x--; //post-decrememt operators -- first assigns the value and then it is decremented
printf("y = %d\n", y); // Prints 100
printf("x = %d\n", x); // Prints 99
return 0;
}
data_type *pointer_name = NULL;
1. const int x;
2. int const x;
3. const int *x;
4. int * const x;
5. int const * x const;
int *p;
*p = 20;
#include "..."
, the preprocessor just searches for the file in the current directory as where the source file is present and if not found, it proceeds to search in the standard directories specified by the compiler. #include <...>
declaration, the preprocessor looks for the files in the compiler designated directories where the standard library files usually reside.
#include <stdlib.h>
void memLeakDemo()
{
int *p = (int *) malloc(sizeof(int));
/* Some set of statements */
return; /* Return from the function without freeing the pointer p*/
}
#include <stdlib.h>;
void memLeakFix()
{
int *p = (int *) malloc(sizeof(int));
/* Some set of statements */
free(p); // Free method to free the memory allocated to the pointer p
return;
}
//Memory address, you want to access
#define RW_FLAG 0x1FFF7800
//Pointer to access the Memory address
volatile uint32_t *flagAddress = NULL;
//variable to stored the read value
uint32_t readData = 0;
//Assign addres to the pointer
flagAddress = (volatile uint32_t *)RW_FLAG;
//Read value from memory
* flagAddress = 12; // Write
//Write value to the memory
readData = * flagAddress;
enum
in C is a user-defined data type. It consists set of named constant integers. Using the enum keyword, we can declare an enumeration type by using the enumeration tag (optional) and a list of named integer.enum Enumeration_Tag { Enumeration_List };
Enumeration_Tag
specifies the enumeration type name.Enumeration_List
is a comma-separated list of named constant.enum FLASH_ERROR { DEFRAGMENT_ERROR, BUS_ERROR};
#include <stdio.h>
#include <inttypes.h>
//Function to change one endian to another
uint32_t ChangeEndianness(uint32_t u32Value)
{
uint32_t u32Result = 0;
u32Result |= (u32Value & 0x000000FF) << 24;
u32Result |= (u32Value & 0x0000FF00) << 8;
u32Result |= (u32Value & 0x00FF0000) >> 8;
u32Result |= (u32Value & 0xFF000000) >> 24;
return u32Result;
}
int main()
{
uint32_t u32CheckData = 0x11223344;
uint32_t u32ResultData =0;
//swap the data
u32ResultData = ChangeEndianness(u32CheckData);
//converted data
printf("0x%x\n",u32ResultData);
return 0;
}
0x44332211
Parameter | RS232 | RS485 |
---|---|---|
Line configuration | Single –ended | differential |
Numbers of devices | 1 transmitter 1 receiver | 32 transmitters 32 receivers |
Mode of operation | Simplex or full duplex | Simplex or half duplex |
Maximum cable length | 50 feet | 4000 feet |
Maximum data rate | 20 Kbits/s | 10 Mbits/s |
signaling | unbalanced | balanced |
Typical logic levels | +-5 ~ +-15V | +-1.5 ~ +-6V |
Minimum receiver input impedance | 3 ~ 7 K-ohm | 12 K-ohm |
Receiver sensitivity | +-3V | +-200mV |
Bit Rate | Baud Rate |
---|---|
Bit rate is the number of bits per second. | Baud rate is the number of signal units per second. |
It determines the number of bits traveled per second. | It determines how many times the state of a signal is changing. |
Cannot determine the bandwidth. | It can determine how much bandwidth is required to send the signal. |
This term generally used to describe the processor efficiency. | This term generally used to describe the data transmission over the channel. |
Bit rate = baud rate x the number of bits per signal unit | Baud rate = bit rate / the number of bits per signal unit |
#include<stdio.h>
void main(){
int num;
printf(“Enter number: ”);
scanf(“%d”,&num);
printf(“%d”, (num<<3)+num);
}
int num1=20, num2=30, temp;
temp = num1;
num1 = num2;
num2 = temp;
int num1=20, num2=30;
num1=num1 + num2;
num2=num1 - num2;
num1=num1 - num2;
int num1=20, num2=30;
num1=num1 ^ num2;
num2=num2 ^ num1;
num1=num1 ^ num2;
int num1=20, num2=30;
num1^=num2^=num1^=num2;
int num1=20, num2=30;
num1 = (num1+num2)-(num2=num1);
void *realloc(void *ptr, size_t size);
void ( *fpData )( int );
void ( *pfDisplayMessage) (const char *);
const char *
, and returns void.const char *
). It is a declaration of a function that takes the const character pointer as arguments and returns a void pointer.extern int data;
extern int foo(int, int);
int fun(int, char); // extern can be omitted for function declarations
int data;
int foo(int, int) { }
int PrintData ( const char *pcMessage);
const volatile uint32_t *DEVICE_STATUS = (uint32_t *) 0x80102040;