Компоновщик ARM RealView: расположение в любом из нескольких регионов

#linker #arm #embedded #cortex-m #bit-banding

#компоновщик #рука #встроенный #cortex-m #кольцевание долот

Вопрос:

Есть ли способ разрешить компоновщику ARM RealView / Keil выбирать из более чем одного, но не из всех регионов?

Я могу использовать .ANY спецификатор, чтобы предоставить компоновщику свободу действий, и я могу использовать *(section_name) спецификатор для определения местоположения определенных объектов в одном регионе, но я хотел бы иметь возможность выбирать компоновщик из нескольких подходящих регионов.

Чтобы было понятно, почему это желательно, я использую микроконтроллер STM32F4xx с тремя отдельными, но смежными областями SRAM на отдельных шинах и еще одной областью памяти, связанной с ядром, которая не имеет битовой полосы пропускания или доступна через DMA. Я хочу использовать меньшую область SRAM для DMA, чтобы избежать конфликтов на шинах и улучшить производительность и детерминированное поведение. Эта область неудобно расположена между двумя более крупными областями, и я хочу иметь возможность использовать любую из более крупных областей для группирования битов, позволяя при этом свободно использовать память CCM для любых целей, отличных от DMA или группирования битов. В настоящее время регионы указаны следующим образом:

   RW_IRAM0 CCM_START CCM_SIZE  
  {
   .ANY ( RW  ZI)
   *(core_coupled_ram)
  }

  ; SRAM1 112Kbytes (Buses: I, D, S, DMA)
  RW_IRAM1 SRAM1_START SRAM1_SIZE  
  {
   .ANY ( RW  ZI)
  }

  ; SRAM2 16Kbytes (Buses: S, DMA)
  RW_IRAM2  SRAM2_START SRAM2_SIZE  
  {
   *(dma_ram)
  }

  ; SRAM3 64Kbytes (Buses: S, DMA)
  RW_IRAM3 SRAM3_START SRAM3_SIZE  
  {
   .ANY ( RW  ZI)
  }
 

Добавление *(bitbandable_ram) к SRAM1 и SRAM3 отклоняется компоновщиком с помощью:

 Error: L6223E: Ambiguous selectors found for ctransmissionschedulertask.o(bitbandable_ram) from Exec regions RW_IRAM1 and RW_IRAM3.
 

Аналогично, создание перекрывающейся области не работает:

  ; SRAM 192Kbytes 

  RW_IRAM_ALL SRAM_START (SRAM1_SIZE   SRAM2_SIZE   SRAM3_SIZE)
  {
   .ANY ( RW  ZI)
    *(bitbandable_ram)  
  }
 

отчетность:

 Error: L6221E: Execution region RW_IRAM1 with Execution range [0x20000000,0x200045e0) overlaps with Execution region RW_IRAM_ALL with Execution range [0x20000000,0x20018608).
 

В настоящее время мои неидеальные решения:

  1. назначить только одну область для битового бэндинга,
  2. чтобы сделать всю непрерывную SRAM единой областью (позволяя выполнять операции DMA в любой памяти, что делает ее менее детерминированной), таким образом:
      ; SRAM 192Kbytes 
    
      RW_IRAM_ALL SRAM_START (SRAM1_SIZE   SRAM2_SIZE   SRAM3_SIZE)
      {
       .ANY ( RW  ZI)
        *(bitbandable_ram)  
        *(dma_ram)  
      }
     
  3. Удаление .ANY селектора из области CCM требует, чтобы объект был явно расположен там, используя core_coupled_ram именованный раздел.

Комментарии:

1. Согласен, макет оперативной памяти STM немного «особенный». Но вы действительно ожидаете серьезной проблемы с конфликтом шины? Просто поместите переменные стека и статические переменные в CCM и используйте системную SRAM как одну непрерывную область.

2. @Olaf: Я, вероятно, тоже сомневаюсь в требовании, но вопрос актуален, даже если в этом не было строгой необходимости; Конечно, у меня есть другие варианты. Это приложение для обработки сигналов; два сигнала от считываются со скоростью 48 кбит / с каждый из АЦП с использованием DMA, DMA также используется для SPI и USB. Опыт работы с несколькими целевыми объектами STM32 показал, что такое расположение является выгодным. Существуют и другие жесткие сроки в реальном времени, требующие детерминизма порядка нескольких десятков микросекунд. Одного места CCM недостаточно, и нет единого стека — это RTOS с запущенными потоками 15 или около того.

3. Я не хотел подразумевать, что это недействительно. И, не зная подробностей, я не скажу, что это не так. Просто это: я использую эти устройства с более чем 15 потоками, все стеки в CCM, это не проблема. (в этом есть еще одно преимущество: DMA не может повредить это пространство.) Хотя не совсем понятно, в чем проблема. Обычно из-за ограничений требуется вручную указать регион. В gcc / gnu-ld используются пользовательские разделы в исходном _attribute__ коде. Я не уверен, что толку оставлять это компоновщику.

4. @Olaf: __attribute__ (armcc использовал синтаксис GNU) — это именно то, что я использую — имена разделов все равно должны быть определены в компоновщике, и компоновщик по-прежнему выполняет поиск — __attribute__(section)) это директива компоновщика. Что мне действительно нужно, так это атрибут, который говорит «найдите этот объект в любом регионе с указанной меткой» , а затем в файле scatter назначьте метки определенным регионам. Имя раздела может быть применено только к одному региону.

5. Хм, возможно, я ошибаюсь, но у меня слабая память, по крайней мере, в GNU-ld (я не знаю инструментов Keil) есть возможность упомянуть раздел ввода в нескольких разделах вывода. Компоновщик поместит его в первую, в которую он вписывается. Как уже было сказано, я не уверен, что правильно помню, но, возможно, стоит попробовать. Альтернативой может быть создание управляющего файла из небольшой программы, например, Python.