Embedded Development: Key Concepts to Save You Three Years of Detours

Hello everyone, I am the Mixed Bag Master.

This time, I have organized some important theoretical concepts in embedded software development.

1. What is Stack Watermark Detection?

Stack watermark detection is a technique for dynamically monitoring task stack usage. During task initialization, the entire stack space is filled with a specific identification pattern (e.g., <span>0xDEADBEEF</span>).

Embedded Development: Key Concepts to Save You Three Years of Detours

As the task runs, the stack pointer gradually overwrites these preset values. By regularly checking the untouched residual identification locations, the historical maximum usage of the stack can be accurately calculated.

Compared to static code analysis, this method can truly reflect the impact of dynamic behaviors such as interrupt nesting and recursive calls. In practical applications, two points need to be noted:

  • The identification pattern must avoid conflicts with normal data;
  • The detection timing should be chosen during task idle or switching to avoid interfering with real-time performance.

2. What are Shallow Copy and Deep Copy?

Shallow copy only copies the values of the object itself (the values of pointer variables) and does not copy the actual data pointed to by the pointers. After copying, the pointer members of the new and old objects point to the same memory address.

Deep copy not only copies the values of the object itself but also recursively copies all data pointed to by the pointers. After copying, the pointer members of the new and old objects point to independent memory addresses.

Embedded Development: Key Concepts to Save You Three Years of Detours

Key Differences:

Embedded Development: Key Concepts to Save You Three Years of Detours

Shallow Copy Example:

// Directly assigning pointer (dangerous operation)
void shallow_copy(Student* dest, const Student* src)
{
    dest->id = src->id;
    dest->name = src->name;  // Sharing the same memory address
}
Student s1;
s1.id = 100;
s1.name = malloc(6);
strcpy(s1.name, "Alice");

Student s2;
shallow_copy(&s2, &s1);

printf("Shallow copy result:\n");
printf("s1.name=%p: %s\n", s1.name, s1.name);  // Outputs the same address
printf("s2.name=%p: %s\n\n", s2.name, s2.name);

// Modifying s1 will affect s2
strcpy(s1.name, "Bob");
printf("After modification:\n");
printf("s1.name: %s\n", s1.name);  // Bob
printf("s2.name: %s\n", s2.name);  // Bob

Deep Copy Example:

// Completely independent data copy
void deep_copy(Student* dest, const Student* src)
{
    dest->id = src->id;
    dest->name = malloc(strlen(src->name) + 1);  // New memory allocation
    strcpy(dest->name, src->name);              // Copy content
}
Student s3;
s3.id = 200;
s3.name = malloc(6);
strcpy(s3.name, "Carol");

Student s4;
deep_copy(&s4, &s3);

printf("Deep copy result:\n");
printf("s3.name=%p: %s\n", s3.name, s3.name);  // Different address
printf("s4.name=%p: %s\n\n", s4.name, s4.name);

// Modifying s3 does not affect s4
strcpy(s3.name, "Dave");
printf("After modification:\n");
printf("s3.name: %s\n", s3.name);  // Dave
printf("s4.name: %s\n", s4.name);  // Carol

// Must free memory separately
free(s1.name);
free(s3.name);
free(s4.name);

3. What are Synchronous and Asynchronous?

Synchronous Processing executes tasks in order, and subsequent tasks are blocked until the current task is completed. For example:

// Synchronous UART send (blocking)
void uart_send_sync(uint8_t *data, uint16_t len)
{
    for(int i=0; i<len; i++) 
    {
        while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); // Wait for send to complete
        USART_SendData(USART1, data[i]);
    }
}

Asynchronous Processing immediately returns after starting a task, notifying results through interrupts, callbacks, or events, without blocking subsequent tasks. For example:

void ADC_IRQHandler()
{
    if(ADC_GetITStatus(ADC1, ADC_IT_EOC)) {
        uint16_t result = ADC_GetConversionValue(ADC1); // Read result
        process_adc_result(result);                     // Callback processing
        ADC_ClearITPendingBit(ADC1, ADC_IT_EOC);
    }
}

Key Differences:

Embedded Development: Key Concepts to Save You Three Years of Detours

4. What are Memory Barriers?

Memory barriers are low-level mechanisms that ensure the order of memory operations. In weakly consistent memory models, compilers/processors may reorder instructions, and memory barriers enforce a specific order of operations. Key scenarios include multi-core communication, peripheral register access, etc.

Embedded Development: Key Concepts to Save You Three Years of Detours

That concludes this sharing. If you find the article helpful, please help share it, thank you!

Embedded Development: Key Concepts to Save You Three Years of Detours

END

Source:Embedded Mixed Bag

Copyright belongs to the original author. If there is any infringement, please contact for deletion..Recommended ReadingThe company received a lawyer’s letter for using pirated AD software…In the future, if your code is fast and good, you will be a fool!!!Why is hardware harder than software, yet hardware engineers are not paid as well as software engineers?→ Follow to avoid getting lost ←

Leave a Comment