Кто любит RISC в жизни, заходим, не стесняемся.
Ответить

Re: Зачем stm32 требует самостоятельно настраивать startup.s

Пт авг 26, 2022 20:48:44

Почему было использовать физические адреса ОЗУ и записывать во флеш, а не по виртуальному адресу.
Зачем для отображения флэш использовать ОЗУ? Его и так мало в контроллере, обычно даже меньше чем флэш. ОЗУ используется для данных, а таблица векторов прерываний, обычно, только для чтения. Если уж хочется "на лету" менять что-то в таблице векторов прерываний, то в вашем контроллере можно перенести её в ОЗУ с помощью регистра VTOR.

Что вы хотите получить отображением флэш на ОЗУ вообще не понятно...

Re: Зачем stm32 требует самостоятельно настраивать startup.s

Пт авг 26, 2022 21:22:33

Линкер берёт его из своего скрипта. Загляните в *.ld-файл. Наверняка, что-то похожее найдёте
Код:
MEMORY
{
  FLASH (RX) : ORIGIN = 0x08000000, LENGTH = 128K
  SRAM (RWX) : ORIGIN = 0x20000000, LENGTH = 20K
}
Да действительно.
Посмотрел nm'ом бинарники для ардуины, там адреса начинаются с близких к нулю.
А вот вывод от блинка из Eclipse для stm32f4
Спойлер08001894 W __aeabi_idiv0
08001894 W __aeabi_ldiv0
08001594 T __aeabi_uldivmod
20000080 b __bss_begin_guard
20000128 B __bss_end__
20000124 b __bss_end_guard
0800041c D __bss_regions_array_end
0800040c D __bss_regions_array_start
20000080 B __bss_start__
20000000 d __data_begin_guard
20000080 D __data_end__
2000007c d __data_end_guard
0800040c D __data_regions_array_end
080003f4 D __data_regions_array_start
20000000 D __data_start__
08001898 T __errno
080024f8 D __etext
080024f8 R __exidx_end
080024f0 R __exidx_start
0800041c d __fini_array_end
0800041c d __fini_array_start
0800041c d __init_array_end
0800041c d __init_array_start
08001100 W __initialize_args
08001448 T __initialize_hardware
080012e4 W __initialize_hardware_early
08000000 T __isr_vectors
20000120 B __lock___malloc_recursive_mutex
2000fc00 A __Main_Stack_Limit
00000400 A __Main_Stack_Size
20000118 B __malloc_free_list
0800223c T __malloc_lock
2000011c B __malloc_sbrk_start
08002248 T __malloc_unlock
0800041c d __preinit_array_end
0800041c d __preinit_array_start
08002264 T __retarget_lock_acquire_recursive
08002266 T __retarget_lock_release_recursive
08001928 T __ssputs_r
20010000 T __stack
080015c4 T __udivmoddi4
08000000 A __vectors_start
08000000 A __vectors_start__
20000128 B _ebss
20000080 D _edata
20000128 B _end_noinit
20010000 A _estack
080024f8 D _etext
080010b8 W _exit
08002000 T _free_r
20000128 B _Heap_Begin
2000fc00 A _Heap_Limit
20000018 D _impure_ptr
080020d4 T _malloc_r
08002254 T _malloc_usable_size_r
00000100 A _Minimum_Stack_Size
20000128 B _noinit
08001be0 T _printf_common
08001cbc T _printf_i
080021bc T _realloc_r
080010bc T _sbrk
0800221c T _sbrk_r
20000080 B _sbss
20000000 D _sdata
080024f8 A _sidata
08000194 W _start
080019e0 T _svfiprintf_r
080019e0 T _svfprintf_r
08001110 t _trace_write_semihosting_debug
080018b4 T _vsniprintf_r
080018b4 T _vsnprintf_r
080003f0 W ADC_IRQHandler
08002444 T AHBPrescTable
2000000c d argv.1
08001458 T assert_failed
08001494 T blink_led_init
08001480 T blink_led_off
0800146c T blink_led_on
20000094 b buf.0
08000344 W BusFault_Handler
08000358 W BusFault_Handler_C
20000088 b current_heap_end.0
080003d8 W DebugMon_Handler
080003f0 W Default_Handler
080003f0 W DMA1_Stream0_IRQHandler
080003f0 W DMA1_Stream1_IRQHandler
080003f0 W DMA1_Stream2_IRQHandler
080003f0 W DMA1_Stream3_IRQHandler
080003f0 W DMA1_Stream4_IRQHandler
080003f0 W DMA1_Stream5_IRQHandler
080003f0 W DMA1_Stream6_IRQHandler
080003f0 W DMA1_Stream7_IRQHandler
080003f0 W DMA2_Stream0_IRQHandler
080003f0 W DMA2_Stream1_IRQHandler
080003f0 W DMA2_Stream2_IRQHandler
080003f0 W DMA2_Stream3_IRQHandler
080003f0 W DMA2_Stream4_IRQHandler
080003f0 W DMA2_Stream5_IRQHandler
080003f0 W DMA2_Stream6_IRQHandler
080003f0 W DMA2_Stream7_IRQHandler
080011d0 T dumpExceptionStack
2000008c B errno
080003f0 W EXTI0_IRQHandler
080003f0 W EXTI1_IRQHandler
080003f0 W EXTI15_10_IRQHandler
080003f0 W EXTI2_IRQHandler
080003f0 W EXTI3_IRQHandler
080003f0 W EXTI4_IRQHandler
080003f0 W EXTI9_5_IRQHandler
080003f0 W FLASH_IRQHandler
080003f0 W FPU_IRQHandler
080004b8 W HAL_GetTick
080005f0 T HAL_GPIO_Init
08000894 T HAL_GPIO_WritePin
080004a0 W HAL_IncTick
0800046c T HAL_Init
08000420 W HAL_InitTick
08001524 T HAL_MspInit
08000500 T HAL_NVIC_SetPriority
080004c4 T HAL_NVIC_SetPriorityGrouping
08000e90 T HAL_RCC_ClockConfig
080010ac T HAL_RCC_GetHCLKFreq
08000dbc W HAL_RCC_GetSysClockFreq
080008cc W HAL_RCC_OscConfig
080005b4 T HAL_SYSTICK_CLKSourceConfig
0800058c T HAL_SYSTICK_Config
080002ce W HardFault_Handler
080002e2 W HardFault_Handler_C
080003f0 W I2C1_ER_IRQHandler
080003f0 W I2C1_EV_IRQHandler
080003f0 W I2C2_ER_IRQHandler
080003f0 W I2C2_EV_IRQHandler
080003f0 W I2C3_ER_IRQHandler
080003f0 W I2C3_EV_IRQHandler
2000001c d impure_data
080012c4 T isSemihosting
080014cc T main
08001f10 T memchr
08001fb0 T memcpy
08000340 W MemManage_Handler
08001fcc T memmove
20000090 b name.0
080002ca W NMI_Handler
080003f0 W OTG_FS_IRQHandler
080003f0 W OTG_FS_WKUP_IRQHandler
080003dc W PendSV_Handler
080003f0 W PVD_IRQHandler
080003f0 W RCC_IRQHandler
080002c4 T Reset_Handler
080003f0 W RTC_Alarm_IRQHandler
080003f0 W RTC_WKUP_IRQHandler
08002094 t sbrk_aligned
080003f0 W SDIO_IRQHandler
080003f0 W SPI1_IRQHandler
080003f0 W SPI2_IRQHandler
080003f0 W SPI3_IRQHandler
080003f0 W SPI4_IRQHandler
080018a4 T strlen
080003d4 W SVC_Handler
080013ac W SystemClock_Config
20000014 D SystemCoreClock
0800130c T SystemCoreClockUpdate
080012fc T SystemInit
08001588 T SysTick_Handler
080003f0 W TAMP_STAMP_IRQHandler
080003f0 W TIM1_BRK_TIM9_IRQHandler
080003f0 W TIM1_CC_IRQHandler
080003f0 W TIM1_TRG_COM_TIM11_IRQHandler
080003f0 W TIM1_UP_TIM10_IRQHandler
080003f0 W TIM2_IRQHandler
080003f0 W TIM3_IRQHandler
080003f0 W TIM4_IRQHandler
080003f0 W TIM5_IRQHandler
20000114 B timer_delayCount
08001560 T timer_sleep
08001528 T timer_start
08001574 T timer_tick
0800117c T trace_printf
080011b0 T trace_puts
08001172 T trace_write
0800038c W UsageFault_Handler
080003a0 W UsageFault_Handler_C
080003f0 W USART1_IRQHandler
080003f0 W USART2_IRQHandler
080003f0 W USART6_IRQHandler
20000084 B uwTick
20000004 D uwTickFreq
20000008 D uwTickPrio
0800190c T vsniprintf
0800190c T vsnprintf
080003f0 W WWDG_IRQHandler
Самый обычный просмотрщик стандартного hex-файла. Открываем в блокноте этот файл и читаем первую строчку:
:020000040800F2
выделенное - и есть адрес (его старшие байты) начала размещения данных.
Возможно, но лучше через nm (обычный тоже пойдёт) сравнить два бинарника для ардуины и stm32. Там видна разница в адресах, и видно что адреса вписаны в бинарник при компиляции.

Re: Зачем stm32 требует самостоятельно настраивать startup.s

Пт авг 26, 2022 22:14:18

Что вы хотите получить отображением флэш на ОЗУ вообще не понятно...

Может быть, псевдоОС с выполнением пользовательских "программ"?

Re: Зачем stm32 требует самостоятельно настраивать startup.s

Пт авг 26, 2022 23:00:43

Почему было использовать физические адреса ОЗУ и записывать во флеш, а не по виртуальному адресу.
Зачем для отображения флэш использовать ОЗУ? Его и так мало в контроллере, обычно даже меньше чем флэш. ОЗУ используется для данных, а таблица векторов прерываний, обычно, только для чтения. Если уж хочется "на лету" менять что-то в таблице векторов прерываний, то в вашем контроллере можно перенести её в ОЗУ с помощью регистра VTOR.

Что вы хотите получить отображением флэш на ОЗУ вообще не понятно...

Было непонятно зачем использовать адресное пространство большее чем ОЗУ. Но может быть действительно так удобнее всё держать в одном адресном пространстве и читать из флеша как из ОЗУ, чем использовать интерфейс вроде файла или EEPROM.

Re: Зачем stm32 требует самостоятельно настраивать startup.s

Сб авг 27, 2022 00:06:23

ddr4 писал(а):Было непонятно зачем использовать адресное пространство большее чем ОЗУ.
Потому что 32 бита позволяют адресовать 4 ГБ.
К некоторым моделям STM32 можно подключать внешнюю память на сотни МБ которая доступна из этого адресного пространства.

ddr4 писал(а):Но может быть действительно так удобнее всё держать в одном адресном пространстве
Удобнее. Например передаешь данные в функцию по указателю и не важно они во флеше или в ОЗУ. В AVR так не получится.

Re: Зачем stm32 требует самостоятельно настраивать startup.s

Сб авг 27, 2022 07:16:52

В AVR так не получится.
А мужики то опять не в курсе :)

1. Можно вот так код в Compiler explorer. Как так получается предлагаю самому подумать.
2. В IAR есть модификатор __generic для указателей, которые могут указывать как на RAM, так и на flash. Они чуть медленнее обычных работают, но работают.
Спойлер
Код:
void char2lcd(char x) {volatile char tmp=x; }

void print(const char __generic *str)
{
  while(*str) char2lcd(*str++);
}

 __flash char str1[] = "FLASH string";
 char str2[] = "SRAM string";

int main()
{
  print(str1);
  print(str2);
}

Re: Зачем stm32 требует самостоятельно настраивать startup.s

Сб авг 27, 2022 10:28:25

Это не совсем то о чем я пишу. Здесь компилятор учитывает где расположены данные. В случае адресного пространства как у STM32 в этом нет необходимости.

Re: Зачем stm32 требует самостоятельно настраивать startup.s

Сб авг 27, 2022 12:30:05

Хотелось бы очистить стандартный ld-script Эклипса от очень полезных, но непонятных секций.

Вот например секции ниже, мне для uart_print ("Hello world.") - примера не потребуются?
Спойлер
Код:
 /*
     * Used for validation only, do not allocate anything here!
     *
     * This is just to check that there is enough RAM left for the Main
     * stack. It should generate an error if it's full.
     */
    ._check_stack : ALIGN(4)
    {
        . = . + _Minimum_Stack_Size ;
    } >RAM
   
    /*
     * The FLASH Bank1.
     * The C or assembly source must explicitly place the code
     * or data there using the "section" attribute.
     */
    .b1text : ALIGN(4)
    {
        *(.b1text)                   /* remaining code */
        *(.b1rodata)                 /* read-only data (constants) */
        *(.b1rodata.*)
    } >FLASHB1
   
    /*
     * The EXTMEM.
     * The C or assembly source must explicitly place the code or data there
     * using the "section" attribute.
     */

    /* EXTMEM Bank0 */
    .eb0text : ALIGN(4)
    {
        *(.eb0text)                   /* remaining code */
        *(.eb0rodata)                 /* read-only data (constants) */
        *(.eb0rodata.*)
    } >EXTMEMB0
   
    /* EXTMEM Bank1 */
    .eb1text : ALIGN(4)
    {
        *(.eb1text)                   /* remaining code */
        *(.eb1rodata)                 /* read-only data (constants) */
        *(.eb1rodata.*)
    } >EXTMEMB1
   
    /* EXTMEM Bank2 */
    .eb2text : ALIGN(4)
    {
        *(.eb2text)                   /* remaining code */
        *(.eb2rodata)                 /* read-only data (constants) */
        *(.eb2rodata.*)
    } >EXTMEMB2
   
    /* EXTMEM Bank0 */
    .eb3text : ALIGN(4)
    {
        *(.eb3text)                   /* remaining code */
        *(.eb3rodata)                 /* read-only data (constants) */
        *(.eb3rodata.*)
    } >EXTMEMB3



Также непонятно назначение секции .inits, в некоторых примерах её нет. Можно ли удалить, чтобы глаза не мозолила?
Спойлер
Код:
    .inits : ALIGN(4)
    {
        /*
         * Memory regions initialisation arrays.
         *
         * Thee are two kinds of arrays for each RAM region, one for
         * data and one for bss. Each is iterrated at startup and the   
         * region initialisation is performed.
         *
         * The data array includes:
         * - from (LOADADDR())
         * - region_begin (ADDR())
         * - region_end (ADDR()+SIZEOF())
         *
         * The bss array includes:
         * - region_begin (ADDR())
         * - region_end (ADDR()+SIZEOF())
         *
         * WARNING: It is mandatory that the regions are word aligned,
         * since the initialisation code works only on words.
         */
         
        __data_regions_array_start = .;
       
        LONG(LOADADDR(.data));
        LONG(ADDR(.data));
        LONG(ADDR(.data)+SIZEOF(.data));
       
        LONG(LOADADDR(.data_CCMRAM));
        LONG(ADDR(.data_CCMRAM));
        LONG(ADDR(.data_CCMRAM)+SIZEOF(.data_CCMRAM));
       
        __data_regions_array_end = .;
       
        __bss_regions_array_start = .;
       
        LONG(ADDR(.bss));
        LONG(ADDR(.bss)+SIZEOF(.bss));
       
        LONG(ADDR(.bss_CCMRAM));
        LONG(ADDR(.bss_CCMRAM)+SIZEOF(.bss_CCMRAM));
       
        __bss_regions_array_end = .;

        /* End of memory regions initialisation arrays. */
   
        /*
         * These are the old initialisation sections, intended to contain
         * naked code, with the prologue/epilogue added by crti.o/crtn.o
         * when linking with startup files. The standalone startup code
         * currently does not run these, better use the init arrays below.
         */
      KEEP(*(.init))
      KEEP(*(.fini))

      . = ALIGN(4);

      /*
         * The preinit code, i.e. an array of pointers to initialisation
         * functions to be performed before constructors.
         */
      PROVIDE_HIDDEN (__preinit_array_start = .);
       
        /*
         * Used to run the SystemInit() before anything else.
         */
      KEEP(*(.preinit_array_sysinit .preinit_array_sysinit.*))
       
        /*
         * Used for other platform inits.
         */
      KEEP(*(.preinit_array_platform .preinit_array_platform.*))
       
        /*
         * The application inits. If you need to enforce some order in
         * execution, create new sections, as before.
         */
      KEEP(*(.preinit_array .preinit_array.*))

      PROVIDE_HIDDEN (__preinit_array_end = .);

      . = ALIGN(4);

      /*
         * The init code, i.e. an array of pointers to static constructors.
         */
      PROVIDE_HIDDEN (__init_array_start = .);
      KEEP(*(SORT(.init_array.*)))
      KEEP(*(.init_array))
      PROVIDE_HIDDEN (__init_array_end = .);

      . = ALIGN(4);

      /*
         * The fini code, i.e. an array of pointers to static destructors.
         */
      PROVIDE_HIDDEN (__fini_array_start = .);
      KEEP(*(SORT(.fini_array.*)))
      KEEP(*(.fini_array))
      PROVIDE_HIDDEN (__fini_array_end = .);

    } >FLASH


Также в Экплипсе секция .rodata находится внутри секции .text, а в других примерах .rodata самостоятельная секция. Что лучше?


Также непонятно зачем нужны разделы типа .bss_CCMRAM (NOLOAD) и .noinit_CCMRAM (NOLOAD) - вторичные неинициализированные секции данных ? Можно ли удалить ?

Спойлер
Код:
    /* The secondary uninitialised data section. */
   .bss_CCMRAM (NOLOAD) : ALIGN(4)
   {
      *(.bss.CCMRAM .bss.CCMRAM.*)
   } > CCMRAM

    .noinit_CCMRAM (NOLOAD) : ALIGN(4)
    {
        *(.noinit.CCMRAM .noinit.CCMRAM.*)         
    } > CCMRAM

Re: Зачем stm32 требует самостоятельно настраивать startup.s

Сб авг 27, 2022 13:42:04

ddr4 писал(а):Хотелось бы очистить стандартный ld-script Эклипса от очень полезных, но непонятных секций.
Чем мешают эти секции?
Они не влияют ни на размер прошивки, ни на скорость ее работы.
Если нет необходимости, не изменяйте ld файл.

Re: Зачем stm32 требует самостоятельно настраивать startup.s

Сб авг 27, 2022 13:49:49

Хотелось бы очистить стандартный ld-script Эклипса от очень полезных, но непонятных секций.
На какой помойке вы его нашли? Возьмите нормальный скрипт и не мучайтесь.
STM32F401CB_flash.zip
(817 байт) Скачиваний: 40

Re: Зачем stm32 требует самостоятельно настраивать startup.s

Сб авг 27, 2022 14:22:54

VladislavS писал(а):
На какой помойке вы его нашли? Возьмите нормальный скрипт и не мучайтесь.
Вложение: STM32F401CB_flash.zip

Это стандартный скрипт для блинк проекта в Эклипсе.

Спасибо за скрипт.
А ниже в нём, это пользовательские секции? то есть не обязательные?

Спойлер
Код:
   .preinit_array :
   {   PROVIDE(__preinit_array_start = .);
      KEEP(*(.preinit_array*))
      PROVIDE(__preinit_array_end = .);
   } > FLASH

   .init_array :
   {   PROVIDE(__init_array_start = .);
      KEEP(*(SORT(.init_array.*)))
      KEEP(*(.init_array*))
      PROVIDE(__init_array_end = .);
   } > FLASH

   .fini_array :
   {   PROVIDE(__fini_array_start = .);
      KEEP(*(.fini_array*))
      KEEP(*(SORT(.fini_array.*)))
      PROVIDE(__fini_array_end = .);
   } > FLASH

   .reserved_for_stack (NOLOAD) :
   {   . = ALIGN(4);
      PROVIDE(__reserved_for_stack_start__ = .);
      KEEP(*(.reserved_for_stack))
      . = ALIGN(4);
      PROVIDE(__reserved_for_stack_end__ = .);
   } > SRAM


А как на счёт такого скрипта, без malloc и С++ ?
Спойлер
Код:
MEMORY
{
    FLASH     (rx)  : ORIGIN = 0x00000000, LENGTH = 256k
    RAM     (xrw)   : ORIGIN = 0x20000000, LENGTH = 64k
}

GROUP(
   libgcc.a
   libg.a
   libc.a
   libm.a
   libnosys.a
 )

__stack = ORIGIN(RAM) + LENGTH(RAM);

SECTIONS
{
    . = ORIGIN(FLASH);
 
    .isr_vectors : ALIGN(4)
    {
        FILL(0xFF)
        __vectors_start__ = ABSOLUTE(.);
        KEEP(*(.vectors))
        *(.after_vectors .after_vectors.*)
    } > FLASH

    /*
     * Start of text.
     */
    _text = .;

    .text : ALIGN(4)
    {
        *(.text)
        *(.text.*)
        *(.glue_7t)
        *(.glue_7)
        *(.gcc*)
    } > FLASH

    /*
     * Arm section unwinding.
     * If removed may cause random crashes.
     */
    .ARM.extab :
    {
        *(.ARM.extab* .gnu.linkonce.armextab.*)
    } > FLASH

    /*
     * Arm stack unwinding.
     * If removed may cause random crashes.
     */
    .ARM.exidx :
    {
        __exidx_start = .;
        *(.ARM.exidx* .gnu.linkonce.armexidx.*)
        __exidx_end = .;
    } > FLASH

    /*
     * Read-only data. Consts should also be here.
     */
    .rodata : ALIGN(4)
    {
        . = ALIGN(4);
        __rodata_start__ = .;
        *(.rodata)
        *(.rodata.*)
        . = ALIGN(4);
        __rodata_end__ = .;
    } > FLASH

    /*
     * End of text.
     */
    _etext = .;

    /*
     * Data section.
     */
    .data : ALIGN(4)
    {
        FILL(0xFF)
        . = ALIGN(4);
        PROVIDE(__textdata__ = LOADADDR(.data));
        PROVIDE(__data_start__ = .);
        *(.data)
        *(.data.*)
        *(.ramtext)
        . = ALIGN(4);
        PROVIDE(__data_end__ = .);
    } > RAM AT > FLASH

    /*
     * BSS section.
     */
    .bss (NOLOAD) : ALIGN(4)
    {
        . = ALIGN(4);
        PROVIDE(_bss_start = .);
        __bss_start__ = .;
        *(.bss)
        *(.bss.*)
        *(COMMON)
        . = ALIGN(4);
        PROVIDE(_bss_end = .);
        __bss_end__ = .;
        PROVIDE(end = .);
    } > RAM

      .noinit (NOLOAD) : ALIGN(4)
    {
        __noinit_start__ = .;
        *(.noinit .noinit.*)
         . = ALIGN(4) ;
        __noinit_end__ = .;   
    } > RAM
  }

В чём, в данном контексте, отличие SRAM от RAM ?

Кстати если я заменю все (в том числе в .isr_vertors ) "> FLASH" на "> SRAM" это будет работать?
Последний раз редактировалось ddr4 Сб авг 27, 2022 14:49:29, всего редактировалось 1 раз.

Re: Зачем stm32 требует самостоятельно настраивать startup.s

Сб авг 27, 2022 14:58:10

А ниже в нём, это пользовательские секции? то есть не обязательные?
Эти секции создаёт компилятор. В них содержится информация, необходимая стартовому коду для инициализации глобального окружения. Посмотрите .map файл, они там есть.

Откуда у вас такое маниакальное желание что-то удалить, даже не понимая зачем это нужно? Всё что вам нужно сделать с этим скриптом - поставить правильный размер FLASH и SRAM для вашего контроллера. Если в скрипте описаны какие-то незадействованные в коде секции, то их всё равно не будет в итоговой прошивке. Это всего лишь правила, по которым линкер размещает их в адресном пространстве, при их наличии в коде. Они жрать не просят. Ничего лишнего в загруженном мной скрипте нет, займитесь уже программированием.

Добавлено after 1 minute 58 seconds:
В чём, в данном контексте, отличие SRAM от RAM ?
Ни в чём, воспринимайте это как имя области памяти, примерно как имя переменной в программе. Можете назвать как хотите, чтобы даже враг не догадался что это :)

Добавлено after 3 minutes 13 seconds:
Кстати если я заменю все (в том числе в .isr_vertors ) "> FLASH" на "> SRAM" это будет работать?
Будет. При отладке программы в SRAM так и делают. Посмотрите приложенный скрипт и сравните с тем что я первым выложил. Вот этот настроен на загрузку кода для отладки в SRAM.
STM32F401CB_sram.zip
(804 байт) Скачиваний: 39


Добавлено after 3 minutes 49 seconds:
А как на счёт такого скрипта, без malloc и С++ ?
Ответьте на простой вопрос - ЗАЧЕМ? Зачем вы пытаетесь не рассказать линкеру что делать с "кучей", если она появится в коде? Эти строки в скрипте жрать просят?

Re: Зачем stm32 требует самостоятельно настраивать startup.s

Сб авг 27, 2022 16:11:26

Чем мешают эти секции?
Если нет необходимости, не изменяйте ld файл.
Тем что я эти секции не использую, зачем они мне? К тому же эти не используемые секции завязаны на стартап, в котором есть переменные этих секций.

Они не влияют ни на размер прошивки, ни на скорость ее работы.
То есть если я удалю множество неиспользуемых секций, а в остальных заменю >FLASH на >RAM, скорость запуска приложения не изменится?

VladislavS писал(а): Посмотрите .map файл, они там есть.
У меня нет такого файла.

VladislavS писал(а):Откуда у вас такое маниакальное желание что-то удалить, даже не понимая зачем это нужно?
Чтобы оставить только то что нужно, раз STM32 в отличии от AVR-gcc предоставляет возможность управления запуском, то значить это нормально удалять всё что не нужно. Пытаюсь упростить код по максимуму. Для меня этот Blink с кучей файлов выглядит сложно. "Хеллоу Ворлд" будет ещё сложней.

VladislavS писал(а):При отладке программы в SRAM так и делают. Посмотрите приложенный скрипт и сравните с тем что я первым выложил. Вот этот настроен на загрузку кода для отладки в SRAM.
Да всё заменено на SRAM, то есть получается в случае замены FLASH на RAM, при запуске программы секции размещаются в оперативке, а до этого размещались во FLASH ?

А как на счёт такого скрипта, без malloc и С++ ?
Ответьте на простой вопрос - ЗАЧЕМ? Зачем вы пытаетесь не рассказать линкеру что делать с "кучей", если она появится в коде? Эти строки в скрипте жрать просят?
Если у меня в коде нет malloc(), надеюсь в этой куче обёрток её тоже нет. Поэтому мне куча и не нужна. В Арудине я malloc() не использовал, то и здесь не требуется.

Re: Зачем stm32 требует самостоятельно настраивать startup.s

Сб авг 27, 2022 16:35:35

Тем что я эти секции не использую, зачем они мне? К тому же эти не используемые секции завязаны на стартап, в котором есть переменные этих секций.
Они нужны не вам, а линкеру. Чтобы он правильно собрал вашу программу.

То есть если я удалю множество неиспользуемых секций, а в остальных заменю >FLASH на >RAM, скорость запуска приложения не изменится?
Что такое в вашем понимании скрость запуска приложения? При включении код лежит в флэш и с первых же тактов начинает работать c Reset_Handler. Это и есть приложение. Где тут скорость запуска измерить. А изменится то, что оно либо не соберётся, либо не будет работать.

VladislavS писал(а): Посмотрите .map файл, они там есть.
У меня нет такого файла.
Он создаётся при компиляции при указании соответствующего ключа. Вот это, в отличии от ковыряния скриптов, стоит сделать. Там много интересной информации.


Чтобы оставить только то что нужно, раз STM32 в отличии от AVR-gcc предоставляет возможность управления запуском, то значить это нормально удалять всё что не нужно. Пытаюсь упростить код по максимуму. Для меня этот Blink с кучей файлов выглядит сложно. "Хеллоу Ворлд" будет ещё сложней.
Ну так и ковыряйте программу, чего вы до линкерскрипта то докопались? Он лишь задаёт правила размещения того что есть в коде. Всё что есть в коде должно быть размещено в памяти. Чего нет, того и так нет. Линкерскрипт вообще никак не влияет на упрощение программы.

Да всё заменено на SRAM, то есть получается в случае замены FLASH на RAM, при запуске программы секции размещаются в оперативке, а до этого размещались во FLASH ?
Да. Только вы должны понимать, что сама по себе программа в оперативке не появится. Кто-то или что-то должны её туда перед запуском поместить.

Если у меня в коде нет malloc(), надеюсь в этой куче обёрток её тоже нет. Поэтому мне куча и не нужна. В Арудине я malloc() не использовал, то и здесь не требуется.
Ну и не используйте дальше. От того что вы упомянете её в скрипте линкера она в коде не появится.

Re: Зачем stm32 требует самостоятельно настраивать startup.s

Сб авг 27, 2022 17:17:01

У меня в проектах вообще нет ассемблерного стартапа. И ничего, IAR прекрасно работает с сишным самописным стартапом.

Re: Зачем stm32 требует самостоятельно настраивать startup.s

Сб авг 27, 2022 17:44:23

VladislavS писал(а):Что такое в вашем понимании скрость запуска приложения? При включении код лежит в флэш и с первых же тактов начинает работать c Reset_Handler. Это и есть приложение.
Я же не знаю как оно в реальности запускается, возможно в линкере указывается куда МК (операционная система) должна разместить секции программы после её запуска. На деле МК размещает секции по адресам в адресном пространстве, желательно чтобы МК размещал секции в ОЗУ, так как во-первых ОЗУ быстрей FLASH'a, а значит скорость программы возрастает, а во-вторых FLASH имеет ограниченный ресурс на число записей. То есть МК с размещением секций в ОЗУ проживёт дольше.
Но видимо указание линкеру разместить секцию в >RAM, ещё не является гарантией что она будет находится именно в ОЗУ ..? Так как нельзя сказать точно на какое устройство отражается кусок адресного пространства.

VladislavS писал(а):Он создаётся при компиляции при указании соответствующего ключа. Вот это, в отличии от ковыряния скриптов, стоит сделать. Там много интересной информации.
Спасибо. Действительно интересная информация.

VladislavS писал(а):Да. Только вы должны понимать, что сама по себе программа в оперативке не появится. Кто-то или что-то должны её туда перед запуском поместить.

В коде стартапа секция данных копируется по адресу (не факт что ОЗУ), а секция bss зануляется. Остальные секции возможно размещает сам МК, может у него есть какие-то внутренние механизмы?

VladislavS писал(а):Ну и не используйте дальше. От того что вы упомянете её в скрипте линкера она в коде не появится.
В коде целый файл sbrk.c под подготовку кучи, + в .map-файле heap'a навалено. Вроде оно всё не мешает, но когда этого всего "не мешает" - много, оно как-то начинает мешать.
Последний раз редактировалось ddr4 Сб авг 27, 2022 17:54:56, всего редактировалось 1 раз.

Re: Зачем stm32 требует самостоятельно настраивать startup.s

Сб авг 27, 2022 17:54:17

ddr4 писал(а):Тем что я эти секции не использую, зачем они мне?
Вот вы подключили библиотеку с функциями, струкурами, дефайнами и др. и почти все их не используете. Будете выпиливать не задействованные и без разницы что компиль это сам может сделать?
С секциями тоже самое. Если не используются, они не попадут в прошивку (при адекватных ключах компиля и линкера). А если используются, прошивку не соберете.

ddr4 писал(а):То есть если я удалю множество неиспользуемых секций
Если секции действительно не используются то просто зря потратите время, т. к. они все равно в прошивку не попадут (повторюсь, при правильных ключах компиля и линкера).

ddr4 писал(а):а в остальных заменю >FLASH на >RAM, скорость запуска приложения не изменится?
Загружать прошивку как планируете? Обычно прошивку помещают в ОЗУ при отладке (ее загружает отладчик) или необходимости полностью переписать флешь.

ddr4 писал(а):У меня нет такого файла.
Создается при компиляции.

ddr4 писал(а):значить это нормально удалять всё что не нужно.
Нормально это когда этим занимается компиль вместе с линкером. Но вы упорно хотите выполнять их работу! :shock: :facepalm:

ddr4 писал(а):Для меня этот Blink с кучей файлов выглядит сложно. "Хеллоу Ворлд" будет ещё сложней.
Какая разница сколько файлов в проекте?

ddr4 писал(а):В Арудине я malloc() не использовал
То есть строками не пользовались, print в любом виде не использовали, классы динамически не создавали и много чего другого не делали что выделяло память из кучи?

Re: Зачем stm32 требует самостоятельно настраивать startup.s

Сб авг 27, 2022 18:09:33

VladislavS писал(а):Они нужны не вам, а линкеру.

С секциями init_array - даже у меня вопросы имеются.
Применительно к ARM, потому как для компов может быть всё иначе.
Для собирательных секций data, rodata, bss, text - есть чёткое определение в доках GCC, чего и в каком качестве туда помещается. Для остальных секций выполняется простое условие, имя секции должно совпадать с именем объекта (функция, переменная, чистая/грязная память, константы и вектора).
Секции array - тоже собирательные, потому как объектов с похожим названием нет ни в одном проекте, и даже в самом GCC.
Однако точного описания в доках GCC нету. (прям именно там, на сайте GCC). Отчего у меня лично возникает ощущение что секцию забыли удалить. Без неё код собирается, и даже не меняет свой состав на бинарном уровне.

Есть вариант что оно висит (или раньше было там) на уровне спецификаций (*.specs) - код подключаемый вне желания программиста. Изначально спецификации были предназначены для того чтобы у всех всё было одинаково. Но случилась неприятность, и бардак возник за забором - чипов и их модификаций развелось как собак не резаных. Писать спеки на каждый чих ARM зоопарка - желающих не нашлось. Отчего настройки спустились на пользовательский уровень, а в *.specs осталась заглушка.

Re: Зачем stm32 требует самостоятельно настраивать startup.s

Сб авг 27, 2022 18:13:03

Если не нравится что-то, просто поочередно удаляйте секцию за секцией и смотрите, когда при очередном компилировании ошибки полезут. Заодним и разберетесь, что для чего там надобно.

Re: Зачем stm32 требует самостоятельно настраивать startup.s

Сб авг 27, 2022 18:21:54

Мурик писал(а):Вот вы подключили библиотеку с функциями, струкурами, дефайнами и др. и почти все их не используете. Будете выпиливать не задействованные и без разницы что компиль это сам может сделать?
С секциями тоже самое. Если не используются, они не попадут в прошивку (при адекватных ключах компиля и линкера). А если используются, прошивку не соберете.

Во-первых библиотека на то и библиотека что скрывает от её пользователя всю реализацию, например это стандартная библиотека и она прикомпиливается при сборке и лежит в библах/компилятора, а не в файлах проекта. Когда флеша не хватает, то из библиотеки берётся одна функция, без подключения хедера зависимого от других хедеров. Иногда это экономит и память и флеш.

Мурик писал(а):Если секции действительно не используются то просто зря потратите время, т. к. они все равно в прошивку не попадут (повторюсь, при правильных ключах компиля и линкера). ... Какая разница сколько файлов в проекте?

Возможно это сложно понять, но мне не хочется видеть лишнего кода при вхождении в новую тему. И чем его меньше (при сохранении читаемости - неассемблер) тем лучше.

Мурик писал(а):Загружать прошивку как планируете? Обычно прошивку помещают в ОЗУ при отладке (ее загружает отладчик) или необходимости полностью переписать флешь.

Пока не знаю, хотел сначала с эмулятором поиграться, а после уже через uart-ttl через сериал. Говорят в F4 есть встроенный загрузчик он это позволяет.

Мурик писал(а):То есть строками не пользовались, print в любом виде не использовали, классы динамически не создавали и много чего другого не делали что выделяло память из кучи?
Динамически создавал структуры malloc(), но память быстро кончилась пришлось от этого быстро отказаться ). printf() заменить самодельный uart_print(). Иначе всё в 2 кБ не впихнуть.
Последний раз редактировалось ddr4 Сб авг 27, 2022 18:27:32, всего редактировалось 1 раз.
Ответить