Jump to content

    
Mysteo

Проблема с функциями stdlib + FreeRTOS

Recommended Posts

А в cubeIDE если не использовать -specs=nosys.specs и nano.specs , то все равно все работает.

 

В общем это не в компиляторах даже дело, а похоже, чего то в скрипте cmake все таки не хватает . Но если смотреть опции которые создаются в cubeIDE
 

--specs=nosys.specs -Wl,-Map="malloc_test.map" -Wl,--gc-sections -static --specs=nano.specs -mfpu=fpv4-sp-d16 -mfloat-abi=hard -mthumb -Wl,--start-group -lc -lm -Wl,--end-group

то в cmake файле  в clion они тоже прописаны. А толку от этого нет, разве что использование nano.specs пару килобайт памяти экономит

Share this post


Link to post
Share on other sites
10 часов назад, Mysteo сказал:

чтобы была удобная современная и всем понятная IDE )

VScode посмотрите. Она кроссплатформенная, современная, бесплатная.

Share this post


Link to post
Share on other sites

Спасибо , все равно нужно как то решить проблему, ведь по сути компилятор один и тот же в IDEшках , а проблема скорее всего в скрипте cmake. Хотелось бы понять что не так 

Share this post


Link to post
Share on other sites
16 hours ago, x893 said:

Три раза перечитал, но так и не понял в чём разница между двумя вариантами вызова malloc.

 


Разницы нету, только в одном случае я вызываю вне задачи FreeRTOS , а в другом случае непосредственно в задаче.
И если вне задачи хоть раз вызвать malloc , то и в задачах память нормально выделяется, а если не выполнять вне задачи , то всегда в задачах будет возвращать NULL, несмотря на то , что памяти предостаточно .

В IDE CLion такая прболема возникает, а в других IDE с тем же компилятором ее нет. 

Share this post


Link to post
Share on other sites
On 8/30/2020 at 11:19 AM, AHTOXA said:

Ищите реализацию функции _sbrk() (или _sbrk_r()), и смотрите, почему она может не сработать при вызове из задачи оси.

Спасибо , порешали. 
Почему-то когда кубом создаешь проект под опредленные IDE , то sbrk имеет одну реализацию:

void *_sbrk(ptrdiff_t incr)
{
    extern uint8_t _end; /* Symbol defined in the linker script */
    extern uint8_t _estack; /* Symbol defined in the linker script */
    extern uint32_t _Min_Stack_Size; /* Symbol defined in the linker script */
    const uint32_t stack_limit = (uint32_t)&_estack - (uint32_t)&_Min_Stack_Size;
    const uint8_t *max_heap = (uint8_t *)stack_limit;
    uint8_t *prev_heap_end;

    /* Initalize heap end at first call */
    if (NULL == __sbrk_heap_end)
    {
        __sbrk_heap_end = &_end;
    }

    /* Protect heap from growing into the reserved MSP stack */
    if (__sbrk_heap_end + incr > max_heap)
    {
        errno = ENOMEM;
        return (void *)-1;
    }

    prev_heap_end = __sbrk_heap_end;
    __sbrk_heap_end += incr;

    return (void *)prev_heap_end;
}

 

а когда под SW4STM32 

 

caddr_t _sbrk(int incr)
{
   extern char end asm("end");
   static char *heap_end;
   char *prev_heap_end;

   if (heap_end == 0)
      heap_end = &end;

   prev_heap_end = heap_end;
   if (heap_end + incr > stack_ptr)
   {
//    write(1, "Heap and stack collision\n", 25);
//    abort();
      errno = ENOMEM;
      return (caddr_t) -1;
   }

   heap_end += incr;

   return (caddr_t) prev_heap_end;
}

 

Я на это не обратил внимания, т.к не думал , Что такое может произойти. 

Share this post


Link to post
Share on other sites
5 часов назад, Mysteo сказал:

а когда под SW4STM32 

Наверно в этой среде файл линкера какой-то свой.

Здесь, в этой функции, внешние переменные берутся из файла линкера. (я не задумывался особо как работает эта функция и просто решил теперь вместе с автором темы также разбираться)

Share this post


Link to post
Share on other sites

Я просмотрел реализацию этой функции в более старых (еще от CubeMX 5.x) проектах и она такая же как тут у Вас, для SW4STM32:

/* Variables */
extern int errno;
register char * stack_ptr asm("sp");

/**
 _sbrk
 Increase program data space. Malloc and related functions depend on this
**/
caddr_t _sbrk(int incr)
{
    extern char end asm("end");
    static char *heap_end;
    char *prev_heap_end;

    if (heap_end == 0)
        heap_end = &end;

    prev_heap_end = heap_end;
    if (heap_end + incr > stack_ptr)
    {
        errno = ENOMEM;
        return (caddr_t) -1;
    }

    heap_end += incr;

    return (caddr_t) prev_heap_end;
}

На это и указывал @Arlleex в своем сообщении тут:

28.08.2020 в 09:56, Arlleex сказал:

Что-то подобное от кого-то уже слышал. Возможно, это поможет.

Цитата из той ссылки:

CubeMX does not properly set up these support functions for a FreeRTOS project.
See: Bug Report to STM regarding CubeMX FreeRTOS projects and the STM bug discussion below.

 

В коде для 746-й Дискавери (файл 'syscalls.c') эта функция также несколько по-ругому сделана и причем там уже упоминается FreeRTOS.

@Mysteo а у Вас во FreeRTOS какая модель памяти используется? Для уточнения дальнейших вариантов не помешает эта информация тоже.

 

 

Share this post


Link to post
Share on other sites

Вот еще такой комментарий, как информация, к тоже другой реализации этой функции:

Цитата

This function overrides the _sbrk version that exists in the newlib library that is linked with.        
That version improperly relies on the SP as part of it's allocation strategy. This is bad in general and
worse in an RTOS environment. This version insures that we allocate the byte pool requested by malloc() 
only from our allocated HEAP area. Also note that newlib is pre-built and forces the pagesize used by   
malloc() to be 4096. That requires that we have a HEAP of at least 4096 if we are to support malloc().  

 

Share this post


Link to post
Share on other sites

Да я что-то мельком просмотрел и не предал значения тому описанию, т.к в других IDE работало, а в голову придти не могло, что Cube генерит для разных IDE разные функции

Теперь буду изучать инструменты отладки FreeRTOS  , в частности контроль стека, а то не понятно куда память тратиться и ее вечно не хватает. Скорее всего создам новую тему

Share this post


Link to post
Share on other sites
6 minutes ago, Mysteo said:

а то не понятно куда память тратиться и ее вечно не хватает

FreeRTOS не самая лучшая система. Но если спользуете её, крайне рекомендую задуматься о статической сборке. Тогда вся информацию об израсходованной информации будет видна в map-файле.

Share this post


Link to post
Share on other sites
9 minutes ago, haker_fox said:

FreeRTOS не самая лучшая система. Но если спользуете её, крайне рекомендую задуматься о статической сборке. Тогда вся информацию об израсходованной информации будет видна в map-файле.

А если в проекте заложено использование библиотек, которое предполагает динамическое распределение памяти, все равно можно будет статическую сборку использовать?

Share this post


Link to post
Share on other sites
8 minutes ago, Mysteo said:

все равно можно будет статическую сборку использовать?

Конечно. Ибо те библиотеки будут испоользовать динамическую память как и ранее. А FreeRTOS - статическую (на этапе компиляции).

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.