-1

Here is my code, I'm almost new to coding and working on my first embedded task, seriously gonna need some help. Thanks in advance.

1 int *xData;
2 char Pixels[246];
3 uint8_t data[128];
4 char* Pixel_data;

5 while(1)
6 {
7   xData= (int*)malloc(sizeof(int));
8
9   ReadSamples(data);
10  int j=0;
11  for (int i=0;i<=127;i+=2)
12  {
13  
14      *xData = data[i] + data[i+1];
15      temp_c[j] = (*xData)*(mult);
16      free(xData);
17      j++;
18  }
19  Pixel_data = Create_heatmap(temp_c);  //Create_heatmap returns char* ptr of size 246
20  memcpy(Pixels, Pixel_data,246*sizeof(char) + 1);
21  //Transfers the whole converted data
22  HAL_UART_Transmit(&huart1,(uint8_t*) Pixels, sizeof(Pixels), 100);
23  free(Pixel_data);
24 }
  1. in line 7 I'm creating a memory for xData using malloc, In line 14 I'm feeding some data to it, In line 16 I'm freeing it using free, I'm freeing the xData in one iteration of for loop only but when I see the output as expected. How is xData getting filled even after freeing the memory allocated?
  2. Can I get better explanation for line 20, I have pixels with size 246 and I'm copying 246+1 it's working only with 247, if not 247 a byte of data is missing at end. Why is this?
  3. At line 9, I'll be getting 64 readings from a sensor each in 12bits and stores as data[0] = 8 bits and data[1] = 4 bits. This may be float/int. I know that what I'm doing is wrong in 'line 14`. How to overcome this?
Yuvi
  • 25
  • 7
  • 2
    Answering your first question, this is undefined behavior. It might "work" by pure luck, or it might be destroying parts of your program without you noticing. – paddy Dec 08 '21 at 05:31
  • What if line 19 returns a NULL pointer, your memcpy will fail, program will crash. Also, your memcpy should copy only bytes equal to destination buffer size. – kiner_shah Dec 08 '21 at 05:32
  • What is the point of xData? What does ReadSamples do - does it return anything? – kiner_shah Dec 08 '21 at 05:32
  • For third question, why not use `uint16_t`? BTW this will depend on how ReadSamples is defined and works. – kiner_shah Dec 08 '21 at 05:35
  • And is this C or C++? Please remove C++ tag is this is not related to it. – kiner_shah Dec 08 '21 at 05:36
  • Thanks for the reply @kiner_shah My third question has info for `Read_samples` function. If a data is stored in two bytes of memory, how shall I club it together and store or how to multiply(do some math) the whole 2 bytes of data once as I'm doing in `line 14` – Yuvi Dec 08 '21 at 05:51
  • 1
    @Yuvi, to me it's still unclear how exactly data is stored inside ReadSamples. How are 12 bits stored in `uint8_t` array? Please include the code for ReadSamples in the post. – kiner_shah Dec 08 '21 at 05:55
  • About the HAL UART you can check this [post](https://stackoverflow.com/questions/56384201/how-receive-data-with-hal-uart) – Ptit Xav Dec 08 '21 at 09:46

1 Answers1

0
  1. Accessing the memory address after calling free() is undefined behavior, anything might happen. What is undefined behavior and how does it work?

    Specifically, there is no such thing as "deleting" physical memory values - most of the time you just mark the address as invalid/not used but the values that were stored there last might still be around. For a great analogy (using the stack, not the heap, but same story either way), check out Can a local variable's memory be accessed outside its scope?

  2. You are accessing the array out of bounds by copying 247 bytes. This too is an undefined behavior bug. "it's working only with 247" - no it is not, you probably have a different bug elsewhere too.

  3. You should probably swap the array to type uint16_t.

    Alternatively you could do (uint32_t)data[i]<<8 | data[i+1]; depending on which byte contains the MSB - this depends on the ADC hardware and endianess. The cast to uint32_t is there to prevent shifting on a small integer type - I'm suspecting this is a Cortex M so you bit shifts should ideally be carried out as unsigned 32.

    Note that ADCs often has an option to set how you want data shifted. Assuming Little Endian and 12 bit ADC, then either LSB at byte 0 bit 0 (left-shifted), or LSB at byte 0 bit 4 (right-shifted)

Overall this code is quite naive, which is of course natural if it's your very first embedded project. Some other things of note:

  • When dealing with integers in embedded systems, you should only use the types from stdint.h. You rarely ever need signed numbers and you should never use plain int.

  • Dynamic allocation is generally not used in embedded systems because it doesn't make any sense, see this. In your specific case it's just massively inefficient overhead bloat - you should be using a statically allocated buffer instead.

  • Similarly, floating point arithmetic should only be used on microcontrollers with an actual FPU. That means at least Cortex M4 .

Lundin
  • 195,001
  • 40
  • 254
  • 396