Миландр
http://forum.milandr.ru/

Работа с DAC при выполнении кода из внешнего ПЗУ
http://forum.milandr.ru/viewtopic.php?f=34&t=3957
Страница 3 из 3

Автор:  andelie [ 2019-май-14 13:32 ]
Заголовок сообщения:  Re: Работа с DAC при выполнении кода из внешнего ПЗУ

Shrek
Так-то да, но недостатки будут следующие:
1. Придется отдельную RAM-секцию делать для каждой функции-обработчика прерываний, ибо нельзя, по крайней мере, в Keil расположить Си-функцию по фиксированному адресу.
2. Будут дополнительные затраты RAM, что не очень хорошо для маленьких камней.
3. Код из RAM, как не странно, может выполняться медленнее, чем из FLASH.

Автор:  Shrek [ 2019-май-14 14:51 ]
Заголовок сообщения:  Re: Работа с DAC при выполнении кода из внешнего ПЗУ

andelie писал(а):
Shrek
Так-то да, но недостатки будут следующие:
1. Придется отдельную RAM-секцию делать для каждой функции-обработчика прерываний, ибо нельзя, по крайней мере, в Keil расположить Си-функцию по фиксированному адресу.
2. Будут дополнительные затраты RAM, что не очень хорошо для маленьких камней.
3. Код из RAM, как не странно, может выполняться медленнее, чем из FLASH.


3. :shock: при длинных переходах нет задержек на чтение как из FLASH
2. Так-то да. Оптимизация должна как то помочь.
1. За keil не скажу для GCC нужна одна секция и линковщик сам функции размещает в секции. Надо всего лишь весь сегмент выгрузить из FLASH в RAM.

Автор:  andelie [ 2019-май-14 15:31 ]
Заголовок сообщения:  Re: Работа с DAC при выполнении кода из внешнего ПЗУ

3. Для 1986ВЕ4 еще не пробовал, но на 1986ВЕ92 код из RAM выполняется реально медленней, чем из Flash. Специально проверял.
1.
Цитата:
За keil не скажу для GCC нужна одна секция и линковщик сам функции размещает в секции. Надо всего лишь весь сегмент выгрузить из FLASH в RAM.

А как указать конкретный абсолютный адрес, по которому будет располагаться функция-обработчик прерывания в каждом из проектов? Если функция в секции всего одна, то все просто, но если функций в секции несколько, то так уже не получается.
2. Возможности оптимизации будем считать исчерпанными :) .

Автор:  Shrek [ 2019-май-14 16:40 ]
Заголовок сообщения:  Re: Работа с DAC при выполнении кода из внешнего ПЗУ

andelie писал(а):
3. Для 1986ВЕ4 еще не пробовал, но на 1986ВЕ92 код из RAM выполняется реально медленней, чем из Flash. Специально проверял.
1.
Цитата:
За keil не скажу для GCC нужна одна секция и линковщик сам функции размещает в секции. Надо всего лишь весь сегмент выгрузить из FLASH в RAM.

А как указать конкретный абсолютный адрес, по которому будет располагаться функция-обработчик прерывания в каждом из проектов? Если функция в секции всего одна, то все просто, но если функций в секции несколько, то так уже не получается.
2. Возможности оптимизации будем считать исчерпанными :) .


Линковщик сам переопределяет адреса функций в таблице векторов прерываний. Чтобы таблица векторов была полной ее заполняют функциями заглушками которые при вызове прерывания не вызывают Hard Fault. Эти функции "заглушки" имеют атрибут "weak" то есть могут быть переопределены в другом месте. При переопределении линковщик сам подменяет нужный адрес.

Код:
#ifndef __VECTORS_H__
#define __VECTORS_H__

//------------------------------------------------------------------------------
// Declaration
//------------------------------------------------------------------------------
void LowLevelInit (void);
void Fault_Handler (void);
extern void main (void);
extern unsigned int _etext, _data, _sstack, DATA_SIZE;

//------------------------------------------------------------------------------
// Weaked Functions
//------------------------------------------------------------------------------
__attribute__ ((weak)) extern void NMI_Handler (void) {while(1);}
__attribute__ ((weak)) extern void Default_Handler (void) {while(1);}
void SVC_Handler (void)   __attribute__ ((naked, weak, alias("Default_Handler")));
void PSV_Handler (void)   __attribute__ ((naked, weak, alias("Default_Handler")));
void SYS_Handler (void)   __attribute__ ((naked, weak, alias("Default_Handler")));

void DMA_Handler (void)         __attribute__ ((naked, weak, alias("Default_Handler")));
void UART1_Handler (void)      __attribute__ ((naked, weak, alias("Default_Handler")));
void UART2_Handler (void)      __attribute__ ((naked, weak, alias("Default_Handler")));
void SSP1_Handler (void)      __attribute__ ((naked, weak, alias("Default_Handler")));
void PWR_Handler (void)         __attribute__ ((naked, weak, alias("Default_Handler")));
void WWDG_Handler (void)      __attribute__ ((naked, weak, alias("Default_Handler")));
void Timer0_Handler (void)      __attribute__ ((naked, weak, alias("Default_Handler")));
void Timer1_Handler (void)      __attribute__ ((naked, weak, alias("Default_Handler")));
void ADC_Handler (void)         __attribute__ ((naked, weak, alias("Default_Handler")));
void CMP_Handler (void)         __attribute__ ((naked, weak, alias("Default_Handler")));
void BKP_Handler (void)         __attribute__ ((naked, weak, alias("Default_Handler")));
void EXT_INT1_Handler (void)   __attribute__ ((naked, weak, alias("Default_Handler")));
void EXT_INT2_Handler (void)   __attribute__ ((naked, weak, alias("Default_Handler")));
void EXT_INT3_Handler (void)   __attribute__ ((naked, weak, alias("Default_Handler")));
void ADCIU_CH1_Handler (void)   __attribute__ ((naked, weak, alias("Default_Handler")));
void ADCIU_CH2_Handler (void)   __attribute__ ((naked, weak, alias("Default_Handler")));
void ADCIU_CH3_Handler (void)   __attribute__ ((naked, weak, alias("Default_Handler")));
void ADCIU_CH4_Handler (void)   __attribute__ ((naked, weak, alias("Default_Handler")));
void ADCIU_CH5_Handler (void)   __attribute__ ((naked, weak, alias("Default_Handler")));
void ADCIU_CH6_Handler (void)   __attribute__ ((naked, weak, alias("Default_Handler")));
void ADCIU_CH7_Handler (void)   __attribute__ ((naked, weak, alias("Default_Handler")));
void ADCIU_CH8_Handler (void)   __attribute__ ((naked, weak, alias("Default_Handler")));
void ADCIU_Handler (void)      __attribute__ ((naked, weak, alias("Default_Handler")));

//------------------------------------------------------------------------------
// Global Const
//------------------------------------------------------------------------------

static void (* vTable[]) (void) __attribute__ ((used, section(".vectors"))) = {
   (void (*)(void)) &_sstack,   /* Top of Stack */
   LowLevelInit,         /* LowLevelInit */
   NMI_Handler,         /* NMI Handler */
   Fault_Handler,         /* Hard Fault Handler */
   0, 0, 0, 0, 0, 0, 0,   /* Reserved */
   SVC_Handler,         /* SVCall Handler */
   0, 0,               /* Reserved */
   PSV_Handler,         /* PendSV Handler */
   SYS_Handler,         /* SysTick Handler */

   DMA_Handler,         /* IRQ0 DMA */
   UART1_Handler,         /* IRQ1 UART1 */
   UART2_Handler,         /* IRQ2 UART2 */
   SSP1_Handler,         /* IRQ3 SSP1 */
   PWR_Handler,         /* IRQ4 PWR */
   WWDG_Handler,         /* IRQ5 WWDG */
   Timer0_Handler,         /* IRQ6 Timer0 */
   Timer1_Handler,         /* IRQ7 Timer1 */
   ADC_Handler,         /* IRQ8 ADC */
   CMP_Handler,         /* IRQ9 CMP */
   BKP_Handler,         /* IRQ10 BKP */
   EXT_INT1_Handler,      /* IRQ11 EXT_INT1 */
   EXT_INT2_Handler,      /* IRQ12 EXT_INT2 */
   EXT_INT3_Handler,      /* IRQ13 EXT_INT3 */
   ADCIU_CH1_Handler,      /* IRQ14 ADCIU_CH1 */
   ADCIU_CH2_Handler,      /* IRQ15 ADCIU_CH2 */
   ADCIU_CH3_Handler,      /* IRQ16 ADCIU_CH3 */
   ADCIU_CH4_Handler,      /* IRQ17 ADCIU_CH4 */
   ADCIU_CH5_Handler,      /* IRQ18 ADCIU_CH5 */
   ADCIU_CH6_Handler,      /* IRQ19 ADCIU_CH6 */
   ADCIU_CH7_Handler,      /* IRQ20 ADCIU_CH7 */
   ADCIU_CH8_Handler,      /* IRQ21 ADCIU_CH8 */
   ADCIU_Handler,         /* IRQ22 ADCIU */
   };

#endif


И в каком либо месте кода обработчики прерываний к примеру:
Код:
//------------------------------------------------------------------------------
// IRQ functions
//------------------------------------------------------------------------------
__attribute__ ((section(".ramfunc"), aligned(8))) void Timer0_Handler (void) {
   bitCount = 847; pxFM -> N++; TIMER0_BASE -> STATUS &= ~TIMER_STATUS_ETR_RE_EVENT; printf ("\r\nSerial num %u", pxFM -> N);
}

__attribute__ ((section(".ramfunc"), aligned(8))) void Timer1_Handler (void) {
   if (TIMER1_BASE -> STATUS & TIMER_STATUS_ETR_RE_EVENT) {PORTB_BASE -> RXTX |= PORT_PB12 & bitOut; bitOut = 0; TIMER1_BASE -> STATUS &= ~TIMER_STATUS_ETR_RE_EVENT;}
   else {
      PORTB_BASE -> RXTX &= ~PORT_PB12; TIMER1_BASE -> STATUS &= ~TIMER_STATUS_ETR_FE_EVENT;
      if (bitCount >= 0) {if (bitCount < 832) {if (pxFM -> byte[bitCount >> 3] & (1 << (bitCount & 0x7))) bitOut = PORT_PB12;} bitCount--;}
      }
}

__attribute__ ((section(".ramfunc"), aligned(8))) void DMA_Handler (void) {
   unsigned int temp, max, min;
   printf ("\r\nDMA_ADCIU:", NULL);
   if (DMAPriCtrlBlock[DMA_ID_ADCIU0].cycle_ctrl == DMA_Mode_Stop) {DMAPriCtrlBlock[DMA_ID_ADCIU0].Cfg = ADCUI0_DMA_Cfg; DMA_ChCfg (DMA_ID_ADCIU0, DMA_CHNL_EN); temp = 17; while (temp--) ADCUI0_DATA[temp] ^= 1 << 23; temp = 16; min = max = ADCUI0_DATA[temp]; while (temp--) {if (min > ADCUI0_DATA[temp]) min = ADCUI0_DATA[temp]; if (max < ADCUI0_DATA[temp]) max = ADCUI0_DATA[temp];} printf ("\t%u", max - min);}
   if (DMAPriCtrlBlock[DMA_ID_ADCIU1].cycle_ctrl == DMA_Mode_Stop) {DMAPriCtrlBlock[DMA_ID_ADCIU1].Cfg = ADCUI0_DMA_Cfg; DMA_ChCfg (DMA_ID_ADCIU1, DMA_CHNL_EN); temp = 17; while (temp--) ADCUI1_DATA[temp] ^= 1 << 23; temp = 16; min = max = ADCUI1_DATA[temp]; while (temp--) {if (min > ADCUI1_DATA[temp]) min = ADCUI1_DATA[temp]; if (max < ADCUI1_DATA[temp]) max = ADCUI1_DATA[temp];} printf ("\t%u", max - min);}
   if (DMAPriCtrlBlock[DMA_ID_ADCIU3].cycle_ctrl == DMA_Mode_Stop) {DMAPriCtrlBlock[DMA_ID_ADCIU3].Cfg = ADCUI0_DMA_Cfg; DMA_ChCfg (DMA_ID_ADCIU3, DMA_CHNL_EN); temp = 17; while (temp--) ADCUI3_DATA[temp] ^= 1 << 23; temp = 16; min = max = ADCUI3_DATA[temp]; while (temp--) {if (min > ADCUI3_DATA[temp]) min = ADCUI3_DATA[temp]; if (max < ADCUI3_DATA[temp]) max = ADCUI3_DATA[temp];} printf ("\t%u", max - min);}
   if (DMAPriCtrlBlock[DMA_ID_ADCIU4].cycle_ctrl == DMA_Mode_Stop) {DMAPriCtrlBlock[DMA_ID_ADCIU4].Cfg = ADCUI0_DMA_Cfg; DMA_ChCfg (DMA_ID_ADCIU4, DMA_CHNL_EN); temp = 17; while (temp--) ADCUI4_DATA[temp] ^= 1 << 23; temp = 16; min = max = ADCUI4_DATA[temp]; while (temp--) {if (min > ADCUI4_DATA[temp]) min = ADCUI4_DATA[temp]; if (max < ADCUI4_DATA[temp]) max = ADCUI4_DATA[temp];} printf ("\t%u", max - min);}
   if (DMAPriCtrlBlock[DMA_ID_ADCIU6].cycle_ctrl == DMA_Mode_Stop) {DMAPriCtrlBlock[DMA_ID_ADCIU6].Cfg = ADCUI0_DMA_Cfg; DMA_ChCfg (DMA_ID_ADCIU6, DMA_CHNL_EN); temp = 17; while (temp--) ADCUI6_DATA[temp] ^= 1 << 23; temp = 16; min = max = ADCUI6_DATA[temp]; while (temp--) {if (min > ADCUI6_DATA[temp]) min = ADCUI6_DATA[temp]; if (max < ADCUI6_DATA[temp]) max = ADCUI6_DATA[temp];} printf ("\t%u", max - min);}
   if (DMAPriCtrlBlock[DMA_ID_ADCIU7].cycle_ctrl == DMA_Mode_Stop) {DMAPriCtrlBlock[DMA_ID_ADCIU7].Cfg = ADCUI0_DMA_Cfg; DMA_ChCfg (DMA_ID_ADCIU7, DMA_CHNL_EN); temp = 17; while (temp--) ADCUI7_DATA[temp] ^= 1 << 23; temp = 16; min = max = ADCUI7_DATA[temp]; while (temp--) {if (min > ADCUI7_DATA[temp]) min = ADCUI7_DATA[temp]; if (max < ADCUI7_DATA[temp]) max = ADCUI7_DATA[temp];} printf ("\t%u", max - min);}
   }


ld файл:
Код:
ENTRY(LowLevelInit)

STACK_SIZE = 0x200;

MEMORY
{
   FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x20000
   RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x4000
}

SECTIONS
{
   .vectors ORIGIN(FLASH) : {
      KEEP(*(.vectors));
   } > FLASH
   
   .text : {
      . = ALIGN(4); PROVIDE(_text = .);
      *(.text*);
      *(.rodata*);
   } > FLASH
   
   . = ALIGN(4); PROVIDE(_etext = .);
   
   .dma ORIGIN(RAM) : {
      *(.dma*);
    } > RAM
   
   .data : AT (_etext) {
      . = ALIGN(4); PROVIDE(_data = .);
      *(.ramfunc*);
        *(.data*);
    } > RAM
   
   DATA_SIZE = SIZEOF(.data);
   
   .rtt : {
      . = ALIGN(4); PROVIDE(_rtt = .);
      *(.rtt*);
   } > RAM
   
   .bss (NOLOAD) : {
      . = ALIGN(4); PROVIDE(_bss = .);
      *(.bss);
      *(.bss*);
      *(COMMON);
   } > RAM
   
   .heap (NOLOAD): {
        . = ALIGN(4); PROVIDE(_heap = .);
        . = (ORIGIN(RAM) + LENGTH(RAM) - STACK_SIZE);
    } > RAM
   
    HEAP_SIZE = SIZEOF(.heap);
   
   .stack (NOLOAD) : {
      . = (ORIGIN(RAM) + LENGTH(RAM) - STACK_SIZE); . = ALIGN(4); PROVIDE(_estack = .);
      . = (ORIGIN(RAM) + LENGTH(RAM)); PROVIDE(_sstack = .);
   } > RAM
}


Загрузка всех рамфункций из флэш в рам:
Код:
   unsigned int temp = (unsigned int) &DATA_SIZE;
   unsigned int *dst = &_data; unsigned int *src = &_etext;
   temp >>= 2;   while (temp--) *dst++ = *src++;

Автор:  andelie [ 2019-май-14 18:34 ]
Заголовок сообщения:  Re: Работа с DAC при выполнении кода из внешнего ПЗУ

Похоже, мы немного о разных вещах говорим. Я имею в виду, что в камень заливается два или более проекта, в каждом из которых нужно работать с одними и теми же прерываниями, но обработчики у них будут в каждом из проектов разными, в том числе, с кодом разного размера. Как же линковщик, которому было указание поместить все функции-обработчики прерываний в один RAM-модуль, сообразит, что каждая из этих функций должна будет размещена по одинаковому адресу в каждом из нескольких проектов?

Страница 3 из 3 Часовой пояс: UTC + 3 часа
Powered by phpBB® Forum Software © phpBB Group
http://www.phpbb.com/