STM32F429-Disco - Расширение ОЗУ с SDRAM Linker Скрипт неправильный? - PullRequest
0 голосов
/ 05 июня 2019

Я пытаюсь использовать SDRAM с моей платы STM32F429-Disco. Я создал функцию для инициализации SDRAM, которая выполняется в основной функции. Реализация SDRAM была сделана со следующей инструкцией: http://en.radzio.dxp.pl/stm32f429idiscovery/sdram.html и должна работать, так как я могу записать в SDRAM. Функция инициализации SDRAM выполняется в основной функции.

Я не уверен, но я думаю, что проблема в моем скрипте компоновщика или syscall.c

Я изменил следующие вещи в файлах, syscall.c - следующий код:

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;
    }

на следующий syscall.c:

    caddr_t _sbrk(int incr)
    {
    //  extern char end asm("end"); // June 2019 - US

        extern char __heap_start asm ("__heap_start");
        extern char __heap_limit asm ("__heap_limit");

        static char *heap_end;
        static char *heap_limit = &__heap_limit;
        char *prev_heap_end;

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

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

        heap_end += incr;

        return (caddr_t) prev_heap_end;
    }

А для скрипта компоновщика я изменил:

   heap was commented out
   heap_start and heap_limit was added
   SDRAM was added to the memory areas
   user_stack was altered
    /*_Min_Heap_Size = 0x200;      /* required amount of heap   commented out*/

    __heap_start = 0xD0000000; /*Was added*/
    __heap_limit = 0xD0800000; /*Was added*/

    /* Specify the memory areas - SDRAM was added */
    MEMORY
    {
    FLASH (rx)      : ORIGIN = 0x8000000, LENGTH = 2048K
    RAM (xrw)      : ORIGIN = 0x20000000, LENGTH = 192K
    CCMRAM (rw)      : ORIGIN = 0x10000000, LENGTH = 64K
    SDRAM (xrw)     : ORIGIN = 0xD000000, LENGTH = 8M
    }

    /* User_stack section, used to check that there is enough RAM left was altered */
      ._user_stack :
      {
        . = ALIGN(8);
        PROVIDE ( end = . );
        PROVIDE ( _end = . );
        . = . + _Min_Stack_Size;
        . = ALIGN(8);
      } >RAM

Но у меня проблема, когда я создаю большой массив - глобально - с помощью:

    volatile uint16_t test[76800];

Я все еще получаю переполнение ОЗУ, которое не должно происходить, так как SDRAM должен использоваться.

Как я могу это исправить, чтобы использовать SDRAM в качестве расширения ОЗУ?

Спасибо

1 Ответ

0 голосов
/ 05 июня 2019

Я все еще получаю переполнение ОЗУ, что не должно произойти, так как SDRAM должен использоваться.

В вашем коде нет ничего, что указывало бы компоновщику поместить большой массив в область SDRAM, поэтому он все равно попытался бы выделить его в RAM. Создайте для него раздел в файле компоновщика

.bigdata :
{
  . = ALIGN(4);
  *(.bigdata)
  *(.bigdata*)
  . = ALIGN(4);
} >SDRAM

и скажите компилятору, чтобы он поместил туда массив

volatile uint16_t test[76800] __attribute__((section(".bigdata")));

Точно так же вы должны создать надлежащий раздел для кучи, которая будет размещена в SDRAM

._user_heap :
{
  . = ALIGN(64);
  PROVIDE ( __heap_start = . );
  . = . + Heap_Size;
  PROVIDE ( __heap_limit = . );
  . = ALIGN(4);
} >SDRAM

В противном случае они перекрываются.

Имейте в виду, что переменные за пределами обычной области данных не будут инициализироваться кодом запуска, поэтому они будут содержать все ненужное, что было в SDRAM при включении питания.

Также обратите внимание, что ваше определение ORIGIN = 0xD000000 содержит слишком мало нулей.

...