This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] MSP430FR2033:定制引导加载程序

Guru**** 2568435 points
Other Parts Discussed in Thread: MSP430F5529, MSP430FR2033

请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/606247/msp430fr2033-custom-bootloader

器件型号:MSP430FR2033
主题中讨论的其他器件:MSP430F5529

我正在尝试创建自定义引导加载程序(不使用 BSL 或 MSPFRBOOT) 、以便能够在接收数据时更新主应用程序。 启动和复位时 、处理器 应进入引导加载程序、以检查是否需要任何更新。

当    MSP430FR2033 处于引导加载程序应用中时、更新将通过 I2C 从 MSP430F5529 (主器件)发送到 MSP430FR2033 (从器件)。 引导加载程序未使用 BSL、它是主存储器中自己的应用程序。

  1. 我已经阅读过、 由于 MSP430FR2033使用 FRAM、并且没有最小擦除大小(被视为 RAM)、因此它不需要代理矢量表、但在 MSP430FRBOOT 代码示例中、它们确实有代理矢量表。 如果链接器包含硬件中断的相同地址、为什么不需要代理矢量表? 每个应用程序是否在引导时重新配置 int00中断中的硬件矢量表? 或者我是否需要 代理矢量表?
  2. 我们的设计是让硬件复位矢量始终跳转到引导加载程序的引导中断。 因此、引导加载程序可以检查主应用程序是否需要在启动时更新、如果没有更新、则跳转到主应用程序。 我们通过在 main 的 int00例程中使用一个跳转指令来跳转到 main。 我们 通过执行欠压复位从主应用程序跳转到引导加载程序。 欠压复位可以正常工作、但似乎没有跳转到引导加载程序 、我们不确定原因。
  3. 我们应该为每个应用使用哪些闪存选项? 目前、我们使用完全擦除和编程在引导加载程序中进行闪存。 然后、我们通过在主应用程序上执行差分下载来刷写应用程序。 执行此操作时、我们立即失去调试控制、因为复位矢量进入引导加载程序。 这是将这两个应用程序闪存到同一处理器的正确方法吗?

这是引导加载程序链接器:

内存
{
SFR :origin = 0x0000、length = 0x0010
外设_8位 :origin = 0x0010,length = 0x00F0
外设_16BIT :origin = 0x0100,length = 0x0100
RESET_Vector:origin = 0x1900,length = 0x0100
RAM :origin = 0x2000、length = 0x0800
FRAM:origin = 0xF400,length = 0x0B80
JTAGSIGNATURE :origin = 0xFF80、length = 0x0004、fill = 0xFFFF
BSLSIGNATURE :origin = 0xFF84、length = 0x0004、fill = 0xFFFF
INT00 :origin = 0xFF88、length = 0x0002
INT01 :origin = 0xFF8A,length = 0x0002
INT02 :origin = 0xFF8C,length = 0x0002
INT03 :origin = 0xFF8E、length = 0x0002
INT04 :origin = 0xFF90,length = 0x0002
INT05 :origin = 0xFF92,length = 0x0002
INT06 :origin = 0xFF94,length = 0x0002
INT07 :origin = 0xFF96、length = 0x0002
INT08 :origin = 0xFF98,length = 0x0002
INT09 :origin = 0xFF9A,length = 0x0002
INT10. :origin = 0xFF9C,length = 0x0002
INT11. :origin = 0xFF9E、length = 0x0002
INT12. :origin = 0xFFA0、length = 0x0002
INT13. :origin = 0xFFA2、length = 0x0002
INT14 :origin = 0xFFA4、length = 0x0002
INT15. :origin = 0xFFA6、length = 0x0002
内部16. :origin = 0xFFFA8、length = 0x0002
INT17. :origin = 0xFFAA、length = 0x0002
INT18 :origin = 0xFFAC,length = 0x0002
INT19. :origin = 0xFFAE、length = 0x0002
INT20. :origin = 0xFFB0,length = 0x0002
INT21. :origin = 0xFFB2、length = 0x0002
INT22. :origin = 0xFFB4,length = 0x0002
INT23 :origin = 0xFFB6、length = 0x0002
INT24 :origin = 0xFFB8、length = 0x0002
INT25. :origin = 0xFFBA,length = 0x0002
INT26. :origin = 0xFFBC,length = 0x0002
INT27. :origin = 0xFFBE,length = 0x0002
INT28 :origin = 0xFFC0、length = 0x0002
INT29 :origin = 0xFFC2,length = 0x0002
INT30 :origin = 0xFFC4,length = 0x0002
INT31 :origin = 0xFFC6、length = 0x0002
Int32. :origin = 0xFFC8,length = 0x0002
INT33 :origin = 0xFFCA,length = 0x0002
INT34 :origin = 0xFFCC,length = 0x0002
INT35. :origin = 0xFFCE,length = 0x0002
INT36 :origin = 0xFFD0、length = 0x0002
INT37 :origin = 0xFFD2,length = 0x0002
INT38 :origin = 0xFFD4、length = 0x0002
INT39. :origin = 0xFFD6、length = 0x0002
INT40. :origin = 0xFFD8、length = 0x0002
INT41 :origin = 0xFFDA,length = 0x0002
INT42. :origin = 0xFFDC,length = 0x0002
INT43 :origin = 0xFFDE,length = 0x0002
INT44 :origin = 0xFFE0、length = 0x0002
INT45. :origin = 0xFFE2,length = 0x0002
INT46 :origin = 0xFFE4,length = 0x0002
INT47. :origin = 0xFFE6,length = 0x0002
INT48 :origin = 0xFFE8、length = 0x0002
INT49 :origin = 0xFFEA,length = 0x0002
INT50 :origin = 0xFFEC,length = 0x0002
INT51. :origin = 0xFFEE,length = 0x0002
INT52. :origin = 0xFFF0,length = 0x0002
INT53 :origin = 0xFFF2,length = 0x0002
INT54. :origin = 0xFFF4,length = 0x0002
INT55 :origin = 0xFFF6、length = 0x0002
INT56 :origin = 0xFFF8,length = 0x0002
INT57. :origin = 0xFFFA,length = 0x0002
INT58 :origin = 0xFFFC,length = 0x0002
复位 :origin = 0xFFFE,length = 0x0002
}/*********

/*
指定段分配到内存中 */
********* /

SECTIONS
{
组(all_FRAM)
{
组(READ_WRITE_MEMORY)
{
.TI.persistent:{} 对于#pragma PERSISTENT */
}

组(只读_存储器)
{
.cinit :{} /*初始化表 *
.pinit :{} /* C++构造函数表 *
二进制文件 :{} /*引导时初始化表*/
init_array :{} /* C++构造函数表 *
.mspabi.exidx:{} /* C++构造函数表 *
.mspabi.extab:{} /* C++构造函数表 *
.const :{} /*常量数据 */
}

GROUP (可执行文件存储器)
{
.text :{} /*代码 */

}
}> FRAM

#ifdef __TI_Compiler_version__
#if __TI_Compiler_version__>=15009000
#ifndef __large_data_model__
.TI.ramfunc:{} load=FRAM、run=RAM、table (BINIT)
其他
.TI.ramfunc:{} load=FRAM | FRAM2、run=RAM、table (BINIT)
endif
#endif #endif #endif


.jtagsignature:{}> JTAGSIGNATURE/* JTAG Signature *
bslsignature:{}> BSLSIGNATURE /* BSL Signature *

.bss :{}> RAM /*全局和静态变量 *
.data :{}> RAM /*全局和静态变量 *
.TI.noinit:{}>RAM /*用于#pragma noinit *
.cio :{}> RAM /* C I/O 缓冲器 *
sysmem :{}> RAM /*动态内存分配区域*/
堆栈 :{}> RAM (高) /*软件系统堆栈 *
.text:_c_int00_noargs_noexit:{}> reset_vector

/* MSP430中断矢量 *
int00 :{} > INT00
.int01 :{} > INT01
.int02 :{} > INT02
.int03 :{} > INT03
.int04 :{} > INT04
.int05 :{} > INT05
.int06 :{} > INT06
.int07 :{} > INT07
.int08 :{} > INT08
.int09 :{} > INT09
INT10 :{} > INT10
INT11 :{} > INT11
INT12. :{} > INT12
INT13. :{} > INT13
INT14 :{} > INT14
.int15. :{} > INT15
.int16. :{} > Int16
.int17. :{} > INT17
.int18. :{} > INT18
.int19. :{} > INT19
.int20. :{} > INT20
.int21. :{} > INT21
.int22. :{} > INT22
.int23. :{} > INT23
.int24. :{} > INT24
.int25. :{} > INT25
.int26. :{} > INT26
.int27. :{} > INT27
.int28 :{} > INT28
.int29 :{} > INT29
.int30 :{} > INT30
.int31. :{} > INT31
.int32. :{} > Int32
.int33. :{} > INT33
.int34. :{} > INT34
.int35. :{} > INT35
.int36. :{} > INT36
.int37. :{} > INT37
.int38. :{} > INT38
.int39. :{} > INT39
int40. :{} > INT40
.int41. :{} > INT41
.int42. :{} > INT42
.int43. :{} > INT43
.int44. :{} > INT44
.int45. :{} > INT45
端口2 :{*(.int46)}> INT46 type = VECT_init
端口1 :{*(.int47 )}> INT47类型= VECT_INIT
ADC :{*(.int48 )}>INT48 type = VECT_init
USCI_B0 :{*(.int49)}> INT49类型= VECT_INIT
USCI_A0 :{*(.int50)}> INT50类型= VECT_INIT
WDT :{*(.int51 )}> INT51 type = VECT_init
RTC :{*(.int52)}> INT52 type = VECT_init
Timer1_A1:{*(.int53)}> INT53 type = VECT_init
Timer1_A0:{*(.int54)}> INT54 type = VECT_init
TIMER0_A1:{*(.int55 )}> INT55 TYPE = VECT_INIT
TIMER0_A0:{*(.int56 )}> INT56 TYPE = VECT_INIT
联合国管理信息系统 :{*(.int57 )}>INT57 type = VECT_init
SYSNMI :{*(.int58 )}> INT58 TYPE = VECT_INIT
复位 :{} >复位/* MSP430复位矢量 */
} 

这是主应用程序链接器:

内存
{
SFR :origin = 0x0000、length = 0x0010
外设_8位 :origin = 0x0010,length = 0x00F0
外设_16BIT :origin = 0x0100,length = 0x0100
RAM :origin = 0x2000、length = 0x0800
INFOA :origin = 0x1800,length = 0x0100
FRAM :origin = 0xC480,length = 0x2F7F
FRAM_JUTO_INstruction:origin = 0xC400,length = 0x0008
FRAM_BOOT_ISR :origin = 0xC408,length = 0x0078
JTAGSIGNATURE :origin = 0xFF80、length = 0x0004、fill = 0xFFFF
BSLSIGNATURE :origin = 0xFF84、length = 0x0004、fill = 0xFFFF
INT00 :origin = 0xFF88、length = 0x0002
INT01 :origin = 0xFF8A,length = 0x0002
INT02 :origin = 0xFF8C,length = 0x0002
INT03 :origin = 0xFF8E、length = 0x0002
INT04 :origin = 0xFF90,length = 0x0002
INT05 :origin = 0xFF92,length = 0x0002
INT06 :origin = 0xFF94,length = 0x0002
INT07 :origin = 0xFF96、length = 0x0002
INT08 :origin = 0xFF98,length = 0x0002
INT09 :origin = 0xFF9A,length = 0x0002
INT10. :origin = 0xFF9C,length = 0x0002
INT11. :origin = 0xFF9E、length = 0x0002
INT12. :origin = 0xFFA0、length = 0x0002
INT13. :origin = 0xFFA2、length = 0x0002
INT14 :origin = 0xFFA4、length = 0x0002
INT15. :origin = 0xFFA6、length = 0x0002
内部16. :origin = 0xFFFA8、length = 0x0002
INT17. :origin = 0xFFAA、length = 0x0002
INT18 :origin = 0xFFAC,length = 0x0002
INT19. :origin = 0xFFAE、length = 0x0002
INT20. :origin = 0xFFB0,length = 0x0002
INT21. :origin = 0xFFB2、length = 0x0002
INT22. :origin = 0xFFB4,length = 0x0002
INT23 :origin = 0xFFB6、length = 0x0002
INT24 :origin = 0xFFB8、length = 0x0002
INT25. :origin = 0xFFBA,length = 0x0002
INT26. :origin = 0xFFBC,length = 0x0002
INT27. :origin = 0xFFBE,length = 0x0002
INT28 :origin = 0xFFC0、length = 0x0002
INT29 :origin = 0xFFC2,length = 0x0002
INT30 :origin = 0xFFC4,length = 0x0002
INT31 :origin = 0xFFC6、length = 0x0002
Int32. :origin = 0xFFC8,length = 0x0002
INT33 :origin = 0xFFCA,length = 0x0002
INT34 :origin = 0xFFCC,length = 0x0002
INT35. :origin = 0xFFCE,length = 0x0002
INT36 :origin = 0xFFD0、length = 0x0002
INT37 :origin = 0xFFD2,length = 0x0002
INT38 :origin = 0xFFD4、length = 0x0002
INT39. :origin = 0xFFD6、length = 0x0002
INT40. :origin = 0xFFD8、length = 0x0002
INT41 :origin = 0xFFDA,length = 0x0002
INT42. :origin = 0xFFDC,length = 0x0002
INT43 :origin = 0xFFDE,length = 0x0002
INT44 :origin = 0xFFE0、length = 0x0002
INT45. :origin = 0xFFE2,length = 0x0002
INT46 :origin = 0xFFE4,length = 0x0002
INT47. :origin = 0xFFE6,length = 0x0002
INT48 :origin = 0xFFE8、length = 0x0002
INT49 :origin = 0xFFEA,length = 0x0002
INT50 :origin = 0xFFEC,length = 0x0002
INT51. :origin = 0xFFEE,length = 0x0002
INT52. :origin = 0xFFF0,length = 0x0002
INT53 :origin = 0xFFF2,length = 0x0002
INT54. :origin = 0xFFF4,length = 0x0002
INT55 :origin = 0xFFF6、length = 0x0002
INT56 :origin = 0xFFF8,length = 0x0002
INT57. :origin = 0xFFFA,length = 0x0002
INT58 :origin = 0xFFFC,length = 0x0002
复位 :origin = 0xFFFE,length = 0x0002
}/*********

/*
指定段分配到内存中 */
********* /

SECTIONS
{
组(all_FRAM)
{
组(READ_WRITE_MEMORY)
{
.TI.persistent:{} 对于#pragma PERSISTENT */
}

组(只读_存储器)
{
.cinit :{} /*初始化表 *
.pinit :{} /* C++构造函数表 *
init_array :{} /* C++构造函数表 *
.mspabi.exidx:{} /* C++构造函数表 *
.mspabi.extab:{} /* C++构造函数表 *
.const :{} /*常量数据 */
}

GROUP (可执行文件存储器)
{
.text :{} /*代码 *
.text:_ISR:{}
}
}> FRAM

.jtagsignature:{}> JTAGSIGNATURE/* JTAG Signature *
bslsignature:{}> BSLSIGNATURE /* BSL Signature *
.jtagpassword /* JTAG 密码 *

.bss :{}> RAM /*全局和静态变量 *
.data :{}> RAM /*全局和静态变量 *
.TI.noinit:{}>RAM /*用于#pragma noinit *
.cio :{}> RAM /* C I/O 缓冲器 *
sysmem :{}> RAM /*动态内存分配区域*/
堆栈 :{}> RAM (高) /*软件系统堆栈 *
.reset_vector:{}> FRAM_BOOT_ISR 
.text:_c_int00_noargs_noexit:{}> FRAM_BOOT_ISR /* MSP430中断矢量 * int00 :{} > INT00 .int01 :{} > INT01 .int02 :{} > INT02 .int03 :{} > INT03 .int04 :{} > INT04 .int05 :{} > INT05 .int06 :{} > INT06 .int07 :{} > INT07 .int08 :{} > INT08 .int09 :{} > INT09 INT10 :{} > INT10 INT11 :{} > INT11 INT12. :{} > INT12 INT13. :{} > INT13 INT14 :{} > INT14 .int15. :{} > INT15 .int16. :{} > Int16 .int17. :{} > INT17 .int18. :{} > INT18 .int19. :{} > INT19 .int20. :{} > INT20 .int21. :{} > INT21 .int22. :{} > INT22 .int23. :{} > INT23 .int24. :{} > INT24 .int25. :{} > INT25 .int26. :{} > INT26 .int27. :{} > INT27 .int28 :{} > INT28 .int29 :{} > INT29 .int30 :{} > INT30 .int31. :{} > INT31 .int32. :{} > Int32 .int33. :{} > INT33 .int34. :{} > INT34 .int35. :{} > INT35 .int36. :{} > INT36 .int37. :{} > INT37 .int38. :{} > INT38 .int39. :{} > INT39 int40. :{} > INT40 .int41. :{} > INT41 .int42. :{} > INT42 .int43. :{} > INT43 .int44. :{} > INT44 .int45. :{} > INT45 端口2 :{*(.int46)}> INT46 type = VECT_init 端口1 :{*(.int47 )}> INT47类型= VECT_INIT ADC :{*(.int48 )}>INT48 type = VECT_init USCI_B0 :{*(.int49)}> INT49类型= VECT_INIT USCI_A0 :{*(.int50)}> INT50类型= VECT_INIT WDT :{*(.int51 )}> INT51 type = VECT_init RTC :{*(.int52)}> INT52 type = VECT_init Timer1_A1:{*(.int53)}> INT53 type = VECT_init Timer1_A0:{*(.int54)}> INT54 type = VECT_init TIMER0_A1:{*(.int55 )}> INT55 TYPE = VECT_INIT TIMER0_A0:{*(.int56 )}> INT56 TYPE = VECT_INIT 联合国管理信息系统 :{*(.int57 )}>INT57 type = VECT_init SYSNMI :{*(.int58 )}> INT58 TYPE = VECT_INIT 复位 :{} > FRAM_JUTER_INstruction /* MSP430复位矢量 */ }

这是主应用中跳转到引导加载程序复位的跳转指令:

#pragma RETAIN (bootloader_jump)
#pragma location=0xC400
const int bootloader_jump []={0x0280、0x1900}; 

这是从引导加载程序返回到主程序的跳转:

((void (*)() 0xC408)(); 

这是掉电复位:

PMMCTL0 = PMMPW|PMMSWBOR; 

谢谢。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    已编辑以删除链接器代码的意外重复帖子

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Dan、您好!  

    我能不能问您为什么决定不将 MSP430FRBoot 用于此应用?

    [引用 user="Dan long]我已经了解到、 由于 MSP430FR2033 使用 FRAM、并且没有最小擦除大小(被视为 RAM)、因此不需要代理矢量表、但在 MSP430FRBOOT 代码示例中、它们确实有代理矢量表。 如果链接器包含硬件中断的相同地址、为什么不需要代理矢量表? 每个应用程序是否在引导时重新配置 int00中断中的硬件矢量表? 或者我是否需要 代理矢量表?

    MSP430FRBoot 不使用代理中断矢量表、即使在链接器文件中定义了一个矢量表。 MSP430FRBoot 是基于针对闪存器件的 MSPBoot 创建的、代码中仍有一些残留物需要删除。 在 MSPBoot 中、引导代码与中断矢量表位于同一个闪存段中。 如果用户想要更新矢量表、则需要擦除启动代码。 为了解决此问题、默认矢量表指向保存实际中断矢量的代理矢量表。 对于 FRAM 器件、这不是必需的、因为它们没有最小擦除大小、因此没有擦除引导代码的危险。  

    [引用 USER="Dan long]我们的设计是让硬件复位矢量始终跳转到引导加载程序的引导中断。 因此、引导加载程序可以检查主应用程序是否需要在启动时更新、如果没有更新、则跳转到主应用程序。 我们通过在 main 的 int00例程中使用一个跳转指令来跳转到 main。 我们 通过执行欠压复位从主应用程序跳转到引导加载程序。 欠压复位可以正常工作、但似乎没有跳转到引导加载程序 、我们不确定原因。

    我建议查看 MSP430FRBoot 是如何实现这一点的。 在引导加载程序链接器文件中、复位定义为默认复位中断地址0xFFFE。 这样、当 MCU 启动时、它将始终首先跳转到引导加载程序。 然后、要从引导加载程序跳回到应用程序、在 RAM 中设置密码、然后执行 BOR。 BOR 发生后、引导加载程序会检查此密码、然后使用您在 {(void (*)()_appl_Reset_Vector)();}上指定的类似代码行跳转到应用程序

    [引用 user="Dan long">我们应该为每个应用使用哪些闪存选项? 目前、我们使用完全擦除和编程在引导加载程序中进行闪存。 然后、我们通过在主应用程序上执行差分下载来刷写应用程序。 执行此操作时、我们立即失去调试控制、因为复位矢量进入引导加载程序。 这是将这两个应用程序闪存到同一处理器的正确方法吗?

    有多种方法可以实现此目的、具体取决于您是要维护调试还是要进行生产编程。 在 CCS 中、您可以通过加载当前运行的代码的符号来维持调试控制。 对于上述方法、这可能是最简单的方法。 加载应用程序代码后、您可以通过加载引导加载程序代码的符号来重新获得调试控制。 然后、当您跳转到应用程序时、您可以通过加载应用程序的符号来重新获得控制:

    希望这对您有所帮助、如果您有任何疑问、敬请告知。  

    此致、  

    Caleb Overbay

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 Caleb、

    [引用用户="Caleb Overbay"]

    我能不能问您为什么决定不将 MSP430FRBoot 用于此应用?

    [/报价]

    我们之所以不使用 MSP430FRBoot、是因为我们的系统要求从微控制器 遵循主器件的注册序列 、然后保持心跳消息 、以指示其在总线上是否出现在主应用程序或引导加载程序中。 这是使用特定的数据包和命令结构、我们认为这种结构在我们自己的自定义引导加载程序中更易于实现和使用。 这也将使我们能够灵活地进一步向下改变任何东西。 为了实现这一点、我们需要计时器中断和 I2C 中断。

    [引用 USER="Caleb Overbay">MSP430FRBoot 是基于为闪存器件制作的 MSPBoot 创建的、代码中仍有一些残留物需要删除。 [/报价]

    感谢您指出这一点。 这引起了一些混淆。

    [引用 USER="Caleb Overbay)]我建议查看 MSP430FRBoot 是如何实现这一点的。 在引导加载程序链接器文件中、复位定义为默认复位中断地址0xFFFE。 这样、当 MCU 启动时、它将始终首先跳转到引导加载程序。[/quot]

    发布后不久 、我们就设法确定了正确的复位过程、以进入和离开引导加载程序。 您的回答确认 我们现在正以正确的方式执行该操作。

    [引用 user="Caleb Overbay"]在 CCS 中,可以通过加载当前运行的代码的符号来保持调试控制。  

    这肯定有助于调试。 谢谢你。

    关于不需要代理矢量表、将中断重新定位到硬件中断矢量表的最佳方法是什么? 我们在主应用程序和引导加载程序中使用 I2C 和计时器。 目前、我们 在每个应用中都有一个 I2C 和一个计时器中断例程。   最好的方法是 将中断地址写入存储器中的单独保留位置 、然后 在需要时将其复制到硬件矢量表中? 例如、在离开引导加载程序之前、将主应用程序中断复制到硬件矢量表中、然后在引导加载程序启动时、将引导加载程序中断复制到硬件矢量表中? 或者是否有更干净的方法来实现这一目的?

    感谢您的帮助、您肯定已经为我们清除了其中的一些问题。

    此致、

    Dan

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Dan、您好!  

    [引用 USER="Dan long]关于不需要代理矢量表、将中断重新定位到硬件中断矢量表的最佳方法是什么? 我们在主应用程序和引导加载程序中使用 I2C 和计时器。 目前、我们 在每个应用中都有一个 I2C 和一个计时器中断例程。   最好的方法是 将中断地址写入存储器中的单独保留位置 、然后 在需要时将其复制到硬件矢量表中? 例如、在离开引导加载程序之前、将主应用程序中断复制到硬件矢量表中、然后在引导加载程序启动时、将引导加载程序中断复制到硬件矢量表中? 或者是否有更好的方法来实现此目的?

    在 MSPBoot 中、从不使用引导加载程序中的中断即可解决此问题。 因此、如果要在引导加载程序中使用 I2C 或计时器、则需要轮询中断标志。 不过、这可能不是您的应用的理想选择。 无论它们是用于引导加载程序还是用于应用程序、ISR 是否执行相同的函数? 如果是这种情况、您可以重复使用引导加载程序中的代码、而不是覆盖矢量。 如果没有、我很难想象比您描述的更好的方法。  

    此致、  
    Caleb Overbay

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好 Caleb、

    我已经测试过覆盖硬件矢量表、它似乎可以根据需要工作。 应用程序和引导加载程序中的 ISR 是相同的、但也可以进一步向下更改、因此将它们分开看起来是最佳方法。

    感谢你的帮助。

    此致、
    Dan