cancel
Showing results for 
Search instead for 
Did you mean: 

How to decide start address in STMH747 for ThreadX Byte/Block Pool

__AdhipShukla
Associate II

I am working on a ThreadX project on my STM32H747I-Disco with M7 and M4 cores. I want to allocate memory dynamically in the initialization phase that can be accessed from both cores. For this, I am planning to use the "tx_byte_pool_create" and "tx_byte_allocate" APIs. The former requires the starting address of the memory pool. The example in the ThreadX user guide shows that it can be any memory location, such as 0x30000000. As I want to access the pool from both cores, I assume the memory location has to be in one of these locations (AXISRAM, SRAM1, SRAM2, SRAM3, SRAM4, BKSRAM). Now, I can get the address of these sections in the reference manual, but how do I know which one to select? Some sections will be used for the stack, which can grow. How can I ensure that the section I am selecting for the pool will always be available and not overwritten by the system?

In summary, I want to understand how to select the start address for the memory pool in RAM, which will remain valid indefinitely.

1 ACCEPTED SOLUTION

Accepted Solutions
nouirakh
ST Employee

Hello @__AdhipShukla ,

To modify the linker script so that a specific memory region (like SRAM1) is used exclusively for dynamic allocation by an RTOS like ThreadX, As you mentioned you need to ensure that the region is defined correctly in the linker script . You also need to inform ThreadX to use this region for its memory pool.
First, you need to define the memory region in your linker script:

MEMORY
{
  /* Define other memory regions */
  SRAM1 (rw) : ORIGIN = 0x20000000, LENGTH = 64K /* Adjust the origin and length as per your MCU's specifications */
  /* Define other memory regions */
}

Next, you'll want to create a section within this memory region that will be used for dynamic allocation:

SECTIONS
{
  .dynamic_alloc :
  {
    . = ALIGN(4);
    _sbrk_heap_start = .; /* Define start of the heap */
    *(.dynamic_heap)
    . = ALIGN(4);
    _sbrk_heap_end = .; /* Define end of the heap */
  } > SRAM1
  /* Define other sections */
}

PS: Make sure that no other data or code is placed into this section by the linker. This is typically done by not assigning any other sections or symbols to .dynamic_heap.
In your application code, you need to inform ThreadX to use the defined memory region for its memory pool. This is typically done by passing the start address and size to the ThreadX memory pool initialization function:

extern CHAR* _sbrk_heap_start;
extern CHAR* _sbrk_heap_end;

void tx_application_define(void* first_unused_memory)
{
  /* Calculate the size of the heap */
  ULONG heap_size = (ULONG)(_sbrk_heap_end - _sbrk_heap_start);

  /* Create a memory pool from the heap */
  tx_byte_pool_create(&my_byte_pool, "byte pool", _sbrk_heap_start, heap_size);
}

Finally, modify your application's dynamic memory allocation calls to use the ThreadX memory pool API instead of the standard library allocation functions such as malloc() and free():

void* ptr;
UINT status;

/* Allocate memory from the pool */
status = tx_byte_allocate(&my_byte_pool, &ptr, size_needed, TX_NO_WAIT);

if (status != TX_SUCCESS)
{
  /* Handle allocation error */
}


I hope my answer has helped you. When your question is answered please close this topic by marking as Best the reply that answered you, it will help others find that answer faster. Thanks for your contribution.

 

 

 

View solution in original post

3 REPLIES 3
nouirakh
ST Employee

Hello @__AdhipShukla 

To determine which memory region to use for your Project,  Look at the memory map in the reference manual to identify which memory regions are accessible by both cores, As you mention you can typically choose from: AXISRAM: This is a block of RAM accessible by both cores and is a good candidate for shared memory. SRAM1, SRAM2, SRAM3, SRAM4: These SRAM blocks may also be accessible by both cores, but you need to check the reference manual to confirm this. BKSRAM: Backup SRAM is usually used for data that needs to be retained across resets and may not be suitable for dynamic memory allocation due to its limited size.
Furthermore, estimate the size of the memory pool you need and select a region that can accommodate it.

Ensure that the memory region you select is not used by the core-specific stacks, heaps, or other system functions. You can do this by: Checking the linker script or scatter file for both cores to see which memory regions are allocated for system use. Ensuring that the memory region is not allocated for peripheral DMA operations that might be core-specific.
Once you've selected a region, modify the linker scripts for both cores to prevent the linker from placing code or data in this region.

For example, if you determine that SRAM3 is accessible by both cores and is not used by other system functions, you could reserve a portion of SRAM3 for your ThreadX byte pool. You would then modify the linker scripts or ICF files for both cores to exclude this region from being used for other purposes.

I hope my answer has helped you. When your question is answered please close this topic by marking as Best the reply that answered you, it will help others find that answer faster.
Thanks for your contribution.

With Regards,
Kholdoun

__AdhipShukla
Associate II

Hi @nouirakh thanks for the reponse.

 

Can you please suggest how to modify the linker scripts so that the memory region(SRAM1, which is shared) is exclusively used for dynamic allocation by ThreadX? Is adding a section like this enough?

 

.SRAM1 :

{

*(.SRAM1)

} >RAM_D2

nouirakh
ST Employee

Hello @__AdhipShukla ,

To modify the linker script so that a specific memory region (like SRAM1) is used exclusively for dynamic allocation by an RTOS like ThreadX, As you mentioned you need to ensure that the region is defined correctly in the linker script . You also need to inform ThreadX to use this region for its memory pool.
First, you need to define the memory region in your linker script:

MEMORY
{
  /* Define other memory regions */
  SRAM1 (rw) : ORIGIN = 0x20000000, LENGTH = 64K /* Adjust the origin and length as per your MCU's specifications */
  /* Define other memory regions */
}

Next, you'll want to create a section within this memory region that will be used for dynamic allocation:

SECTIONS
{
  .dynamic_alloc :
  {
    . = ALIGN(4);
    _sbrk_heap_start = .; /* Define start of the heap */
    *(.dynamic_heap)
    . = ALIGN(4);
    _sbrk_heap_end = .; /* Define end of the heap */
  } > SRAM1
  /* Define other sections */
}

PS: Make sure that no other data or code is placed into this section by the linker. This is typically done by not assigning any other sections or symbols to .dynamic_heap.
In your application code, you need to inform ThreadX to use the defined memory region for its memory pool. This is typically done by passing the start address and size to the ThreadX memory pool initialization function:

extern CHAR* _sbrk_heap_start;
extern CHAR* _sbrk_heap_end;

void tx_application_define(void* first_unused_memory)
{
  /* Calculate the size of the heap */
  ULONG heap_size = (ULONG)(_sbrk_heap_end - _sbrk_heap_start);

  /* Create a memory pool from the heap */
  tx_byte_pool_create(&my_byte_pool, "byte pool", _sbrk_heap_start, heap_size);
}

Finally, modify your application's dynamic memory allocation calls to use the ThreadX memory pool API instead of the standard library allocation functions such as malloc() and free():

void* ptr;
UINT status;

/* Allocate memory from the pool */
status = tx_byte_allocate(&my_byte_pool, &ptr, size_needed, TX_NO_WAIT);

if (status != TX_SUCCESS)
{
  /* Handle allocation error */
}


I hope my answer has helped you. When your question is answered please close this topic by marking as Best the reply that answered you, it will help others find that answer faster. Thanks for your contribution.