2

I am using stm32f429 UART to send commands into a module. I prefer the second function code but I don't know how can I make it work. First function code, which works completely.

void v_cmd(unsigned short cmd)
{
    uint8_t cmd_packet[8];
    sprintf((char *)cmd_packet, "%02hu", cmd);
    HAL_UART_Transmit(&huart1, cmd_packet, 2, 100);
}

The Seconde function code, which doesn't work as the first code as I expected.

void v_cmd(unsigned short cmd)
{
    uint8_t *cmd_packet;
    sprintf((char *)cmd_packet, "%02hu", cmd);
    HAL_UART_Transmit(&huart1, cmd_packet, 2, 100);
}
WedaPashi
  • 3,561
  • 26
  • 42
vahid ajal
  • 49
  • 5
  • 2
    In the second snippet `cmd_packet` is a pointer, but *where does it point?* – Some programmer dude Dec 04 '20 at 07:56
  • 1
    Microcontroller programming can be somewhat advanced, more so than PC programming. You need fundamental C knowledge before taking on embedded systems, so if I were you, I'd stay clear of STM32 for now and read some basic C programming books first. – Lundin Dec 04 '20 at 08:56

2 Answers2

1

It works it the first piece code because you are allocating memory for with

uint8_t cmd_packet[8];

As you must be aware of, this is allocating 8 bytes of memory.

In the second piece of code you have shared, uint8_t *cmd_packet; is a pointer. But, you haven't allocated any memory where this point will point to. The code in its present state isn't functional because the pointer cmd_packet isn't initialized.

The next statement,

sprintf((char *)cmd_packet, "%02hu", cmd); 

tries to populate the memory pointed by cmd_packet with data cmd. However, like I explained earlier, it isn't pointing to a valid address location where you can put this data. This ends up in a segmentation fault.

Use malloc to allocate memory. You can refer the manual page for malloc.

uint8_t *p_cmd_packet = malloc(8);

The very next thing your code should do is to check if call to malloc has successfully allocated memory or not and some error handling if memory is not allocated.

if(NULL == p_cmd_packet)
{
    //! handle memory allocation error here
}

You also need to free this memory once you are done using it.

free(p_cmd_packet);

I see that the code you are developing is for an embedded microcontroller stm32f429. You also need to check in your startup assembly file for how much of heap is reserved/configured for application usage. Accordingly, you can handle memory allocations.

I see another potential problem here:

HAL_UART_Transmit(&huart1, cmd_packet, 2, 100);

Ideally, if I were you, and used sprintf() to populate the data, I would have read the return value of sprintf() function and would use that value to pass as number of bytes to be transmitted. As of now, I can't comment more on this unless I know the exact parameters passed to HAL_UART_Transmit().

WedaPashi
  • 3,561
  • 26
  • 42
  • Thank you for your answer. Is there any solution to solve the problem dynamically? Otherwise, what is the purpose of pointers? The static assignment in the first code does its work completely and clean. – vahid ajal Dec 04 '20 at 08:30
  • Exactly as the answer says but there will not be segmentation fault as the microcontroller doesn't have memory protection unit. It will write the characters to some undefined address using the sprintf() function. – teroi Dec 04 '20 at 08:37
  • As for the purpose of pointers: well, for example, pointers make it possible to indirectly refer to some memory location or variable or data structure that is either statically or dynamically allocated maybe even in some place other than in the same function. – teroi Dec 04 '20 at 08:40
  • @teroi: Not all microcontrollers have a Memory Protection Unit (MPU), and hence I still stand by statement that it will end up in a Hard Fault handler. – WedaPashi Dec 04 '20 at 09:32
  • 1
    @vahidajal: Like I said, when you are allocating memory using `malloc`, it is dynamic memory allocation. Isn't it? And, irrelevant though, pointers have unique purpose which doesn't really limit to dynamic memory allocation. – WedaPashi Dec 04 '20 at 09:34
0

From the open group page on sprintf:

int sprintf(char *s, const char *format, ...);

The sprintf() function places output followed by the null byte, '\0', in consecutive bytes starting at *s; it is the user's responsibility to ensure that enough space is available.

It is the responsibility of the user to allocate enough memory for cmd_packet (here). But you did not allocate any memory to cmd_packet.

Use malloc to allocate enough memory cmd_packet

Krishna Kanth Yenumula
  • 2,533
  • 2
  • 14
  • 26