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.

[参考译文] TM4C123GH6PM:中断矢量、并分支到闪存中的新程序

Guru**** 2531950 points
Other Parts Discussed in Thread: EK-TM4C1294XL

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1168379/tm4c123gh6pm-interrupt-vector-and-branching-to-new-program-in-flash

器件型号:TM4C123GH6PM
Thread 中讨论的其他器件:EK-TM4C1294XL

大家好、

我将继续进行无线更新。 我有一个逻辑、可以将新的.bin 文件加载到闪存中的某个位置(即0x20000)、  并且正在运行的程序可以成功调用 入口点符号:"_c_int00_noargs" 地址:0001c701 、没有问题。

请注意、为了进行测试、我只使用 LM 闪存编程器(内部版本1613)将引导加载程序写入0x0000、将第二个程序写入0x00020000)

第2个程序按预期启动、但除简单 GPIO (打开和关闭引脚)之外的任何内容似乎都不起作用。  我当前的理论是任何需要中断矢量的东西都发生了故障。

请注意、如果我将 APP_BASE 值设置为0x0000、一切正常。 (在不使用简单引导加载程序的情况下独立运行。)

这是我的第二个程序的.cmd 文件:

/******************************************************************************
 *
 * Default Linker Command file for the Texas Instruments TM4C123GH6PM
 *
 * This is derived from revision 15071 of the TivaWare Library.
 *
 *****************************************************************************/

--retain=g_pfnVectors


/* The starting address of the application.  Normally the interrupt vectors  */
/* must be located at the beginning of the application.                      */

#define APP_BASE 0x00010000

#define RAM_BASE 0x20000000

/* System memory map */

MEMORY
{
    /* Application stored in and executes from internal flash */
    FLASH (RX) : origin = APP_BASE, length = 0x00020000
    /* Application uses internal RAM for data */
    SRAM (RWX) : origin = 0x20000000, length = 0x00020000
}

/* Section allocation in memory */

SECTIONS
{
    .intvecs:   > APP_BASE
    .text   :   > FLASH
    .const  :   > FLASH
    .cinit  :   > FLASH
    .pinit  :   > FLASH
    .init_array : > FLASH

    .vtable :   > RAM_BASE
    .data   :   > SRAM
    .bss    :   > SRAM
    .sysmem :   > SRAM
    .stack  :   > SRAM

#ifdef  __TI_COMPILER_VERSION__
#if     __TI_COMPILER_VERSION__ >= 15009000
    .TI.ramfunc : {} load=FLASH, run=SRAM, table(BINIT)
#endif
#endif
}

__STACK_TOP = __stack + 512;

编译后会创建预期的.map 文件(一切看起来都在正确的存储器位置)

******************************************************************************
                  TI ARM Linker PC v18.12.2                    
******************************************************************************
>> Linked Sat Nov  5 16:28:55 2022

OUTPUT FILE NAME:   <TIVA_PK_M1_Dec24.out>
ENTRY POINT SYMBOL: "_c_int00_noargs"  address: 0001c701


MEMORY CONFIGURATION

         name            origin    length      used     unused   attr    fill
----------------------  --------  ---------  --------  --------  ----  --------
  FLASH                 00010000   00020000  0000d3fe  00012c02  R  X
  SRAM                  20000000   00020000  00006d58  000192a8  RW X


SEGMENT ALLOCATION MAP

run origin  load origin   length   init length attrs members
----------  ----------- ---------- ----------- ----- -------
00010000    00010000    0000d400   0000d400    r-x
  00010000    00010000    0000026c   0000026c    r-- .intvecs
  0001026c    0001026c    0000c6fa   0000c6fa    r-x .text
  0001c968    0001c968    00000988   00000988    r-- .const
  0001d2f0    0001d2f0    00000110   00000110    r-- .cinit
20000000    20000000    00006d5c   00000000    rw-
  20000000    20000000    00004b54   00000000    rw- .bss
  20004b58    20004b58    00002000   00000000    rw- .stack
  20006b58    20006b58    00000204   00000000    rw- .data


SECTION ALLOCATION MAP

 output                                  attributes/
section   page    origin      length       input sections
--------  ----  ----------  ----------   ----------------
.intvecs   0    00010000    0000026c     
                  00010000    0000026c     tm4c123gh6pm_startup_ccs.obj (.intvecs)

... (cut of rest of file, I can post if needed.)

我有一个简单的引导加载程序、它只调用入口点:

void main()
{
    HWREG(NVIC_DIS0) = 0xffffffff;
    HWREG(NVIC_DIS1) = 0xffffffff;


    typedef void (*boot_loader_entry_t)(void);
    boot_loader_entry_t boot_loader_entry_ptr = (boot_loader_entry_t) 0x0001c701;
    boot_loader_entry_ptr();


    while(1)
    {
    }
}

如果有任何建议、我将不胜感激。  请注意、我多次查看 boot_loader 示例、它似乎是以汇编语言编写的 BL_startup.gcc.S 文件、并对我在简单引导加载程序中缺少的矢量表执行一些操作。

boot_demo1和 boot_demo2、startup.css.c 与我的类似:   

//*****************************************************************************
//
// Startup code for use with TI's Code Composer Studio.
//
// Copyright (c) 2011-2014 Texas Instruments Incorporated.  All rights reserved.
// Software License Agreement
// 
// Software License Agreement
//
// Texas Instruments (TI) is supplying this software for use solely and
// exclusively on TI's microcontroller products. The software is owned by
// TI and/or its suppliers, and is protected under applicable copyright
// laws. You may not combine this software with "viral" open-source
// software in order to form a larger program.
//
// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
// DAMAGES, FOR ANY REASON WHATSOEVER.
//
//*****************************************************************************

#include <stdint.h>
#include "inc/hw_nvic.h"
#include "inc/hw_types.h"

#include "tiva_uart_new.h"
#include "PK_MISC.h"

//*****************************************************************************
//
// Forward declaration of the default fault handlers.
//
//*****************************************************************************
void ResetISR(void);
static void NmiSR(void);
static void FaultISR(void);
static void IntDefaultHandler(void);

//*****************************************************************************
//
// External declaration for the reset handler that is to be called when the
// processor is started
//
//*****************************************************************************
extern void _c_int00(void);

//*****************************************************************************
//
// Linker variable that marks the top of the stack.
//
//*****************************************************************************
extern uint32_t __STACK_TOP;

//*****************************************************************************
//
// External declarations for the interrupt handlers used by the application.
//
//*****************************************************************************
// To be added by user

//*****************************************************************************
//
// The vector table.  Note that the proper constructs must be placed on this to
// ensure that it ends up at physical address 0x0000.0000 or at the start of
// the program if located at a start address other than 0.
//
//*****************************************************************************
#pragma DATA_SECTION(g_pfnVectors, ".intvecs")
void (* const g_pfnVectors[])(void) =
{
    (void (*)(void))((uint32_t)&__STACK_TOP),
                                            // The initial stack pointer
    ResetISR,                               // The reset handler
    NmiSR,                                  // The NMI handler
    FaultISR,                               // The hard fault handler
    IntDefaultHandler,                      // The MPU fault handler
    IntDefaultHandler,                      // The bus fault handler
    IntDefaultHandler,                      // The usage fault handler
    0,                                      // Reserved
    0,                                      // Reserved
    0,                                      // Reserved
    0,                                      // Reserved
    IntDefaultHandler,                      // SVCall handler
    IntDefaultHandler,                      // Debug monitor handler
    0,                                      // Reserved
    IntDefaultHandler,                      // The PendSV handler
    IntDefaultHandler,                      // The SysTick handler
    IntDefaultHandler,                      // GPIO Port A
    IntDefaultHandler,                      // GPIO Port B
    IntDefaultHandler,                      // GPIO Port C
    IntDefaultHandler,                      // GPIO Port D
    IntDefaultHandler,                      // GPIO Port E
    UARTStdioIntHandler0,                      // UART0 Rx and Tx
    IntDefaultHandler,                      // UART1 Rx and Tx
    IntDefaultHandler,                      // SSI0 Rx and Tx
    IntDefaultHandler,                      // I2C0 Master and Slave
    IntDefaultHandler,                      // PWM Fault
    IntDefaultHandler,                      // PWM Generator 0
    IntDefaultHandler,                      // PWM Generator 1
    IntDefaultHandler,                      // PWM Generator 2
    IntDefaultHandler,                      // Quadrature Encoder 0
    IntDefaultHandler,                      // ADC Sequence 0
    IntDefaultHandler,                      // ADC Sequence 1
    IntDefaultHandler,                      // ADC Sequence 2
    IntDefaultHandler,                      // ADC Sequence 3
    WatchdogIntHandler,                     // Watchdog timer
    IntDefaultHandler,                      // Timer 0 subtimer A
    IntDefaultHandler,                      // Timer 0 subtimer B
    IntDefaultHandler,                      // Timer 1 subtimer A
    IntDefaultHandler,                      // Timer 1 subtimer B
    IntDefaultHandler,                      // Timer 2 subtimer A
    IntDefaultHandler,                      // Timer 2 subtimer B
    IntDefaultHandler,                      // Analog Comparator 0
    IntDefaultHandler,                      // Analog Comparator 1
    IntDefaultHandler,                      // Analog Comparator 2
    IntDefaultHandler,                      // System Control (PLL, OSC, BO)
    IntDefaultHandler,                      // FLASH Control
    IntDefaultHandler,                      // GPIO Port F
    IntDefaultHandler,                      // GPIO Port G
    IntDefaultHandler,                      // GPIO Port H
    IntDefaultHandler,                      // UART2 Rx and Tx
    IntDefaultHandler,                      // SSI1 Rx and Tx
    IntDefaultHandler,                      // Timer 3 subtimer A
    IntDefaultHandler,                      // Timer 3 subtimer B
    IntDefaultHandler,                      // I2C1 Master and Slave
    IntDefaultHandler,                      // Quadrature Encoder 1
    IntDefaultHandler,                      // CAN0
    IntDefaultHandler,                      // CAN1
    0,                                      // Reserved
    0,                                      // Reserved
    IntDefaultHandler,                      // Hibernate
    IntDefaultHandler,                      // USB0
    IntDefaultHandler,                      // PWM Generator 3
    IntDefaultHandler,                      // uDMA Software Transfer
    IntDefaultHandler,                      // uDMA Error
    IntDefaultHandler,                      // ADC1 Sequence 0
    IntDefaultHandler,                      // ADC1 Sequence 1
    IntDefaultHandler,                      // ADC1 Sequence 2
    IntDefaultHandler,                      // ADC1 Sequence 3
    0,                                      // Reserved
    0,                                      // Reserved
    IntDefaultHandler,                      // GPIO Port J
    IntDefaultHandler,                      // GPIO Port K
    IntDefaultHandler,                      // GPIO Port L
    IntDefaultHandler,                      // SSI2 Rx and Tx
    IntDefaultHandler,                      // SSI3 Rx and Tx
    IntDefaultHandler,                      // UART3 Rx and Tx
    IntDefaultHandler,                      // UART4 Rx and Tx
    IntDefaultHandler,                      // UART5 Rx and Tx
    IntDefaultHandler,                      // UART6 Rx and Tx
    IntDefaultHandler,                      // UART7 Rx and Tx
    0,                                      // Reserved
    0,                                      // Reserved
    0,                                      // Reserved
    0,                                      // Reserved
    IntDefaultHandler,                      // I2C2 Master and Slave
    IntDefaultHandler,                      // I2C3 Master and Slave
    IntDefaultHandler,                      // Timer 4 subtimer A
    IntDefaultHandler,                      // Timer 4 subtimer B
    0,                                      // Reserved
    0,                                      // Reserved
    0,                                      // Reserved
    0,                                      // Reserved
    0,                                      // Reserved
    0,                                      // Reserved
    0,                                      // Reserved
    0,                                      // Reserved
    0,                                      // Reserved
    0,                                      // Reserved
    0,                                      // Reserved
    0,                                      // Reserved
    0,                                      // Reserved
    0,                                      // Reserved
    0,                                      // Reserved
    0,                                      // Reserved
    0,                                      // Reserved
    0,                                      // Reserved
    0,                                      // Reserved
    0,                                      // Reserved
    IntDefaultHandler,                      // Timer 5 subtimer A
    IntDefaultHandler,                      // Timer 5 subtimer B
    IntDefaultHandler,                      // Wide Timer 0 subtimer A
    IntDefaultHandler,                      // Wide Timer 0 subtimer B
    IntDefaultHandler,                      // Wide Timer 1 subtimer A
    IntDefaultHandler,                      // Wide Timer 1 subtimer B
    IntDefaultHandler,                      // Wide Timer 2 subtimer A
    IntDefaultHandler,                      // Wide Timer 2 subtimer B
    IntDefaultHandler,                      // Wide Timer 3 subtimer A
    IntDefaultHandler,                      // Wide Timer 3 subtimer B
    IntDefaultHandler,                      // Wide Timer 4 subtimer A
    IntDefaultHandler,                      // Wide Timer 4 subtimer B
    IntDefaultHandler,                      // Wide Timer 5 subtimer A
    IntDefaultHandler,                      // Wide Timer 5 subtimer B
    IntDefaultHandler,                      // FPU
    0,                                      // Reserved
    0,                                      // Reserved
    IntDefaultHandler,                      // I2C4 Master and Slave
    IntDefaultHandler,                      // I2C5 Master and Slave
    IntDefaultHandler,                      // GPIO Port M
    IntDefaultHandler,                      // GPIO Port N
    IntDefaultHandler,                      // Quadrature Encoder 2
    0,                                      // Reserved
    0,                                      // Reserved
    IntDefaultHandler,                      // GPIO Port P (Summary or P0)
    IntDefaultHandler,                      // GPIO Port P1
    IntDefaultHandler,                      // GPIO Port P2
    IntDefaultHandler,                      // GPIO Port P3
    IntDefaultHandler,                      // GPIO Port P4
    IntDefaultHandler,                      // GPIO Port P5
    IntDefaultHandler,                      // GPIO Port P6
    IntDefaultHandler,                      // GPIO Port P7
    IntDefaultHandler,                      // GPIO Port Q (Summary or Q0)
    IntDefaultHandler,                      // GPIO Port Q1
    IntDefaultHandler,                      // GPIO Port Q2
    IntDefaultHandler,                      // GPIO Port Q3
    IntDefaultHandler,                      // GPIO Port Q4
    IntDefaultHandler,                      // GPIO Port Q5
    IntDefaultHandler,                      // GPIO Port Q6
    IntDefaultHandler,                      // GPIO Port Q7
    IntDefaultHandler,                      // GPIO Port R
    IntDefaultHandler,                      // GPIO Port S
    IntDefaultHandler,                      // PWM 1 Generator 0
    IntDefaultHandler,                      // PWM 1 Generator 1
    IntDefaultHandler,                      // PWM 1 Generator 2
    IntDefaultHandler,                      // PWM 1 Generator 3
    IntDefaultHandler                       // PWM 1 Fault
};

//*****************************************************************************
//
// This is the code that gets called when the processor first starts execution
// following a reset event.  Only the absolutely necessary set is performed,
// after which the application supplied entry() routine is called.  Any fancy
// actions (such as making decisions based on the reset cause register, and
// resetting the bits in that register) are left solely in the hands of the
// application.
//
//*****************************************************************************
void
ResetISR(void)
{
    //
    // Jump to the CCS C initialization routine.  This will enable the
    // floating-point unit as well, so that does not need to be done here.
    //
    __asm("    .global _c_int00\n"
          "    b.w     _c_int00");
}

//*****************************************************************************
//
// This is the code that gets called when the processor receives a NMI.  This
// simply enters an infinite loop, preserving the system state for examination
// by a debugger.
//
//*****************************************************************************
static void
NmiSR(void)
{
    //
    // Enter an infinite loop.
    //
    while(1)
    {
    }
}

//*****************************************************************************
//
// This is the code that gets called when the processor receives a fault
// interrupt.  This simply enters an infinite loop, preserving the system state
// for examination by a debugger.
//
//*****************************************************************************
static void
FaultISR(void)
{
    //
    // Enter an infinite loop.
    //
    while(1)
    {
    }
}

//*****************************************************************************
//
// This is the code that gets called when the processor receives an unexpected
// interrupt.  This simply enters an infinite loop, preserving the system state
// for examination by a debugger.
//
//*****************************************************************************
static void
IntDefaultHandler(void)
{
    //
    // Go into an infinite loop.
    //
    while(1)
    {
    }
}

再次感谢您的任何建议、

Bob

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [引用 userid="51949" URL"~/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1168379/tm4c123gh6pm-interrupt-vector-and-branching-to-new-program-in-flash ]]注意,为了进行测试,我只使用 LM Flash Programmer (内部版本1613)将引导加载程序写入0x0000,将第二个程序写入0x00020000)[/quot]

    虽然该帖子说您将第二个程序写入 0x00020000、 但第二个程序的.cmd 文件包含:

    /* The starting address of the application.  Normally the interrupt vectors  */
    /* must be located at the beginning of the application.                      */
    
    #define APP_BASE 0x00010000

    其中、APP_BASE 值 0x00010000用于设置中断矢量的地址和闪存存储器区域的原点:

        .intvecs:   > APP_BASE
        
        /* Application stored in and executes from internal flash */
        FLASH (RX) : origin = APP_BASE, length = 0x00020000

    LM Flash Programmer 是否确实用于将第二个程序写入 0x00020000而不是 0x00010000、或者这是帖子中的拼写错误?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [引用 userid="51949" URL"~/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1168379/tm4c123gh6pm-interrupt-vector-and-branching-to-new-program-in-flash "]我的当前理论是任何需要中断矢量的东西都发生了故障。

    第2个程序是否设置 矢量表偏移量(VTABLE)寄存器?

    复位时、VTABLE 为0x0000000、这是闪存的起始位置(引导加载程序已编程的位置)。

    如果第二个程序需要使用中断、则需要更改 VTABLE 的值。

    查看 TivaWare_C_Series-2.2.0.295/examples/boards/ek-tm4c1294xl/USB_stick_update/USB_stick_update.c、可以使用以下 CallApplication 函数调用应用程序的入口点、该应用程序会将矢量表设置为闪存中应用程序的开头:

    #elif defined(ccs)
    void
    CallApplication(uint_fast32_t ui32StartAddr)
    {
        //
        // Set the vector table to the beginning of the app in flash.
        //
        HWREG(NVIC_VTABLE) = ui32StartAddr;
    
        //
        // Load the stack pointer from the application's vector table.
        //
        __asm("    ldr     r1, [r0]\n"
              "    mov     sp, r1\n");
    
        //
        // Load the initial PC from the application's vector table and branch to
        // the application's entry point.
        //
        __asm("    ldr     r0, [r0, #4]\n"
              "    bx      r0\n");
    }
    #else
    

    其中 、CallApplication 还从矢量表中读取初始堆栈指针和初始 PC、这也将避免引导加载 程序对 boot_loader_entry_ptr 的值进行硬编码(该值可能在应用程序更改时发生更改)。

    即、建议在引导加载程序中添加 CallApplication 函数(该函数以 TI ARM 编译器支持的格式使用内联汇编器)并替换:

        typedef void (*boot_loader_entry_t)(void);
        boot_loader_entry_t boot_loader_entry_ptr = (boot_loader_entry_t) 0x0001c701;
        boot_loader_entry_ptr();

    其中:

        CallApplication (0x10000); /* Transfer to the application with the vector table starting at address 0x10000 */

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

    闪存编程器正在写入0x10000、 APP_BASE 值。  我注意到您突出显示了长度长度。  我是否需要在此处进行更改?

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

    第2个程序未设置 VTABLE。  感谢您的建议、我将在周一晚上查看并与小组成员再次进行讨论。

    谢谢、

    Bob

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [引用 userid="51949" URL"~/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1168379/tm4c123gh6pm-interrupt-vector-and-branching-to-new-program-in-flash/4395653 #4395653]Flash 编程器正在写入0x10000、 APP_BASE 值。  我注意到您突出显示了长度长度。  我是否需要在此处进行更改?

    无需更改;LM 闪存编程器设置看起来正常并且与 APP_BASE 的设置相匹配。

    当我第一次读取您的原始帖子时、我认为以下情况意味着 LM 闪存编程器中的程序地址偏移可能已设置为0x20000而不是0x10000:

    [引用 userid="51949" URL"~/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1168379/tm4c123gh6pm-interrupt-vector-and-branching-to-new-program-in-flash ]]注意,为了进行测试,我只使用 LM Flash Programmer (内部版本1613)将引导加载程序写入0x0000,将第二个程序写入0x00020000)[/quot]
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    切斯特、

    非常感谢!!!!!!!!!!!!!!!!!  这解决了我的问题!

    我非常感谢您的帮助。

    Bob