Posted on Leave a comment

How to Use C SDK to Create UF2 file which Interface Ultrasonic Sensor with Raspberry Pi Pico

Hardware setup

HC-SR04Raspberry Pi Pico
VCCVSYS
GNDGND
TrigGP2
ECHOGP3

I am using raspberry pi model 3 b+ for the code compilation.

  1. Create the folder named “distance” inside the pico folder
  1. Then Create the test.c and CMakeLists.txt files using touch command.
touch test.c CMakeLists.txt
  1. Copy the pico_sdk_import.cmake file from pico/pico-sdk/external
  2. make the build directory using mkdir command
mkdir build
  1. Here is the CMakeLists.txt code
# Set the minimum required version of CMake
cmake_minimum_required(VERSION 3.13)

# Import the Pico SDK CMake configuration file
include(pico_sdk_import.cmake)

# Set the project name and languages
project(test_project C CXX ASM)

# Set the C and C++ language standards
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)

# Initialize the Pico SDK
pico_sdk_init()

# Create an executable target called "test" from the source file "test.c"
add_executable(test
    test.c
)

# Enable USB stdio for the "test" target (used for serial communication)
pico_enable_stdio_usb(test 1)

# Disable UART stdio for the "test" target
pico_enable_stdio_uart(test 0)

# Add extra outputs for the "test" target (e.g., UF2 file)
pico_add_extra_outputs(test)

# Link the "test" target with the pico_stdlib library
target_link_libraries(test pico_stdlib)
  1. Here is the c code that you put inside the test.c file
#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/gpio.h"
#include "hardware/timer.h"

#define TRIG_PIN 2
#define ECHO_PIN 3

float measure_distance() {
    gpio_put(TRIG_PIN, 1);
    sleep_us(10);
    gpio_put(TRIG_PIN, 0);

    uint32_t start_ticks = 0;
    uint32_t end_ticks = 0;

    while (gpio_get(ECHO_PIN) == 0) {
        start_ticks = time_us_32();
    }

    while (gpio_get(ECHO_PIN) == 1) {
        end_ticks = time_us_32();
    }

    uint32_t elapsed_time_us = end_ticks - start_ticks;
    float distance_cm = elapsed_time_us * 0.0343 / 2;

    return distance_cm;
}

int main() {
    stdio_init_all();
    sleep_ms(2000);  // Wait for sensor to stabilize

    gpio_init(TRIG_PIN);
    gpio_set_dir(TRIG_PIN, GPIO_OUT);

    gpio_init(ECHO_PIN);
    gpio_set_dir(ECHO_PIN, GPIO_IN);

    while (1) {
        float distance = measure_distance();
        printf("Distance: %.2f cm\n", distance);
        sleep_ms(1000);
    }

    return 0;
}
  1. after this you need to execute this line of code in the terminal
export PICO_SDK_PATH=../../pico
  1. then execute the following code in the given order
cd build
cmake ..
make

If everything worked, you will have your ulf2 file in your build directory

Posted on Leave a comment

Merge Sort is bad for Embedded System

Merge sort is good if your system has plenty of memory to accommodate the temporary array.

Embedded systems have very limited memory and it is often fixed.

If the system has some other function that also runs concurrently. Then that memory also gets shortened.

Merge sort is good for a bigger system like the personal computer and business computer which have the bigger memory in which all the temporary array can reside.

The advantage of merge sort is that it is stable.

Since it takes a lot of space it is not useful for an embedded system, as they have a very small memory sometimes it is just KilloByte.
example:
ATmega328p = 2KB SRAM
ATtiny85 = 512B SRAM

Code for STM32F429ZIT6

This code redirects the printf statements towards the asynchronous UART.
As the size of input array for merge sort increases the space required to store temporary element increases, which eventually leads to stalling of the program.
/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2023 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.h"
#include "stdlib.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
UART_HandleTypeDef huart1;

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART1_UART_Init(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/*
* Function Name: _write
* Function Description: Redirect the printf() statement towards the UART using the HAL_UART_Transmit
Author: Abhay

*/
int _write(int fd, char* ptr, int len) {
    HAL_UART_Transmit(&huart1, (uint8_t *) ptr, len, HAL_MAX_DELAY);
 //   HAL_UART_Transmit(&huart1, ptr, len, Timeout)
    return len;
}

// Merges two subarrays of arr[].
// First subarray is arr[l..m]
// Second subarray is arr[m+1..r]
void merge(int arr[], int l, int m, int r)
{
	int i, j, k;
	int n1 = m - l + 1;
	int n2 = r - m;

	/* create temp arrays */
	int L[n1], R[n2];

	/* Copy data to temp arrays L[] and R[] */
	for (i = 0; i < n1; i++)
		L[i] = arr[l + i];
	for (j = 0; j < n2; j++)
		R[j] = arr[m + 1 + j];

	/* Merge the temp arrays back into arr[l..r]*/
	i = 0; // Initial index of first subarray
	j = 0; // Initial index of second subarray
	k = l; // Initial index of merged subarray
	while (i < n1 && j < n2) {
		if (L[i] <= R[j]) {
			arr[k] = L[i];
			i++;
		}
		else {
			arr[k] = R[j];
			j++;
		}
		k++;
	}

	/* Copy the remaining elements of L[], if there
	are any */
	while (i < n1) {
		arr[k] = L[i];
		i++;
		k++;
	}

	/* Copy the remaining elements of R[], if there
	are any */
	while (j < n2) {
		arr[k] = R[j];
		j++;
		k++;
	}
}

/* l is for left index and r is right index of the
sub-array of arr to be sorted */
void mergeSort(int arr[], int l, int r)
{
	if (l < r) {
		// Same as (l+r)/2, but avoids overflow for
		// large l and h
		int m = l + (r - l) / 2;

		// Sort first and second halves
		mergeSort(arr, l, m);
		mergeSort(arr, m + 1, r);

		merge(arr, l, m, r);
	}
}

/* UTILITY FUNCTIONS */
/* Function to print an array */
void printArray(int A[], int size)
{
	int i;
	for (i = 0; i < size; i++)
		printf("%d ", A[i]);
	printf("\n");
}

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */
  int arr[] = { 12, 11, 13, 5, 6, 7,12};
        int arr_size = sizeof(arr) / sizeof(arr[0]);

//        for( int temp=0; temp<1023;temp++){
//  	arr[temp] = rand()*1000;
//  }
        printf("Given array is \n");
        printArray(arr, arr_size);

        mergeSort(arr, 0, arr_size - 1);

        printf("\nSorted array is \n");
        printArray(arr, arr_size);
     //   return 0;
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Configure the main internal regulator output voltage
  */
  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE3);

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
  {
    Error_Handler();
  }
}

/**
  * @brief USART1 Initialization Function
  * @param None
  * @retval None
  */
static void MX_USART1_UART_Init(void)
{

  /* USER CODE BEGIN USART1_Init 0 */

  /* USER CODE END USART1_Init 0 */

  /* USER CODE BEGIN USART1_Init 1 */

  /* USER CODE END USART1_Init 1 */
  huart1.Instance = USART1;
  huart1.Init.BaudRate = 115200;
  huart1.Init.WordLength = UART_WORDLENGTH_8B;
  huart1.Init.StopBits = UART_STOPBITS_1;
  huart1.Init.Parity = UART_PARITY_NONE;
  huart1.Init.Mode = UART_MODE_TX_RX;
  huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart1.Init.OverSampling = UART_OVERSAMPLING_16;
  if (HAL_UART_Init(&huart1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN USART1_Init 2 */

  /* USER CODE END USART1_Init 2 */

}

/**
  * @brief GPIO Initialization Function
  * @param None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOG_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOG, ledg_Pin|ledr_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pins : ledg_Pin ledr_Pin */
  GPIO_InitStruct.Pin = ledg_Pin|ledr_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);

}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
Posted on Leave a comment

Swapping of two numbers

Before Swapping :
a = 10
b = 2

After Swapping:
a = 2
b = 10

To do the swapping we have different approaches.
1. Swapping using a temporary variable
2. Swapping without using a temporary variable
3. Swapping using pointers

NOTE: We do not use of the second method in embedded system software writing. Because it would have to execute more instructions to perform the same operation with a temporary variable.

Swapping using a temporary variable

#include <stdio.h>
#include <stdlib.h>

int main(void) {
	int a = 10;
	int b = 3;
	int temp = 0;
	printf("Before Swapping");
	printf("\na = %d\tb = %d\n",a,b);

	temp = a;
	a = b;
	b = temp;

	printf("After Swapping");
	printf("\na = %d\tb = %d\n",a,b);

	return EXIT_SUCCESS;
}

Swapping without using a temporary variable

#include <stdio.h>
#include <stdlib.h>

int main(void) {
	int a = 10;
	int b = 3;
	int temp = 0;
	printf("Before Swapping");
	printf("\na = %d\tb = %d\n",a,b);

	a = a - b;
	b = a + b;
	a = b - a;

	printf("After Swapping");
	printf("\na = %d\tb = %d\n",a,b);

	return 1;
}

Swapping using pointers

When the memory size is very limited we prefer to do this.

#include <stdio.h>
#include <stdlib.h>

int main(void) {
	int a = 10;
	int b = 3;
	int temp;
	int *x , *y;

	printf("Before Swapping");
	printf("\na = %d\tb = %d\n",a,b);

	x = &a;
	y = &b;
	temp = *x;
	*x = *y;
	*y = temp;

	printf("After Swapping");
	printf("\na = %d\tb = %d\n",a,b);
	
	return 1;
}
Posted on Leave a comment

How to Perform Discrete Fourier Transform on N-Point Sequence using STM32L476G

x(n) = { 0, 1, 0, 1}

Here x(n) is a 4 point sequence

Now to perform Fourier transform on this sequence.

DFT Formula

Here X(k) is the DFT of x(n)

‘k’ is the index representing individual frequency component

‘N’ is the Length of the sample sequence

‘n’ is an index of the element of the sequence in x(n)

For example: if we calculate the value for k =1

This will give us the X(1)

So, if the sequence is sampled at 4Hz and the sampling frequency is equal to two times the max frequency. Then X(1) gives us the 1 Hz frequency component.

To calculate Euler identity

Here is the code:

/*
* Author: ABHAY KANT
* Discrete Fourier Transform using STM32L476vg on STM32L476g-Disco board.
* computes N point DFT
* computes magnitude of N/2 Points of dft
* computes phase of N/2 points of dft
* NOTE: DFT array is named xfft. It DOES NOT Calcultes DFT using FFT algo.
* Limitations: for a 2000 point sequence it takes a lot of time.
               And as the number of points increase the computational time also increases.
a rough estimate of time for a 2000 point dft it takes roughly ~ 60 seconds. 
*/
asm("nop");
//int xn[6] = {1,1,2,2,3,3};

int16_t Len = 1024; 
float xn[Len];

float xfft[Len * 2];

/*
 * calculating phase and mag for only N/2 since the value generated after N/2 are conjugate 
 */
float phase[Len/2], mag[Len/2];
int	k = 1;
int	N = 0;
int	n = 0;
float	real = 0;
float	imag = 0;
float	param = 0;
int	freq = 10;
int i;

/*
 * These two "for loops" are used to initalize the array with zero's
 */
for(n=0;n<=Len;n++){xn[n] = 0;}
for(n=0;n<=Len*2;n++){xfft[n] = 0;}



/*
 * Generating a sine Wave 
 */

	for(i=0; i<Len/2; i++){
		xn[i+512] = sin((2 * 3.1415926 * i * freq)/Len);
	}

N = Len;				
/* Note: if Len/8 then it will only calculate the 1/8 th term from 0 only.*/
/*
 * This loop calculates the x[n].e^(-j2.PI.n.k/N)
 */

	for(k=0 ; k<N ; k++){

		for(n=0 ; n<N; n++){
		param = ((2 * M_PI * n * k)/N);
		real = real + ( xn[n] * cos(param) );
		imag = imag + ((-1) * xn[n] * sin(param) );
		}
		xfft[2 * k] = real;
		xfft[(2 * k) + 1] = imag;
		real = 0;
		imag = 0;
	}



/*
 * Calculate phase angle of each frequency component
 */
float temp;
for(k=0; k<N/2;k++)
{
	temp = xfft[(2 * k ) + 1] / xfft[2 * k];
	phase[k] = atan(temp);
}

/*
 * Calculate Magnitude of each frequency 
 */

for(k=0; k<N/2;k++)
{
	temp = sqrt( (xfft[(2 * k ) + 1] * xfft[(2 * k ) + 1] ) + ( xfft[2 * k] * xfft[2 * k] ) );
	mag[k] = temp;
}
asm("nop");  //added to support for creating breakpoint during debug
Posted on Leave a comment

Stack implementation without pointer

Stack is a type of data structure, where data is stored in Last In First Out fashion. In embedded system there are different kind of stacks available.
They are implemented in hardware and software.
The hardware implementation of stack is faster than software stack; but the size of stack in hardware is limited.

There are two types of stack available in hardware implementation:
1. Up-counting
2. Down-counting
Up-counting stack: where the memory location of the top element of stack is incremented from the low memory address;
Down-counting stack where the memory location is decremented from the highest memory address.

The following is a general stack implementation program which is written on x86 machine.


#include <stdio.h>

#define MAX 7

int arr[MAX]; // array of size MAX

int top = -1; //top is the index which stores the location
              // of the last inserted element in stack
/*
isFull Function checks that the top == MAX
isEmpty Function checks that the top == -1
*/
int isFull();
int isEmpty();

/*
push(int num)     To insert a element in stack
pop()             To remove the last inserted element in stack
display()         To display all the element in stack
*/

void pop();
void push(int num);

void display();

int main() {

display();	//display the elements of the stack

    push(32);
    push (1);
    push (26);
    push (64);
    push (127);
    push (-98);
    push (43);
    push (5);
    push (255);
    push (5);
    display();
    pop();

return 0;
}

int isEmpty(){
	if(top == -1){
		return 1;
	}
	else
		return 0;
}

int isFull(){
	if(top == MAX){
		return 1;
	}
	else
		return 0;
}

/*check if the stack is full or not.
If stack full 
write overflow
else 
increment the TOP and write the value.
*/
void push(int num){
	if(isFull()){
	printf("Stack Full OverFlow\n");
	}
	else {
		top++;
		arr[top] = num;
	}
	display();
}
/*check if the stack is empty or not.
If stack empty 
write underflow
else 
decrement the TOP.
*/
void pop(){
	if( isEmpty() ) {
	printf("Stack Full OverFlow\n");
	}
	else {
		top--;
	}
	display();
}

void display(){
	if( isEmpty() ){
		printf("Stack Empty UNDERFLOW\n");
		
	}
	else{
		int temp;
		for(temp = top; temp >= 0 ; temp--){
			printf("%d ",arr[temp]);
		}
		printf("\n");
		/*int *ptr = arr;
		while(ptr <= ((&arr)+MAX) ){
			printf("%d ",*ptr);
			ptr = ptr + 1;
			printf("\n");
		}
		*/
		
	}
}

Output Of the above program


Stack Empty UNDERFLOW

32 

1 32 

26 1 32 

64 26 1 32 

127 64 26 1 32 

-98 127 64 26 1 32 

43 -98 127 64 26 1 32 

5 43 -98 127 64 26 1 32 
Stack Full OverFlow

5 43 -98 127 64 26 1 32 
Stack Full OverFlow

5 43 -98 127 64 26 1 32 

5 43 -98 127 64 26 1 32 

43 -98 127 64 26 1 32 

Posted on Leave a comment

Union

Union is another user defined data type.

The difference between union and struct is that; struct uses a contagious memory allocation for each individual item inside it; whereas union uses the size of biggest element for allocation of memory.

union segment1 {
int x1;
char y2;
};

// sizeof segement1 union is 4 bytes 

struct segment2{
int x1;
char y2;
};

// sizeof segement1 union is 8 bytes 

Posted on Leave a comment

Convert program written in C into assembly

Sometimes to understand code , you need to look into assembly language. I write mostly using C. So sometimes to better understand the program i converte the program into assembly. The syntax changes from machine to machine.

Here is the program that i will use to convert to assembly using two different machine. One is ARM based and the other is x86_64.

#include <stdio.h>

struct CarDetail{
int CarNumber;
char CarOptions;
};

int main() {
struct CarDetail maruti_alto;

maruti_alto.CarNumber = 123;
maruti_alto.CarOptions = 'L';

printf("Maruti Alto Details\nNumber = \t%d\nOptions = \t%c",maruti_alto.CarNumber,maruti_alto.CarOptions);
return 0;
}

ARM

If i convert the above program using ARM based machine using command

gcc main.c -S -o main.s
        .arch armv6
	.file	"main.c"
	.text
	.section	.rodata
	.align	2
.LC0:
	.ascii	"Maruti Alto Details\012Number = \011%d\012Options ="
	.ascii	" \011%c\000"
	.text
	.align	2
	.global	main
	.arch armv6
	.syntax unified
	.arm
	.fpu vfp
	.type	main, %function
main:
	@ args = 0, pretend = 0, frame = 8
	@ frame_needed = 1, uses_anonymous_args = 0
	push	{fp, lr}
	add	fp, sp, #4
	sub	sp, sp, #8
	mov	r3, #123
	str	r3, [fp, #-12]
	mov	r3, #76
	strb	r3, [fp, #-8]
	ldr	r3, [fp, #-12]
	ldrb	r2, [fp, #-8]	@ zero_extendqisi2
	mov	r1, r3
	ldr	r0, .L3
	bl	printf
	mov	r3, #0
	mov	r0, r3
	sub	sp, fp, #4
	@ sp needed
	pop	{fp, pc}
.L4:
	.align	2
.L3:
	.word	.LC0
	.size	main, .-main
	.ident	"GCC: (Raspbian 8.3.0-6+rpi1) 8.3.0"
	.section	.note.GNU-stack,"",%progbits

If we want to remove relative addressing modes and make it very simple you can use -fomit-frame-pointer option

gcc main.c -S -fomit-frame-pointer -o main-omit-fp.s
        .arch armv6
	.file	"main.c"
	.text
	.section	.rodata
	.align	2
.LC0:
	.ascii	"Maruti Alto Details\012Number = \011%d\012Options ="
	.ascii	" \011%c\000"
	.text
	.align	2
	.global	main
	.arch armv6
	.syntax unified
	.arm
	.fpu vfp
	.type	main, %function
main:
	@ args = 0, pretend = 0, frame = 8
	@ frame_needed = 0, uses_anonymous_args = 0
	str	lr, [sp, #-4]!
	sub	sp, sp, #12
	mov	r3, #123
	str	r3, [sp]
	mov	r3, #76
	strb	r3, [sp, #4]
	ldr	r3, [sp]
	ldrb	r2, [sp, #4]	@ zero_extendqisi2
	mov	r1, r3
	ldr	r0, .L3
	bl	printf
	mov	r3, #0
	mov	r0, r3
	add	sp, sp, #12
	@ sp needed
	ldr	pc, [sp], #4
.L4:
	.align	2
.L3:
	.word	.LC0
	.size	main, .-main
	.ident	"GCC: (Raspbian 8.3.0-6+rpi1) 8.3.0"
	.section	.note.GNU-stack,"",%progbits

X86_64

gcc main.c -S -o main.s
	.file	"main.c"
	.text
	.section	.rodata
	.align 8
.LC0:
	.string	"Maruti Alto Details\nNumber = \t%d\nOptions = \t%c"
	.text
	.globl	main
	.type	main, @function
main:
.LFB0:
	.cfi_startproc
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register 6
	subq	$16, %rsp
	movl	$123, -8(%rbp)
	movb	$76, -4(%rbp)
	movzbl	-4(%rbp), %eax
	movsbl	%al, %edx
	movl	-8(%rbp), %eax
	movl	%eax, %esi
	leaq	.LC0(%rip), %rdi
	movl	$0, %eax
	call	printf@PLT
	movl	$0, %eax
	leave
	.cfi_def_cfa 7, 8
	ret
	.cfi_endproc
.LFE0:
	.size	main, .-main
	.ident	"GCC: (Debian 8.3.0-6) 8.3.0"
	.section	.note.GNU-stack,"",@progbits
gcc main.c -S -fomit-frame-pointer -o main-omit-fp.s
	.file	"main.c"
	.text
	.section	.rodata
	.align 8
.LC0:
	.string	"Maruti Alto Details\nNumber = \t%d\nOptions = \t%c"
	.text
	.globl	main
	.type	main, @function
main:
.LFB0:
	.cfi_startproc
	subq	$24, %rsp
	.cfi_def_cfa_offset 32
	movl	$123, 8(%rsp)
	movb	$76, 12(%rsp)
	movzbl	12(%rsp), %eax
	movsbl	%al, %edx
	movl	8(%rsp), %eax
	movl	%eax, %esi
	leaq	.LC0(%rip), %rdi
	movl	$0, %eax
	call	printf@PLT
	movl	$0, %eax
	addq	$24, %rsp
	.cfi_def_cfa_offset 8
	ret
	.cfi_endproc
.LFE0:
	.size	main, .-main
	.ident	"GCC: (Debian 8.3.0-6) 8.3.0"
	.section	.note.GNU-stack,"",@progbits