在 IAR 中将电机库函数放入 RAM 运行

关键字 :NXPMCUKV30

1.概述

2.将中断向量表放入 RAM 运行

3.修改 .icf 链接文件

4.查看 MAP 文件




  1. 概述

          电机电流环 FOC 控制环路需要在每个 PWM 半周期时间内运行完毕(或每个 PWM 周期运行两次),在电机转速很高,即其相电流频率很高时,需要将控制频率(FOC 控制频率)提高至电流频率二十倍以上,才能保证比较好的电流正弦度和稳定性要求,但 MCU 算力有限,代码在 Flash 中运行比较慢(NXP KV30 Flash 运行频率 24MHZ,FOC 时间:45us),如果将 FOC 代码放入 RAM (100MHZ)中运行,则 FOC 运行时间缩短很多(FOC 时间:23us),此时可以提高 PWM 的频率。


  1. 将中断向量表放入 RAM 中运行

       

           FOC 运行代码一般都是在 PWM 或 ADC 中断中运行,中断函数如果是在 Flash 中,而 FOC 代码指定在 RAM 中时,IAR 在链接时并没有把 FOC 代码链接到 RAM 中,此为 IAR 的链接保护机制规定的。

 1)将默认的 .s 启动文件修改为:

       其中的中断向量表将被后面新建的替代。

MODULE ?cstartup

;; Forward declaration of sections.
SECTION CSTACK:DATA:NOROOT(3)

SECTION .intvec:CODE:NOROOT(2)

EXTERN __iar_program_start
EXTERN SystemInit
EXTERN Empty_Handler
PUBLIC __vector_table
PUBLIC __vector_table_0x1c
PUBLIC __Vectors
PUBLIC __Vectors_End
PUBLIC __Vectors_Size
PUBLIC Reset_Handler

DATA

__vector_table
DCD sfe(CSTACK)
DCD Reset_Handler

DCD Empty_Handler ;NMI Handler
DCD Empty_Handler ;Hard Fault Handler
DCD Empty_Handler ;MPU Fault Handler
DCD Empty_Handler ;Bus Fault Handler
DCD Empty_Handler ;Usage Fault Handler
__vector_table_0x1c
DCD Empty_Handler ;Reserved
DCD Empty_Handler ;Reserved
DCD Empty_Handler ;Reserved
DCD Empty_Handler ;Reserved
DCD Empty_Handler ;SVCall Handler
DCD Empty_Handler ;Debug Monitor Handler
DCD Empty_Handler ;Reserved
DCD Empty_Handler ;PendSV Handler
DCD Empty_Handler ;SysTick Handler
__Vectors_End


SECTION intvec_2:CODE:NOROOT(2)
DCD Empty_Handler




SECTION FlashConfig:CODE
__FlashConfig
DCD 0xFFFFFFFF
DCD 0xFFFFFFFF
DCD 0xFFFFFFFF
DCD 0xFFFFFFFE
__FlashConfig_End

__Vectors EQU __vector_table
__Vectors_Size EQU __Vectors_End - __Vectors


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Default interrupt handlers.
;;
THUMB

PUBWEAK Reset_Handler
SECTION .text:CODE:REORDER:NOROOT(2)
Reset_Handler
CPSID I ; Mask interrupts
LDR R0, =0xE000ED08
LDR R1, =__vector_table
STR R1, [R0]
LDR R2, [R1]
MSR MSP, R2
LDR R0, =SystemInit
BLX R0
CPSIE I ; Unmask interrupts
LDR R0, =__iar_program_start
BX R0

DefaultISR
B DefaultISR

END




2)新建一个中断向量表并指定放入 RAM 地址中:

__ramfunc
void NMI_Handler(void)
{
while(1);
}
__ramfunc
void HardFault_Handler(void)
{
while(1);
}
__ramfunc
void MemManage_Handler(void)
{
while(1);
}
__ramfunc
void BusFault_Handler(void)
{
while(1);
}
__ramfunc
void UsageFault_Handler(void)
{
while(1);
}
__ramfunc
void Reserved_Handler(void)
{
while(1);
}
__ramfunc
void SVC_Handler(void)
{
while(1);
}
__ramfunc
void DebugMon_Handler(void)
{
while(1);
}
__ramfunc
void PendSV_Handler(void)
{
while(1);
}
__ramfunc
void SysTick_Handler(void)
{
while(1);
}


typedef void( *intfunc )( void );
typedef union { intfunc __fun; void * __ptr; } intvec_elem;


#pragma segment="CSTACK"
extern void Reset_Handler();
extern void FTM0_IRQHandler(void);
extern void FTM1_IRQHandler(void);
extern void PDB0_IRQHandler(void);

intvec_elem __vector_table_ram[69] @0x1FFFE000 =
{
{.__ptr = __sfe("CSTACK")},//0
Reset_Handler,
NMI_Handler,
HardFault_Handler,
MemManage_Handler,
BusFault_Handler,
UsageFault_Handler,
Reserved_Handler,
Reserved_Handler,
Reserved_Handler,
Reserved_Handler,
SVC_Handler,
DebugMon_Handler,
Reserved_Handler,
PendSV_Handler,
SysTick_Handler,//15

Reserved_Handler,//DMA0_IRQHandler,
Reserved_Handler,//DMA1_IRQHandler,
Reserved_Handler,//DMA2_IRQHandler,
Reserved_Handler,//DMA3_IRQHandler,
Reserved_Handler,
Reserved_Handler,
Reserved_Handler,
Reserved_Handler,
Reserved_Handler,
Reserved_Handler,//25

Reserved_Handler,
Reserved_Handler,
Reserved_Handler,
Reserved_Handler,
Reserved_Handler,
Reserved_Handler,
Reserved_Handler,//DMA_Error_IRQHandler,//32
Reserved_Handler,//MCM_IRQHandler,
Reserved_Handler,//FTF_IRQHandler,
Reserved_Handler,//Read_Collision_IRQHandler, //35

Reserved_Handler,//LVD_LVW_IRQHandler,
Reserved_Handler,//LLWU_IRQHandler ,
Reserved_Handler,//WDOG_EWM_IRQHandler,
Reserved_Handler,
Reserved_Handler,//I2C0_IRQHandler, //40
Reserved_Handler,
Reserved_Handler,//SPI0_IRQHandler ,//42
Reserved_Handler,
Reserved_Handler,
Reserved_Handler, //45

Reserved_Handler,
Reserved_Handler,//UART0_RX_TX_IRQHandler,//47
Reserved_Handler,//UART0_ERR_IRQHandler,
Reserved_Handler,//UART1_RX_TX_IRQHandler,
Reserved_Handler,//UART1_ERR_IRQHandler,//50
Reserved_Handler,
Reserved_Handler,
Reserved_Handler,
Reserved_Handler,
Reserved_Handler,//ADC0_IRQHandler, //55

Reserved_Handler,//CMP0_IRQHandler,

Reserved_Handler,//CMP1_IRQHandler,
FTM0_IRQHandler,
FTM1_IRQHandler,
Reserved_Handler,//FTM2_IRQHandler,
Reserved_Handler,
Reserved_Handler,
Reserved_Handler,
Reserved_Handler,//PIT0_IRQHandler,
Reserved_Handler,//PIT1_IRQHandler, //65

Reserved_Handler,//PIT2_IRQHandler,
Reserved_Handler,//PIT3_IRQHandler,
PDB0_IRQHandler,//68
};



3)在 MAIN 函数中更新 VTOR 的值:

       int main(void)

       {

            SCB->VTOR = ((uint32_t)__vector_table_ram);

            ……





  1. 修改 .icf 链接文件

          将电机库链接至 RAM 中,并让 IAR 的启动拷贝函数在 MCU 启动时自动将用到的电机库函数拷贝到 RAM 中。

 1) 新建两个 region ,一个在 Flash 地址中(电机库函数的存储地址),一个在 RAM 地址中(电机库函数的运行地址)

define region region_for_lib_RAM = mem:[from region_for_lib_RAM_start to region_for_lib_RAM_end];

define region region_for_lib_ROM = mem:[from region_for_lib_ROM_start to region_for_lib_ROM_end];

2)定义两个 BLOCK,用于指定哪些静态电机库链接到 RAM 中

define block LIB       { readwrite code object GMCLIB.a,readwrite code object AMCLIB.a,readwrite code object GFLIB.a,readwrite code object m7M_tls.a };

define block LIB_INIT  { readonly code section *_init object GMCLIB.a,readonly  code section *_init object AMCLIB.a,readonly code section *_init object GFLIB.a,readonly code section *_init object m7M_tls.a};

3) 启动时自动将 Flash 中的电机库函数拷贝到 RAM 中

initialize by copy { readonly  object GMCLIB.a  };

initialize by copy { readonly  object AMCLIB.a  };

initialize by copy { readonly  object GFLIB.a   };



完整文件如下:

define symbol m_interrupts_start = 0x00000000;
define symbol m_interrupts_end = 0x000003FF;

define symbol m_flash_config_start = 0x00000400;
define symbol m_flash_config_end = 0x0000040F;

define symbol region_for_lib_ROM_start = 0x00000410;
define symbol region_for_lib_ROM_end = 0x000017AB;

define symbol m_text_start = 0x000017AC;
define symbol m_text_end = 0x0000FFFF;

define symbol m_data_start = 0x1FFFE000;
define symbol m_data_end = 0x1FFFFFFF;

define symbol region_for_lib_RAM_start = 0x20000000;
define symbol region_for_lib_RAM_end = 0x2000139B;

define symbol m_data_2_start = 0x2000139C;
define symbol m_data_2_end = 0x20001FFF;

/* Sizes */
if (isdefinedsymbol(__stack_size__)) {
define symbol __size_cstack__ = __stack_size__;
} else {
define symbol __size_cstack__ = 0x0200;
}

if (isdefinedsymbol(__heap_size__)) {
define symbol __size_heap__ = __heap_size__;
} else {
define symbol __size_heap__ = 0x0200;
}


define memory mem with size = 4G;
define region m_flash_config_region = mem:[from m_flash_config_start to m_flash_config_end];
define region TEXT_region = mem:[from m_interrupts_start to m_interrupts_end]
| mem:[from m_text_start to m_text_end];

define region DATA_region = mem:[from m_data_start to m_data_end]
| mem:[from m_data_2_start to m_data_2_end-__size_cstack__];
define region CSTACK_region = mem:[from m_data_2_end-__size_cstack__+1 to m_data_2_end];
define region region_for_lib_RAM = mem:[from region_for_lib_RAM_start to region_for_lib_RAM_end];
define region region_for_lib_ROM = mem:[from region_for_lib_ROM_start to region_for_lib_ROM_end];

define block CSTACK with alignment = 8, size = __size_cstack__ { };
define block HEAP with alignment = 8, size = __size_heap__ { };
define block RW { readwrite };
define block ZI { zi };
define block LIB { readwrite code object GMCLIB.a,readwrite code object AMCLIB.a,readwrite code object GFLIB.a,readwrite code object m7M_tls.a };
define block LIB_INIT { readonly code section *_init object GMCLIB.a,readonly code section *_init object AMCLIB.a,readonly code section *_init object GFLIB.a,readonly code section *_init object m7M_tls.a};


initialize by copy { readwrite, section .textrw };
initialize by copy { readonly object GMCLIB.a };
initialize by copy { readonly object AMCLIB.a };
initialize by copy { readonly object GFLIB.a };
initialize by copy { readonly object m7M_tls.a };

do not initialize { section .noinit };

place at address mem: m_interrupts_start { readonly section .intvec };
place in m_flash_config_region { section FlashConfig };
place in region_for_lib_RAM { block LIB };
place in region_for_lib_ROM { block LIB_INIT };

place in TEXT_region { readonly };
place in DATA_region { block RW };
place in DATA_region { block ZI };
place in DATA_region { last block HEAP };
place in CSTACK_region { block CSTACK };




  1. 4. 查看 MAP 文件

        通过查看 IAR 编译链接后的 MAP 文件确认电机库函数放到了 RAM 地址中,如下图所示:

★博文内容均由个人提供,与平台无关,如有违法或侵权,请与网站管理员联系。

★文明上网,请理性发言。内容一周内被举报5次,发文人进小黑屋喔~

评论