Exercise Efficiency and Robustness - JawaharT/Best-Practices-On-Azure-Sphere GitHub Wiki
In general, these exercises use a variety of the topics discussed as part of the 'How: Efficiency and Robustness' section such as an example of memory overflows and the use of pointers.
In this exercise we will develop a simple Fibonacci program that asks for a number (index) from the user and shows the Fibonacci sequence up until that index (i.e., 4 as input would yield: 0 1 1 2). This exercise is not directly related to embedded systems but this exercise is used to illustrate the use of arrays and buffer overflows which is explained in a greater discussion below:
To understand and to learn more about the basics of Fibonacci, have a look at this webpage: click here
The below code is a start to the development of this exercise but there are issues with this program that range from the use of pointers as well as logical errors that need to be fixed to produce the correct result.
#include <stdio.h>
int end_integer_input(){
static int number;
// Use this for testing purposes on the desktop
// printf("Enter a Number for Fibonacci Sequence: ");
// scanf("%d", number);
// For embedded systems, place keypad entry here
number = 10;
return number;
}
void generate_sequence(*end_pos){
int *fib_sequence[end_pos]; // array of int pointer
fib_sequence[0] = 0;
printf("%d ", 0);
if (end_pos >= 1){
fib_sequence[1] = 1;
printf("%d ", 1);
for(int index = 0; index < end_pos; index++){
int next_number = fib_sequence[index] + fib_sequence[index+1];
printf("%d ", next_number);
fib_sequence[index] = next_number;
}
}
}
int main(){
generate_sequence(end_integer_input());
return 0;
}
The main issue with this program is the Int Data Type size limitation which means after the 47th index of the sequence the numbers are too large to be held inside Int data type which leads to what is called an overflow. To prevent this from happening, the use of the Long data type is better as it can hold numbers larger than Int data type.
A buffer is considered to be a sequence of data, so the issues in the above program can occur in any data structure. A buffer overflow occurs inside the fib_sequence array if the developer attempts to access an index that is greater than its size. A buffer underflow occurs if the index is less than zero. Any of these attempts will cause errors to be displayed due to accessing memory that does not belong to fib_sequence. It is important to remember that there is no boundary checking during stack-based array usage (such as fib_sequence above), so accessing out-of-bounds indexes will use already allocated stack space. But a segmentation fault is thrown if the stack is completely out of memory to use. So it is important to remember array boundaries are contentious in C. Therefore as a best practice it is ideal to never go beyond the bounds of a declared array. In C and other languages, it is considered as undefined behaviour to go beyond the boundaries of an array and does not have built-in error checking mechanisms in any scenario it is used in.
In the second exercise of this section, we will develop a program to read the gyro sensor onboard the Azure Sphere AVNET MT3620 board revision one. The code below is an incomplete start for a particular section to read the gyro sensor inside the board. The commented notes will provide guidance on tasks to complete for this exercise.
do {
// Read the calibration values
lsm6dso_gy_flag_data_ready_get(&dev_ctx, ®);
if (reg){
// Task 1: Read angular rate field data to use for calibration
}
// Read the angular data rate again and verify that after applying the calibration
lsm6dso_gy_flag_data_ready_get(&dev_ctx, ®);
if (reg){
// Read angular rate
memset(data_raw_angular_rate.u8bit, 0x00, 3 * sizeof(int16_t));
lsm6dso_angular_rate_raw_get(&dev_ctx, data_raw_angular_rate.u8bit);
// Before we store the angular rate values subtract the calibration data first.
angular_rate_dps[0] = lsm6dso_from_fs2000_to_mdps(data_raw_angular_rate.i16bit[0] - raw_angular_rate_calibration.i16bit[0]);
angular_rate_dps[1] = lsm6dso_from_fs2000_to_mdps(data_raw_angular_rate.i16bit[1] - raw_angular_rate_calibration.i16bit[1]);
angular_rate_dps[2] = lsm6dso_from_fs2000_to_mdps(data_raw_angular_rate.i16bit[2] - raw_angular_rate_calibration.i16bit[2]);
}
// Task 2: If the angular values after applying the offset are not 0.7 or less, then do perform again!
} while ();
In this third exercise, we will develop a program to add numbers using pointers and compare them with the localised version. The code below is incomplete, the commented notes will provide guidance on tasks to complete this exercise.
#include <stdio.h>
int addLocal(int x, int y, int z){
// Task 1: Locally store the addition of x and y inside z
printf("Local Z = %d\n", z);
return 0;
}
int addUsingPointer(int x, int y, int* z){
// Task 2: Use a pointer to add x and y and store it inside z
printf("Pointer Z = %d\n", *z);
return 0;
}
void main(){
int x = 5;
int y = 7;
int z = -2;
printf("x: %d\n", x);
printf("y: %d\n", y);
printf("z: %d\n\n", z);
printf("addLocal\n");
addLocal(x, y, z);
printf("z in main: %d\n\n", z);
printf("addUsingPointer\n");
addUsingPointer(x, y, &z);
printf("z in main: %d\n", z);
}
For a version of the correct solutions and an explanation for the differences click here.