Thread 中讨论的其他器件:EK-TM4C1294XL
您好!
我为 SD 卡引导加载程序自定义了引导加载程序代码。一切正常、但此代码无法跳转并执行应用程序文件。请检查是否缺少任何内容。
连接引导加载程序 codee2e.ti.com/.../X24015_5F00_boot_5F00_loader_5F00_sd.rar
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.
您好!
我为 SD 卡引导加载程序自定义了引导加载程序代码。一切正常、但此代码无法跳转并执行应用程序文件。请检查是否缺少任何内容。
连接引导加载程序 codee2e.ti.com/.../X24015_5F00_boot_5F00_loader_5F00_sd.rar
这是我用于 BL_main.c 的引导加载程序代码
//
//
// bl_main.c -文件保存引导加载程序的主控制循环。
//
//版权所有(c) 2006-2020 Texas Instruments Incorporated。 保留所有权利。
//软件许可协议
//
//德州仪器(TI)仅提供和使用此软件
//专门用于 TI 的微控制器产品。 该软件归其所有
// TI 和/或其供应商、受适用版权保护
//法律。 您不能将此软件与"病毒"开源软件结合使用
//软件,以便形成一个更大的程序。
//
//此软件按“原样”提供,且存在所有故障。
//不作任何明示、暗示或法定的保证,包括但
//不限于对适销性和适用性的暗示保证
//此软件的特定用途。 TI 不得在任何情况下使用
//情况,对特殊、偶然或从属事件负责
//任何原因造成的损害。
//
//这是 Tiva 固件开发包2.2.0.295修订版的一部分。
//
//
#include
#include
#include
#include "inc/hw_gpio.h"
#include "inc/hw_flash.h"
#include "inc/hw_i2c.h"
#include "inc/hw_memmap.h"
#include "inc/hw_NVIC.h"
#include "inc/hw_ssI.h"
#include "inc/hw_sysctl.h"
#include "inc/hw_types.h"
#include "bl_config.h"
#include "bootloader/bl_flash.h"
#include "bootloader/bl_hooks.h"
#include "driverlib/gpio.h"
#include "driverlib/pin_map.h"
#include "driverlib/ssi.h"
#include "driverlib/rom.h"
#include "driverlib/rom_map.h"
#include "driverlib/sysctl.h"
#include "Petit/pff.h"
#include "Petit/pffconf.h"
#include "custom.h"
//
//指定一次从文件读取多少个字节来写入闪存
//如果增大 RAM 大小,则会缩短程序加载时间
//否则减小 RAM 大小会增加程序加载时间
//
#define WRITE_DATA_PACKET_SIZE 128//128 -默认值
静态字节 bWriteBuffer[WRITE_DATA_PACKE_SIZE];
静态 FATFS 死亡;
//函数原型
void ConfigureSSIPort (uint32_t ui32协议、uint32_t ui32模式、
uint32_t ui32BitRate、uint32_t ui32DataWidth);
//
//
//确保应用程序起始地址位于闪存页边界上
//
//
#if (APP_START_ADDRESS &(FLASH_PAGE_SIZE - 1))
错误错误:APP_START_ADDRESS 必须是 FLASH_PAGE_SIZE 字节的倍数!
#endif
//
//
//确保闪存保留空间是闪存页的倍数。
//
//
#if (FLASH_RSVD_SPACE 和(FLASH_PAGE_SIZE - 1))
错误错误:FLASH_RSVD_SPACE 必须是 FLASH_PAGE_SIZE 字节的倍数!
#endif
//
//
//! \addtogroup bl_main_API
//! @{
//
//
//
//
//用于调用的函数的原型(在启动代码中)
//应用。
//
//
extern void CallApplication (uint32_t ui32Base);
//
//
//可预测长度的函数原型(在启动代码中)
//延迟。
//
//
extern void delay (uint32_t ui32Count);
//
//
//将一个字从大端字节序转换为小端字节序。 这个宏使用编译器-
//执行"rev"指令内联插入的特定结构,
//它直接执行字节交换。
//
//
#IF 定义(ewarm)
#include
#define SwapWord (x)_REV (x)
#endif
#if defined (CodeRed)|| Defined (gcc)|| Defined (sourceygxx)
#define SwapWord (x)__extension__\
({\
寄存器 uint32_t __ret、__INP = x;\
__asm__("rev %0,%1":"=r"(__ret):"r"(__INP));\
__转台;\
})
#endif
#if defined (rvmdk)|| defined (__ARMCC_VERSION)
#define SwapWord (x)_rev (x)
#endif
#if defined (CCS)(如果已定义)
uint32_t
SwapWord (uint32_t x)
{
_asm (" rev r0、r0\n"
" BX lr\n");//需要此操作以确保返回 r0
return (x + 1);// return 使编译器满意-忽略
}
#endif
//
//
//! 配置微控制器。
//!
//! 此函数用于配置微控制器的外设和 GPIO、
//! 准备供引导加载程序使用。 接口
//! 因为更新端口将被配置、并且将自动波特
//! 必要时执行。
//!
//! \无返回。
//
//
空配置设备(空)
{
#ifdef crystal_FREQ
//
//由于指定了晶振频率,因此启用主振荡器
//并从它为处理器计时。
//
#if defined (target_IS_TM4C129_RA0)||\
已定义(TARGET_IS_TM4C129_RA1)||\
已定义(TARGET_IS_TM4C129_RA2)
//
//由于指定了晶振频率,因此启用主振荡器
//并从它为处理器计时。 检查振荡器范围
//必须设置,等待状态需要更新
//
if (crystal_FREQ >= 10000000)
{
HWREG (SYSCTL_MOSCCTL)|=(SYSCTL_MOSCCTL_OSCRNG);
HWREG (SYSCTL_MOSCCTL)&=~(SYSCTL_MOSCCTL_PWRDN |
SYSCTL_MOSCCTL_NOXTAL);
}
其他
{
HWREG (SYSCTL_MOSCCTL)&=~(SYSCTL_MOSCCTL_PWRDN |
SYSCTL_MOSCCTL_NOXTAL);
}
//
//等待振荡器稳定
//
延迟(524288);
if (crystal_FREQ > 16000000)
{
HWREG (SYSCTL_MEMTIME0)=(SYSCTL_MEMTIME0_FBCHT_1_5 |
(1 << SYSCTL_MEMTIME0_FWS_S)|
SYSCTL_MEMTIME0_EBCHT_1_5 |
(1 << SYSCTL_MEMTIME0_EWS_S)|
SYSCTL_MEMTIME0_MB1);
HWREG (SYSCTL_RSCLKCFG)=(SYSCTL_RSCLKCFG_MEMTIMEU |
SYSCTL_RSCLKCFG_OSCSRC_MOSC);
}
其他
{
HWREG (SYSCTL_RSCLKCFG)=(SYSCTL_RSCLKCFG_OSCSRC_MOSC);
}
其他
HWREG (SYSCTL_RCC)&=~(SYSCTL_RCC_MOSCDIS);
延迟(524288);
HWREG (SYSCTL_RCC)=((HWREG (SYSCTL_RCC)&~(SYSCTL_RCC_OSCSRC_M)))|
SYSCTL_RCC_OSCSRC_MAIN);
#endif
#endif
}
//
//
//! 在 SPI 模式中为 SD 接口配置 SSI 端口 SPI。
//
//
空配置 SSI (空)
{
/*启用 SD SSI 外设*/
ROM_SysCtlPeripheralEnable (SD_SYSCTL_Periph_SSI);
ROM_SysCtlPeripheralEnable (SD_SYSCTL_Periph_GPIO_SCLK);
ROM_SysCtlPeripheralEnable (SD_SYSCTL_Periph_GPIO_MOSI);
ROM_SysCtlPeripheralEnable (SD_SYSCTL_Periph_GPIO_MISO);
ROM_SysCtlPeripheralEnable (SD_SYSCTL_Periph_GPIO_FSS);
/* SSI-1配置引脚*/
SSI SSI1CLK 的//使能引脚
ROM_GPIOPinConfigure (SD_GPIO_SCLK_PINCFG);
ROM_GPIOPinTypeSSI (SD_GPIO_SCLK_base、SD_GPIO_SCLK_PIN);
SSI SSI1XDAT0 (MOSI)的//使能引脚
ROM_GPIOPinConfigure (SD_GPIO_MOSI_PINCFG);
ROM_GPIOPinTypeSSI (SD_GPIO_MOSI_BASE、SD_GPIO_MOSI_PIN);
SSI SSI1XDAT1的//使能引脚(MISO)
ROM_GPIOPinConfigure (SD_GPIO_MISO/PINCFG);
ROM_GPIOPinTypeSSI (SD_GPIO_MISO、SD_GPIO_MISO);
//为 SSI1 SSI1FSS 启用引脚 PB4
//GPIOPinConfigure (SD_GPIO_FFS_PINCFG);
//GPIOPinTypeSSI (SD_GPIO_FSS_BASE、SD_GPIO_FSS_PIN);
// GPIOOutput 的使能引脚 PK7 (SSI1FSS_SD)
ROM_GPIOPinTypeGPIOOutput (SD_GPIO_FFS_BASE、SD_GPIO_FFS_PIN);
/*配置焊盘设置*/
/* SCLK (PD3)*/
MAP_GPIOPadConfigSet (SD_GPIO_SCLK_base、
SD_GPIO_SCLK_PIN、
GPIO_Strength _4mA、GPIO_PIN_TYPE_STD);
/* MOSI (PD1)*/
MAP_GPIOPadConfigSet (SD_GPIO_MOSI_BASE、
SD_GPIO_MOSI_PIN、
GPIO_Strength _4mA、GPIO_PIN_TYPE_STD);
/* MISO (PD0)*/
MAP_GPIOPadConfigSet (SD_GPIO_MISO/base、
SD_GPIO_MISO、
GPIO_Strength _4mA、GPIO_PIN_TYPE_STD_WPU);
/* CS (PD2)*/
MAP_GPIOPadConfigSet (SD_GPIO_FFS_BASE、
SD_GPIO_FFS_PIN、
GPIO_Strength _4mA、GPIO_PIN_TYPE_STD);
//
//为 SPI 主控模式配置和启用 SSI 端口。 使用 SSI1、
//系统时钟电源,空闲时钟低电平和低电平有效时钟输入
//飞思卡尔 SPI 模式、主控模式、1MHz SSI 频率和8位数据。
//对于 SPI 模式,可以设置 SSI 时钟的极性
//单元空闲。 您还可以配置所需的时钟边沿
//在上捕获数据。 有关的更多信息、请参阅数据表
//不同的 SPI 模式。
//
uint32_t sysclock = 120000000;
ROM_SSIConfigSetExpClk (SD_SSI_base、sysclock、SSI_FRF_MOTO_MOTO_0、SSI_MODE_MASTER、400000、 8);
//
//启用 SSI1模块。
//
ROM_SSIEnable (SD_SSI_base);
}
//
//
//! 此函数对所选端口执行更新。
//!
//! 此函数由引导加载程序直接调用或作为调用
//! 应用程序更新请求的结果。
//!
//! 返回但不返回。
//
//
空更新程序(空)
{
/*
uint32_t EraseSize=0;
uint32_t AppAddress=0;
uint32_t i、j、k、l;
uint32_t WriteDataPacketCount;
uint32_t WriteDataPacketRemainder;
FRESULT RC;
通用 br
*
uint32_t EraseSize=0;
uint32_t AppAddress=0;
uint32_t i、j;
uint32_t WriteDataPacketCount、WriteDataPacketRemainder;
FRESULT RC;
FATFS 死亡;
通用 br
//初始化控制台消息的 UART
ConfigureUART();
//初始化 SSI 控制器
ConfigureSSI();
// LED GPIO 引脚设置
ROM_SysCtlPeripheralEnable (SYSCTL_Periph_GPION);
ROM_GPIOPinTypeGPIOOutput (GPIO_PORTN_BASE、GPIO_PIN_1);
// LED 闪烁
ROM_GPIOPinWrite (GPIO_PORTN_BASE、GPIO_PIN_1、GPIO_PIN_1);
for (i=0;i<100000;i++);
ROM_GPIOPinWrite (GPIO_PORTN_BASE、GPIO_PIN_1、!GPIO_PIN_1);
for (i=0;i<100000;i++);
//尝试安装 SD 卡10次。 每次尝试时闪烁 LED。
J=0;
执行{
RC = pf_mount (&fatfs);
ROM_GPIOPinWrite (GPIO_PORTN_BASE、GPIO_PIN_1、GPIO_PIN_1);
for (i=0;i<100000;i++);
ROM_GPIOPinWrite (GPIO_PORTN_BASE、GPIO_PIN_1、!GPIO_PIN_1);
for (i=0;i<100000;i++);
J++;
}
while (rc && j<10);
//如果 SD 卡安装失败,则退出,否则继续
if (!rc){
//尝试打开 SD 卡中的 app.bin 文件(如果存在) 10次。 每次尝试时闪烁 LED。
J=0;
执行{
RC = pf_open ("X24015.bin");
ROM_GPIOPinWrite (GPIO_PORTN_BASE、GPIO_PIN_1、GPIO_PIN_1);
for (i=0;i<100000;i++);
ROM_GPIOPinWrite (GPIO_PORTN_BASE、GPIO_PIN_1、!GPIO_PIN_1);
for (i=0;i<100000;i++);
J++;
}
while (rc && j<10);
//如果 app.bin 文件失败,则打开 exit,否则继续
if (!rc)
{
UARTprintf ("fatfs.fsize %d \n"、fatfs.fsize);
//如果文件大小不是4个 exit 的倍数,则继续
if ((fatfs.fsize & 0x03)==0)
{
//计算将根据 app.bin 文件大小擦除的页数
EraseSize = fatfs.fsize/flash_page_size;
if (fatfs.fsize%flash_page_size)
EraseSize++;
//擦除必要的页
AppAddress=APP_START_ADDRESS;
for (i=0;i< EraseSize;i++)
{
ROM_FlashErase (AppAddress);
AppAddress += FLASH_PAGE_SIZE;
}
AppAddress=APP_START_ADDRESS;//设置要写入的应用地址
//根据用户定义的写入数据包大小计算数据包计数
WriteDataPacketCount=fatfs.fsize/write_data_packet_size;
UARTprintf ("WriteDataPacketCount %d \n"、WriteDataPacketCount);
//计算除法的余数
WriteDataPacketRemainder=fatfs.fsize=write_data_packet_size;
UARTprintf ("WriteDataPacketRemainder %d \n"、WriteDataPacketRemainder);
//从 app.bin 文件和中读取 write_data_packet_size 个字节的数量
//将其写入闪存存储器的 WriteDataPacketCount 次。
for (i=0;i<WriteDataPacketCount;i++){
PF_Read (bWriteBuffer、WRITE_DATA_PACKE_SIZE、&);
ROM_FlashProgram (((uint32_t*) bWriteBuffer、AppAddress、write_data_packet_size);
AppAddress += write_data_packet_size;
UARTPutch ('.');
}
//从 app.bin 文件和中读取4个字节
//将其写入快闪存储器的 WriteDataPacketRemainder 次数。
for (i=0;i<WriteDataPacketRemaineder/4;i++)
{
PF_Read (bWriteBuffer、4、& br);
ROM_FlashProgram (((uint32_t*) bWriteBuffer、AppAddress、4);
AppAddress += 4;
}
//如果完成,则以较长的延迟使 LED 闪烁2次。
ROM_GPIOPinWrite (GPIO_PORTN_BASE、GPIO_PIN_1、GPIO_PIN_1);
for (i=0;i<1000000;i++);
ROM_GPIOPinWrite (GPIO_PORTN_BASE、GPIO_PIN_1、!GPIO_PIN_1);
for (i=0;i<1000000;i++);
ROM_GPIOPinWrite (GPIO_PORTN_BASE、GPIO_PIN_1、GPIO_PIN_1);
for (i=0;i<1000000;i++);
ROM_GPIOPinWrite (GPIO_PORTN_BASE、GPIO_PIN_1、!GPIO_PIN_1);
for (i=0;i<1000000;i++);
UARTprintf ("Done1\n");
//复位和禁用引导加载程序使用的 SSI 外设。
ROM_SysCtlPeripheralDisable (SD_SYSCTL_Periph_SSI);
ROM_SysCtlPeripheralReset (SD_SYSCTL_Periph_SSI);
ROM_SysCtlPeripheralDisable (SD_SYSCTL_Periph_GPIO_SCLK);
ROM_SysCtlPeripheralReset (SD_SYSCTL_Periph_GPIO_SCLK);
ROM_SysCtlPeripheralDisable (SD_SYSCTL_Periph_GPIO_MOSI);
ROM_SysCtlPeripheralReset (SD_SYSCTL_Periph_GPIO_MOSI);
ROM_SysCtlPeripheralDisable (SD_SYSCTL_Periph_GPIO_MISO);
ROM_SysCtlPeripheralReset (SD_SYSCTL_Periph_GPIO_MISO);
ROM_SysCtlPeripheralDisable (SD_SYSCTL_Periph_GPIO_FSS);
ROM_SysCtlPeripheralReset (SD_SYSCTL_Periph_GPIO_FSS);
for (i=0;i<1000000;i++);
UARTprintf ("Done2\n");
for (i=0;i<1000000;i++);
((int (*)(void)) app_start_address)();
HWREG (NVIC_APINT)=(NVIC_APINT_VECTKEY | NVIC_APINT_SYSRESETREQ);
while (1);
}
}
}
// for (i=0;i<1000000;i++);
// UARTprintf ("Done11\n");
// for (i=0;i<1000000;i++);
//重置
((int (*)(void)) app_start_address)();
HWREG (NVIC_APINT)=(NVIC_APINT_VECTKEY | NVIC_APINT_SYSRESETREQ);
}
//
//
//关闭 Doxygen 组。
//! @}
//
//
这是 bl_config.h 文件
其中起始地址为 #define APP_START_ADDRESS 0x00004000
//
//
// bl_config.h -引导加载程序的可配置参数。
//
//版权所有(c) 2010-2017 Texas Instruments Incorporated。 保留所有权利。
//软件许可协议
//
//德州仪器(TI)仅提供和使用此软件
//专门用于 TI 的微控制器产品。 该软件归其所有
// TI 和/或其供应商、受适用版权保护
//法律。 您不能将此软件与"病毒"开源软件结合使用
//软件,以便形成一个更大的程序。
//
//此软件按“原样”提供,且存在所有故障。
//不作任何明示、暗示或法定的保证,包括但
//不限于对适销性和适用性的暗示保证
//此软件的特定用途。 TI 不得在任何情况下使用
//情况,对特殊、偶然或从属事件负责
//任何原因造成的损害。
//
//这是 Tiva 固件开发包的修订版2.1.4.178的一部分。
//
//
#ifndef __BL_CONFIG_H__
#define __BL_CONFIG_H__
#include "custom.h"
//
//
//以下定义用于配置引导操作
//加载程序。 对于每个定义、都描述了它与其他定义的交互。
//第一个是依赖项(即如果它也必须定义的定义)
//已定义),接下来是排除(即无法定义的定义)
//如果定义了它),最后是要求(即
//定义如果定义了它,则必须定义)。
//
//引导加载程序必须定义以下定义
//操作:
//
//其中一个 CAN_ENABLE_UPDATE、ENET_ENABLE_UPDATE、I2C_ENABLE_UPDATE、
// SSI_ENABLE_UPDATE、UART_ENABLE_UPDATE 或 USB_ENABLE_UPDATE
// app_start_address
// stack_size
// buffer_size
//
//
//
//
//用于为微控制器计时的晶体的频率。
//
//这定义了运行的微控制器所使用的晶振频率
//引导加载程序。 如果在生产时这是未知的、则使用
// UART_autobaud 功能以正确配置 UART。
//
//取决于:无
//不包括:无
//要求:无
//
//
#define CRYSTICL_FREQ 25000000
//
//
//这可以将 LDO 电压升压到2.75V。 引导加载程序
//启用 PLL 的配置(例如、使用以太网端口)
//对于具有 PLL 勘误表的器件,应启用此功能。 这适用于
// Fury 级器件的修订版 A2。
//
//取决于:无
//不包括:无
//要求:无
//
//
//#define BOOST_LDO_VOLTAGE
//
//
//应用程序的起始地址。 这必须是1024的倍数
//字节(使其与页边界对齐)。 矢量表的预期值为
//此位置,以及向量表(位于的栈)的感知有效性
//在 SRAM 中、位于闪存中的复位矢量)用作的指示
//应用程序映像的有效性。
//
//引导加载程序的闪存映像不得大于此值。
//
//取决于:无
//不包括:无
//要求:无
//
//
#define APP_START_ADDRESS 0x00004000
//
//
//应用程序查找其异常矢量表的地址。
//这必须是1KB 的倍数(使其与页边界对齐)。
//通常,应用程序将从其矢量表和该值开始
//将默认为 APP_START_ADDRESS。 提供此选项以满足需求
//从无法访问的外部存储器运行的应用程序
// NVIC (矢量表偏移寄存器的长度只有30位)。
//
//取决于:无
//不包括:无
//要求:无
//
//
#define VTABLE vstart_address 0x00004000
//
//
//闪存中单个可擦除页的大小。 这必须是电源
//共2个。 默认值1KB 表示内部的页面大小
//所有 Tiva MCU 上的闪存和该值只应在以下情况下被覆盖
//配置引导加载程序以访问页大小的外部闪存设备
//与此不同。
//
//取决于:无
//不包括:无
//要求:无
//
//
#define FLASH_PAGE_SIZE 0x00004000
//
//
//闪存末尾要保留的空间量。 这必须是 A
// 1024字节的倍数(使其与页边界对齐)。 这种情况
//更新应用程序时不会擦除保留空间,提供
//可用于参数的非易失性存储。
//
//取决于:无
//不包括:无
//要求:无
//
//
//#define FLASH_RSVD_SPACE 0x00000800
//
//
//为引导加载程序保留的堆栈空间字数。
//
//取决于:无
//不包括:无
//要求:无
//
//
#define STACK_SIZE 1024
//
//
//数据缓冲区中用于接收数据包的字数。 这种情况
//值必须至少为3。 如果在 UART 上使用自动辅助、则必须位于
//至少20个。 最大可用值为65 (较大的值将导致
//缓冲区中未使用的空间)。
//
//取决于:无
//不包括:无
//要求:无
//
//
#define buffer_size 20
//
//
//启用基于引脚的强制更新检查。 启用后、引导加载程序
//将进入更新模式,而不是在读取引脚时调用应用程序
//在特定极性强制执行更新操作。 在这两种情况下、都是
//应用程序仍然能够将控制权返回给引导加载程序以
//开始更新。
//
//取决于:无
//不包括:无
//需要:forced_update_Periph、forced_update_port、forced_update_pin、
//强制_更新_极性
//
//
#define ENABLE_UPDATE_CHECK
//
//
//启用 GPIO 模块以检查强制更新。 这将会
//是 SYSCTL_RCGCGPIO_Rx 值之一、其中 Rx 代表所需值
// GPIO 端口。 这适用于 Blizzard 类以及用于 forced_update_port 的更高版本器件。
//
//取决于:enable_update_check
//不包括:无
//库:无
//
//
#define Forced_update_Periph sysctl_RCGCGPIO_R5 /*端口 F */
//
//
// GPIO 端口以检查强制更新。 这将是其中之一
// GPIO_Portx_BASE 值、其中"x"替换为端口名称(例如
// B)。 "x"的值应与"x"的值匹配
// Forced_update_Periph。
//
//取决于:enable_update_check
//不包括:无
//库:无
//
//
#define FORUD_UPDATE_PORT GPIO_PORTF_BASE
//
//
//检查强制更新的引脚。 这是一个介于0和7之间的值。
//
//取决于:enable_update_check
//不包括:无
//库:无
//
//
#define Forced_update_PIN 4 //连接到引导开关的 PF4
//
//
//导致强制更新的 GPIO 引脚的极性。 该值
如果引脚应为低电平、//应为0;如果引脚应为高电平、则应为1。
//
//取决于:enable_update_check
//不包括:无
//库:无
//
//
#define Forced_update_polarity 0 // PF0 = 0触发引导加载程序更新
//
//
//这为强制更新中使用的 GPIO 引脚启用弱上拉。 这种情况
如果引脚应该具有内部弱下拉电阻、//值应该为0
// 1如果引脚应该具有内部弱上拉电阻。
//只应定义 Forced_update_WPU 或 Forced_update_wpd,或两者都不应定义。
//
//取决于:enable_update_check
//不包括:无
//库:无
//
//
//#define Forced_update_WPU
//#define forced_update_wpd
//
//
//这可以使用 GPIO_LOCK 机制进行配置
//受保护的 GPIO 引脚(例如 JTAG 引脚)。 如果未定义此值、
//不使用锁定机制。 唯一的合法值
//功能包括 Fury 器件的 GPIO_LOCK_KEY 和全部的 GPIO_LOCK_KEY_DD
//除 Sandstorm 设备以外的其它设备,它们不支持此功能。
//
//取决于:enable_update_check
//不包括:无
//库:无
//
//
//#define Forced_update_key GPIO_lock_key
//#define Forced_update_key GPIO_lock_key_DD
//
//
//引导加载程序挂钩函数。
//
//以下定义允许您添加特定于应用程序的函数
//在引导加载程序执行期间的不同点调用。
//
//
//
//
//在系统上执行应用特定的低级硬件初始化
//复位。
//
//如果挂钩,则在引导加载程序之后立即调用此函数
//代码重定位完成。 应用程序可以执行任何所需的低电平
//在该函数期间进行硬件初始化。 请注意系统时钟
调用此函数时、//尚未设置。 进行初始化
//可以在 BL_INIT_FN_Hook 函数中执行系统时钟设置
//而是。
//
// void MyHwInitFunc (void);
//
//
//#define BL_HW_INIT_FN_Hook MyHwInitFunc
//
//
//在系统复位时执行应用特定的初始化。
//
//如果挂钩,则在引导加载程序之后立即调用此函数
//设置系统时钟。 应用程序可以执行任何附加操作
//在此函数期间进行初始化。
//
// void MyInitFunc (void);
//
//
#define BL_INIT_FN_Hook MyInitFunc
//
//
//通过 SVC 在引导加载程序进入时执行应用特定的重新初始化。
//
//如果挂钩,则在引导加载程序之后立即调用此函数
//从应用程序输入时,重新初始化系统时钟
//通过 SVC 机制而不是系统复位的结果。 一个
//应用程序可以在此函数中执行任何其他重新初始化。
//
// void MyReinitFunc (void);
//
//
//#define BL_reinit_fn_hook MyReinitFunc
//
//
//通知应用程序正在开始下载。
//
//如果已连接,则在下载新固件时将调用此函数
//即将开始。 应用程序可以使用该信号来初始化任何信号
//进度显示。
//
//空 MyStartFunc (空);
//
//
#define BL_START_FN_Hook MyStartFunc
//
//
//通知应用程序 SD 驱动器安装状态
//
//如果已连接,则在加载程序安装 SD 驱动器时调用此函数。
//
//空 MyMountFunc (uint32_t 错误);
//
//
#define BL_MOUN_FN_Hook MyMountFunc
//
//
//通知应用程序 SD 驱动器映像文件打开状态。
//
//如果挂钩,则在加载程序打开 SD 驱动器时调用此函数。
//
// void MyOpenFunc (uint32_t 错误);
//
//
#define BL_open_fn_hook MyOpenFunc
//
//
//通知应用程序闪存进程已开始。
//
//如果已连接,则在加载程序启动固件时调用此函数
//闪存过程。
//
// void MyBeginFunc (uint32_t 错误);
//
//
#define BL_BEGIN_FN_Hook MyBeginFunc
//
//
//通知应用程序闪存进程已完成。
//
//如果挂钩,则在加载程序完成固件时调用此函数
//闪存过程。
//
// void MyEndFunc (uint32_t 错误);
//
//
#define BL_END_Hook MyEndFunc
//
//
//通知应用下载进度。
//
//如果已连接,则在固件期间将定期调用此函数
//下载。 应用程序可以使用此更新其用户界面。
//使用的协议不会将的最终大小通知客户端
//预先下载(例如 TFTP)、ulTotal 参数将为0、
//否则,它指示完整下载的预期大小。
//
//空 MyProgresFunc (unsigned long ulCompleded、unsigned long ulTotal);
//
//其中:
//
//-已完成表示已下载的字节数。
//- ulTotal 表示预期的字节数,如果不知道,则为0。
//
//
#define BL_Progress_fn_hook MyProgressFunc
//
//
//通知应用程序闪存进程正在退出引导加载程序。
//
//如果挂钩,则在加载程序完成固件时调用此函数
//闪存过程。
//
// void MyExitFunc (uint32_t 错误);
//
//
#define BL_EXIT_FN_Hook MyExitFunc
//
//
//定义要在 SD 驱动器上查找的应用程序 bin 映像文件名。
//引导加载程序将尝试装入并打开此文件十次。 如果
//成功,它会将文件的内容刷写到程序中
//内存空间。
//
//
#define BL_IMAGE_FILENAME "X24015.bin"
//
//
// X24015 SD 卡插槽 SPI 引脚分配
//
//.baseAddr = SSI1_base、// SPI 基址*/
//.portSCK = GPIO_PORTB_BASE、// SPI SCK 端口*/
//.pinSCK = GPIO_PIN_5、// SCK 引脚(PB5)*/
//.portMISO = GPIO_Porte _BASE、// SPI MISO 端口*/
//.pinMISO = GPIO_PIN_5、// MISO 引脚(PE5)*/
//.portMOSI = GPIO_Porte _BASE、// SPI MOSI 端口*/
//.pinMOSI = GPIO_PIN_4、// MOSI 引脚(PE4)*/
//.portCS = GPIO_PORTK_base、// GPIO CS 端口*/
//.pinCS = GPIO_PIN_7 // CS PIN (PK7)*/
//
//
// SD 驱动器使用的外设
#define SD_SYSCTL_PERIPH_SSI SYSCTL_PERIPH_SSI2
#define SD_SYSCTL_Periph_GPIO_SCLK SYSCTL_Periph_GPIOD // PD3 -- CLK
#define SD_SYSCTL_PERIPH_GPIO_MOSI SYSCTL_PERIPH_GPIOD // PD1 -- DAT0
#define SD_SYSCTL_PERIPH_GPIO_MISO SYSCTL_PERIPH_GPIOD // PD0 -- DAT1
#define sd_sysctl_Periph_GPIO_FSS SYSCTL_Periph_GPIOD // PD2 -- FSS
针对 SD SSI 的/*基本端口*/
#define SD_SSI_base SSI2_base
/* SD 驱动器 SCLK 端口/引脚定义*/
#define SD_GPIO_SCLK_base GPIO_PORTD_base
#define SD_GPIO_SCLK_PINCFG GPIO_PD3_SSI2CLK
#define SD_GPIO_SCLK_PIN GPIO_PIN_3
/* SD 驱动器 MOSI 端口/引脚定义*/
#define SD_GPIO_MOSI_BASE GPIO_PORTD_BASE
#define SD_GPIO_MOSI_PINCFG GPIO_PD1_SSI2XDAT0
#define SD_GPIO_MOSI_PIN GPIO_PIN_1
/* SD Drive MISO 端口/引脚定义*/
#define SD_GPIO_Miso_base GPIO_PORTD_base
#define SD_GPIO_MISO/PINCFG GPIO_PD0_SSI2XDAT1
#define SD_GPIO_MISO GPIO_PIN_0
/* SD 驱动器 FSS 端口/引脚定义*/
#define SD_GPIO_FFS_BASE GPIO_PORTD_BASE
#define SD_GPIO_FFS_PIN GPIO_PIN_2
//
// UART 可用于调试输出消息支持
//
//
//
//选择 UART 使用的波特率。
//
//取决于:UART_ENABLE_UPDATE、CRYSTRAL_FREQ
//不包括:UART_autobaud
//要求:无
//
//
#define UART_FIXED_BAUDRATE 115200
//
//
//选择 UART 外设模块的时钟启用
//
//取决于:UART_ENABLE_UPDATE
//不包括:无
//需要:UARTx_BASE
//
//
#define UART_CLOCK_ENABLE SYSCTL_RCGCUART_R0
//
//
//选择 UART 外设模块的基地址
//
//取决于:UART_ENABLE_UPDATE
//不包括:无
//需要:UART_CLOCK_ENABLE
//
//
#define UARTx_BASE UART0_BASE
//
//
//为对应于 UART RX 引脚的 GPIO 选择时钟启用
//
//取决于:UART_ENABLE_UPDATE
//不包括:无
//需要:UART_RXPIN_BASE、UART_RXPIN_PCTL 和 UART_RXPIN_POS
//
//
#define UART_RXPIN_CLOCK_ENABLE SYSCTL_RCGCGPIO_R0
//
//
//为对应于 UART RX 引脚的 GPIO 选择基地址
//
//取决于:UART_ENABLE_UPDATE
//不包括:无
//需要:UART_RXPIN_CLOCK_ENABLE、UART_RXPIN_PCTL 和 UART_RXPIN_POS
//
//
#define UART_RXPIN_BASE GPIO_PORta_base
//
//
//为对应于 UART RX 引脚的 GPIO 选择端口控制值
//
//取决于:UART_ENABLE_UPDATE
//不包括:无
//需要:UART_RXPIN_CLOCK_ENABLE、UART_RXPIN_BASE 和 UART_RXPIN_POS
//
//
#define UART_RXPIN_PCTL 0x1
//
//
//为对应于 UART RX 引脚的 GPIO 选择引脚编号
//
//取决于:UART_ENABLE_UPDATE
//不包括:无
//需要:UART_RXPIN_CLOCK_ENABLE、UART_RXPIN_BASE 和 UART_RXPIN_PCTL
//
//
#define UART_RXPIN_POS 0
//
//
//为对应于 UART TX 引脚的 GPIO 选择时钟启用
//
//取决于:UART_ENABLE_UPDATE
//不包括:无
//需要:UART_TXPIN_BASE、UART_TXPIN_PCTL 和 UART_TXPIN_POS
//
//
#define UART_TXPIN_CLOCK_ENABLE SYSCTL_RCGCGPIO_R0
//
//
//为对应于 UART TX 引脚的 GPIO 选择基地址
//
//取决于:UART_ENABLE_UPDATE
//不包括:无
//需要:UART_TXPIN_CLOCK_ENABLE、UART_TXPIN_PCTL 和 UART_TXPIN_POS
//
//
#define UART_TXPIN_BASE GPIO_PORta_base
//
//
//为对应于 UART TX 引脚的 GPIO 选择端口控制值
//
//取决于:UART_ENABLE_UPDATE
//不包括:无
//需要:UART_TXPIN_CLOCK_ENABLE、UART_TXPIN_BASE 和 UART_TXPIN_POS
//
//
#define UART_TXPIN_PCTL 0x1
//
//
//为与 UART TX 引脚相对应的 GPIO 选择引脚编号
//
//取决于:UART_ENABLE_UPDATE
//不包括:无
//需要:UART_TXPIN_CLOCK_ENABLE、UART_TXPIN_BASE 和 UART_TXPIN_PCTL
//
//
#define UART_TXPIN_POS 1.
#endif //__BL_CONFIG_H__
这是 需要由引导加载程序运行的主应用程序的.cmd 文件。
/*********
*
* enet_weather_ccs.cmd - enet_weather.的 CCS 链接器配置文件。
*
*版权所有(c) 2013-2017 Texas Instruments Incorporated。 保留所有权利。
*软件许可协议
*
*德州仪器(TI)提供此软件仅用于和
*专门用于 TI 的微控制器产品。 该软件归其所有
* TI 和/或其供应商、受适用版权保护
*法律。 您不能将此软件与"病毒"开源软件结合使用
*软件、以便形成更大的程序。
*
*此软件按"原样"提供、且存在所有缺陷。
*不作任何明示、默示或法定的保证、包括但
*不限于对适销性和适用性的暗示保证
*此软件有一个特殊用途。 TI 不得在任何情况下使用
*情况下、应对特殊、偶然或必然的情况负责
*任何原因造成的损失。
*
*这是 EK-TM4C1294XL 固件包版本2.1.4.178的一部分。
*
(小部分 /
--retain=g_pfnVectors
/*以下命令行选项作为 CCS 项目的一部分进行设置。 *
/*如果您使用命令行构建,或者出于某种原因想要*/
/*在此处定义它们,您可以根据需要取消注释并修改这些行。 *
/*如果您使用 CCS 进行构建、最好进行任何这样的构建*/
/*对 CCS 项目进行修改并将此文件保留为单独文件。 *
/**//
/*--heap_size=0 */
/*--stack_size=256 */
/*--library=rtsv7M3_T_le_eabi.lib */
/*应用程序的起始地址。 通常是中断矢量*/
/*必须位于应用程序的开头。 *
#define APP_BASE 0x00004000 // 0x00004000 [用于引导加载程序]//0x00000000 [用于正常]
#define RAM_base 0x20000000
/*系统内存映射*/
存储器
{
/*存储在内部闪存中并从内部闪存执行的应用程序*/
闪存(RX):origin = APP_BASE,length = 0x000FC000 // 0x000FC000[对于引导加载程序]// 0x00100000 [对于正常]
/*应用程序使用内部 RAM 进行数据*/
SRAM (rwx):origin = 0x20000000,length = 0x00040000
}
/*内存中的段分配*/
部分
{
.intvecs:> app_base
.text:> FLASH
.const:> FLASH
.cinit:>闪存
.pinit:> FLASH
init_array:> FLASH
.vtable:> RAM_base
.data :> SRAM
.bss:> SRAM
.sysmem:> SRAM
.stack:> SRAM
}
//__STACK_TOP =__STACK + 2048;原始
__STACK_TOP =__STACK + 2048;
SD 卡读取和 SD 卡中的数据也正常。
下面是我从串行端口获取的日志
fatfs.fsize 185360
WriteDataPacketCount 1448
WriteDataPacketRemainder 16.
................................................................................................................................ Done1.
Done2.
您好!
如果您查看引导加载程序启动文件 BL_STARTUP_CCS.s、它将在跳转到应用程序之前检查是否存在强制更新。 CheckForceUpdate 位于文件 BL_CHECK.c 中 它将检查 APP_START_ADDRESS = 0x4000的前两个位置是否全部为0xFFFFFFFF。 它将检查程序映像的 CRC 是否正确。 它将检查引脚是否强制执行引导加载。 如果其中任何一个为 true,则不会跳转到应用程序,而是跳转到更新程序。 因此、您需要检查您的案例中是否存在任何这些条件。
;
;
;复位处理程序,在处理器启动时调用。
;
;
.thumbfunc ResetISR
ResetISR:.asmfunc
;
;启用浮点单元。 如果有任何情况、必须在此处执行此操作
;;后面的 C 函数使用浮点。 请注意、有些工具链会
;;即使没有显式浮点、也可将 FPU 寄存器用于通用工作区
;点数据类型正在使用中。
;
movw r0、#0xED88
movt r0、#0xE000
LDR R1、[r0]
ORR R1、R1、#0x00F00000
STR R1、[r0]
;
;初始化处理器。
;
BL 处理器初始化
;
;;调用用户提供的低级硬件初始化函数
;如果提供。
;
.if $defined (BL_HW_INIT_FN_Hook)
.ref BL_HW_INIT_FN_HOOK
BL BL_HW_INIT_FN_HOOK
.endif
;
;查看是否应执行更新。
;
.ref CheckForceUpdate
BL CheckForceUpdate
CBZ r0、CallApplication
;
;;配置微控制器。
;
thumbfunc EnterBootLoader
EnterBootLoader:
.if $$defined (ENET_ENABLE_UPDATE)
.ref 配置环境
BL 配置 Enet
.elseif $$defined (CAN_ENABLE_UPDATE)
.ref 配置 CAN
BL 配置 CAN
.elseif $$defined (USB_ENABLE_UPDATE)
.ref 配置 USB
BL 配置 USB
其他
.ref 配置设备
BL 配置设备
.endif
;
;;调用用户提供的初始化函数(如果提供)。
;
.if $defined (bl_init_fn_hook)
.ref bl_init_fn_hook
BL BL_INIT_FN_HOOK
.endif
;
;;分支到更新处理程序。
;
.if $$defined (ENET_ENABLE_UPDATE)
.ref UpdateBOOTP
b 更新 BOOTP
.elseif $$defined (CAN_ENABLE_UPDATE)
.ref UpdateerCAN
b 更新 CAN
.elseif $$defined (USB_ENABLE_UPDATE)
.ref UpdateerUSB
B 更新程序 USB
其他
.ref 更新程序
b 更新程序
.endif
endasmfunc
uint32_t
CheckForceUpdate(void)
{
#ifdef CHECK_CRC
uint32_t ui32Retcode;
#endif
#ifdef BL_CHECK_UPDATE_FN_HOOK
//
// If the update check function is hooked, call the application to determine
// how to proceed.
//
return(BL_CHECK_UPDATE_FN_HOOK());
#else
uint32_t *pui32App;
#ifdef ENABLE_UPDATE_CHECK
g_ui32Forced = 0;
#endif
//
// See if the first location is 0xfffffffff or something that does not
// look like a stack pointer, or if the second location is 0xffffffff or
// something that does not look like a reset vector.
//
pui32App = (uint32_t *)APP_START_ADDRESS;
if((pui32App[0] == 0xffffffff) ||
((pui32App[0] & 0xfff00000) != 0x20000000) ||
(pui32App[1] == 0xffffffff) ||
((pui32App[1] & 0xfff00001) != 0x00000001))
{
return(1);
}
//
// If required, scan the image for an embedded CRC and ensure that it
// matches the current CRC of the image.
//
#ifdef CHECK_CRC
InitCRC32Table();
ui32Retcode = CheckImageCRC32(pui32App);
//
// If ENFORCE_CRC is defined, we only boot the image if the CRC is
// present in the image information header and the value calculated
// matches the value in the header. If ENFORCE_CRC is not defined, we
// the image if the CRC is good but also if the length field of the header
// is zero (which typically indicates that the post-build step of running
// binpack to add the length and CRC to the header was not run).
//
#ifdef ENFORCE_CRC
if(ui32Retcode != CHECK_CRC_OK)
#else
if((ui32Retcode != CHECK_CRC_OK) && (ui32Retcode != CHECK_CRC_NO_LENGTH))
#endif
{
//
// The CRC32 image check failed indicating that the image is
// corrupt (or doesn't have the CRC embedded correctly). Either way,
// fail the update check and force the boot loader to retain control.
//
return(2);
}
#endif
#ifdef ENABLE_UPDATE_CHECK
//
// If simple GPIO checking is configured, determine whether or not to force
// an update.
//
return(CheckGPIOForceUpdate());
#else
//
// GPIO checking is not required so, if we get here, a valid image exists
// and no update is needed.
//
return(0);
#endif
#endif
}您好 Charles,现在我无法从主应用程序跳转到引导加载程序。
我将使用以下函数。
空 JumpToBootLoader (空)
{
//
//禁用所有处理器中断。 而不是禁用它们
//一次一个,直接写入 NVIC 即可禁用所有功能
//外设中断。
//
HWREG (NVIC_DIS0)= 0xffffffff;
HWREG (NVIC_DIS1)= 0xffffffff;
//
//将控制权返回给引导加载程序。 这是对 SVC 的调用
//引导加载程序中的处理程序。
//
(*(void (*)(void))(*(uint32_t *) 0x2C))();
}
ROM_SysCtlPeripheralDisable (SYSCTL_Periph_SSI2);
ROM_SysCtlPeripheralReset (SYSCTL_Periph_SSI2);
ROM_SysCtlPeripheralDisable (SYSCTL_Periph_GPIOD);
ROM_SysCtlPeripheralReset (SYSCTL_Periph_GPIOD);
ROM_SysCtlPeripheralDisable (SYSCTL_Periph_GPIOD);
ROM_SysCtlPeripheralReset (SYSCTL_Periph_GPIOD);
ROM_SysCtlPeripheralDisable (SYSCTL_Periph_GPIOD);
ROM_SysCtlPeripheralReset (SYSCTL_Periph_GPIOD);
ROM_SysCtlPeripheralDisable (SYSCTL_Periph_GPIOD);
ROM_SysCtlPeripheralReset (SYSCTL_Periph_GPIOD);
HWREG (NVIC_DIS0)= 0xffffffff;
HWREG (NVIC_DIS1)= 0xffffffff;
HWREG (NVIC_DIS2)= 0xffffffff;
HWREG (NVIC_DIS3)= 0xffffffff;
HWREG (NVIC_DIS4)= 0xffffffff;
//也禁用 SysTick 中断。
ROM_SysTickIntDisable();
ROM_SysTickDisable();
(*(void (*)(void))(*(uint32_t *) 0x2C))();
您好!
不确定发生了什么。 您如何知道它在执行 (*(void (*)(void)(*(void))(*(uint32_t *) 0x2C)))之后没有跳转到引导加载程序?(
如果您查看 BL_STARTUP_CCS.s、对于 SVC 调用、处理器应该跳转到0x2C。 如您所见,它将跳转到 UpdateHandler 处的向量。
.word 0 ;; Offset 24: Reserved
.word 0 ;; Offset 28: Reserved
.word UpdateHandler - 0x20000000 ;; Offset 2C: SVCall handler
.word IntDefaultHandler ;; Offset 30: Debug monitor handler
UpdateHandler: .asmfunc
;;
;; Initialize the processor.
;;
bl ProcessorInit
;;
;; Load the stack pointer from the vector table.
;;
movs r0, #0x0000
ldr sp, [r0]
;;
;; Call the user-supplied low level hardware initialization function
;; if provided.
;;
.if $$defined(BL_HW_INIT_FN_HOOK)
bl BL_HW_INIT_FN_HOOK
.endif
;;
;; Call the user-supplied re-initialization function if provided.
;;
.if $$defined(BL_REINIT_FN_HOOK)
.ref BL_REINIT_FN_HOOK
bl BL_REINIT_FN_HOOK
.endif
;;
;; Branch to the update handler.
;;
.if $$defined(ENET_ENABLE_UPDATE)
b UpdateBOOTP
.elseif $$defined(CAN_ENABLE_UPDATE)
.ref AppUpdaterCAN
b AppUpdaterCAN
.elseif $$defined(USB_ENABLE_UPDATE)
.ref AppUpdaterUSB
b AppUpdaterUSB
.else
b Updater
.endif
.endasmfunc