Hercules TMS570LC43x LaunchPad SylixOS移植记录
Hercules TMS570LC43x LaunchPad是TI官方出的TMS570LC43x芯片DEMO板:
http://www.ti.com/tool/launchxl2-570lc43
TMS570LC43x使用ARM Cortex-R5核心,主频300MHz,
有MPU、CACHE、FPU,没有MMU,Flash有4MB,RAM只有512KB,近日成功跑起SylixOS,记录一下移植过程以备忘。
硬件连接
使用一USB转TTL模块连接LaunchPad有SCI3,如下图:
sylixos-base裁减
目前只编译libsylixos,sylixos-base的makefile如下:COMPONENTS = \
libsylixos \
all: $(COMPONENTS)
@for target in $(COMPONENTS); do make -C $$target all -j 16; done
clean: $(COMPONENTS)
@for target in $(COMPONENTS); do make -C $$target clean; done
libsylixos裁减
libsylixos也需要裁减,libsylixos的makefile,修改BUILD_LITE_TARGET变量值为1,即编译lite版本:BUILD_LITE_TARGET = 1
libsylixos下的libsylixos.mk,去掉:SylixOS/fs/mtd/mtdcore.c \
SylixOS/fs/mtd/linux/bch.c \
SylixOS/fs/mtd/linux/strim.c \
SylixOS/fs/mtd/nand/nand_base.c \
SylixOS/fs/mtd/nand/nand_bbt.c \
SylixOS/fs/mtd/nand/nand_bch.c \
SylixOS/fs/mtd/nand/nand_ecc.c \
SylixOS/fs/mtd/nand/nand_ids.c \
SylixOS/fs/mtd/onenand/onenand_base.c \
SylixOS/fs/mtd/onenand/onenand_bbt.c \
SylixOS/fs/yaffs2/yaffs_allocator.c \ |
同时将:NET_SRCS = \
修改为:NO_NET_SRCS = \
即不编译mtd、yaffs2、net。
libsylixos配置
修改的配置项目比较多,这里只罗列重要的几个,如下:
SylixOS\config\cpu\cpu_cfg_arm.h:#define LW_CFG_ARM_PL330 0 /* 是否允许 PL330 DMA 驱动 */
#define LW_CFG_ARM_CACHE_L2 0 /* 是否允许管理 ARM 二级 CACHE */
#define LW_CFG_ARM_CACHE_L2_ECC 0 /* 是否打开 ARM 二级 CACHE ECC */
SylixOS\config\kernel\vmm_cfg.h:#define LW_CFG_VMM_EN 0 /* 是否需要对虚拟内存的支持 */
SylixOS\config\mp\mp_cfg.h:#define LW_CFG_SMP_EN 0 /* 是否需要系统对多处理器支持 */
HALCoGen使用
使用HALCoGen新建一个工程:
CPU按图选择,TOOLS 使用 GCC:
使能 GIO、SCI3、RTI驱动:
配置SCI3的管脚复用:
配置SCI3的波特率为115200:
配置SCI3的PORT:
配置异常向量表:
配置各处理器模式的堆栈空间大小:
配置GIO PORTB BIT6为输出:
BSP编写
创建 bsp,模板使用arm-none,名字为bsparmr5。
将 HALCoGen 生成的代码放到 SylixOS/driver/HCG 目录。
将 config.ld 的内容清空,因为链接脚本不需要配置了。
将 SylixOS/bsp/symbol.c 排除到工程外。
将 SylixOS/bsp/bspMap.h 删除,同时 bspInit.c 不再 include 该头文件。
修改 SylixOS/driver/HCG/source/HL_sys_startup.c:/* USER CODE BEGIN (26) */
extern int bspInit(void);
bspInit();
/* USER CODE END */
修改 SylixOS/driver/HCG/source/HLsys_core.s文件的_coreInitStackPointer函数,返回前通过cps #19进入SVC模式:_coreInitStackPointer_:
cps #17
ldr sp, fiqSp
cps #18
ldr sp, irqSp
cps #19
ldr sp, svcSp
cps #23
ldr sp, abortSp
cps #27
ldr sp, undefSp
cps #31
ldr sp, userSp
cps #19
bx lr
链接脚本 SylixOSBSP.ld
使用 SylixOS/driver/HCG/source/HL_sys_link.ld 的内容,加入:
PROVIDE ( end = _ebss ); |
config.h
内容如下,需要根据芯片的 Flash 和 RAM 的地址、容量来修改:
#define BSP_CFG_ROM_BASE (0x00000000) |
bsparmr5.mk
关键变量如下:
LOCAL_INC_PATH := \ |
LOCAL_DSYMBOL := \ |
加入SylixOS/driver/HCG/source/HL_sys_core.s的编译,它需要使用浮点才能编译通过:
ARM_FPU_ASFLAGS = -mfloat-abi=softfp -mfpu=vfpv3 |
bspInit.c关键内容
cortex-r5 同样支持 WFI 指令:static VOID halIdleInit (VOID)
{
API_SystemHookAdd(armWaitForInterrupt,
LW_OPTION_THREAD_IDLE_HOOK); /* 空闲时暂停 CPU */
}
CACHE 初始化:static VOID halCacheInit (VOID)
{
API_CacheLibInit(CACHE_COPYBACK, CACHE_COPYBACK, ARM_MACHINE_R5); /* 初始化 CACHE 系统 */
API_CacheEnable(INSTRUCTION_CACHE);
API_CacheEnable(DATA_CACHE); /* 使能 CACHE */
}
FPU 初始化(使用 VFPv3-d16):static VOID halFpuInit (VOID)
{
API_KernelFpuInit(ARM_MACHINE_R5, ARM_FPU_VFPv3);
}
没有硬盘,使用 ramfs:static VOID halStdDirInit (VOID)
{
/*
* 没有硬盘,使用 ramfs,并链接到根文件系统的目录
*/
system("mount -t ramfs 0 /ram");
mkdir("/ram/boot", DEFAULT_DIR_PERM);
mkdir("/ram/etc", DEFAULT_DIR_PERM);
mkdir("/ram/ftk", DEFAULT_DIR_PERM);
mkdir("/ram/qt", DEFAULT_DIR_PERM);
mkdir("/ram/lib", DEFAULT_DIR_PERM);
mkdir("/ram/lib/modules", DEFAULT_DIR_PERM);
mkdir("/ram/usr", DEFAULT_DIR_PERM);
mkdir("/ram/usr/lib", DEFAULT_DIR_PERM);
mkdir("/ram/bin", DEFAULT_DIR_PERM);
mkdir("/ram/sbin", DEFAULT_DIR_PERM);
mkdir("/ram/apps", DEFAULT_DIR_PERM);
mkdir("/ram/home", DEFAULT_DIR_PERM);
mkdir("/ram/root", DEFAULT_DIR_PERM);
mkdir("/ram/var", DEFAULT_DIR_PERM);
mkdir("/ram/tmp", DEFAULT_DIR_PERM);
symlink("/ram/boot", "/boot");
symlink("/ram/etc", "/etc");
symlink("/ram/ftk", "/ftk");
symlink("/ram/qt", "/qt");
symlink("/ram/lib", "/lib");
symlink("/ram/usr", "/usr");
symlink("/ram/bin", "/bin");
symlink("/ram/sbin", "/sbin");
symlink("/ram/apps", "/apps");
symlink("/ram/home", "/home");
symlink("/ram/root", "/root");
symlink("/ram/var", "/var");
symlink("/ram/tmp", "/var/tmp");
symlink("/ram/tmp", "/tmp");
}
调试通道使用 SCI3,故 bspInit 函数加入:
sciInit(); |
同时 hz 修改为 1000:
API_KernelStartParam("kdlog=no kderror=yes kfpu=no heapchk=yes hz=1000 hhz=1000"); |
bspLib.c 关键内容
中断初始化:
VOID bspIntInit (VOID) |
中断处理(暂时只支持定时器中断):VOID bspIntHandle (VOID)
{
REGISTER UINT32 uiVector = 2;
archIntHandle((ULONG)uiVector, LW_FALSE);
}
开关中断:
VOID bspIntVectorEnable (ULONG ulVector) |
处理器特性:ULONG bspInfoHwcap (VOID)
{
return (HWCAP_VFP | HWCAP_VFPv3 | HWCAP_VFPv3D16);
}
调试信息输出:VOID bspDebugMsg (CPCHAR pcMsg)
{
if (!pcMsg) { /* 指针为空 */
return;
}
while (*pcMsg != '\0') { /* 发送字符串 */
sciSendByte(sciREG3, *pcMsg);
pcMsg++;
}
}
定时器相关函数:static irqreturn_t __tickTimerIsr (VOID)
{
portRTI_INTFLAG_REG = 1;
API_KernelTicksContext(); /* 保存被时钟中断的线程控制块 */
#if TICK_IN_THREAD > 0
API_ThreadResume(htKernelTicks);
#else
API_KernelTicks(); /* 内核 TICKS 通知 */
API_TimerHTicks(); /* 高速 TIMER TICKS 通知 */
#endif /* TICK_IN_THREAD > 0 */
return (LW_IRQ_HANDLED);
}
static void prvSetupTimerInterrupt(void)
{
/* Disable timer 0. */
portRTI_GCTRL_REG &= 0xFFFFFFFEUL;
/* Use the internal counter. */
portRTI_TBCTRL_REG = 0x00000000U;
/* COMPSEL0 will use the RTIFRC0 counter. */
portRTI_COMPCTRL_REG = 0x00000000U;
/* Initialise the counter and the prescale counter registers. */
portRTI_CNT0_UC0_REG = 0x00000000U;
portRTI_CNT0_FRC0_REG = 0x00000000U;
/* Set Prescalar for RTI clock. */
portRTI_CNT0_CPUC0_REG = 0x00000001U;
portRTI_CNT0_COMP0_REG = ( configCPU_CLOCK_HZ / 2 ) / LW_TICK_HZ;
portRTI_CNT0_UDCP0_REG = ( configCPU_CLOCK_HZ / 2 ) / LW_TICK_HZ;
/* Clear interrupts. */
portRTI_INTFLAG_REG = 0x0007000FU;
portRTI_CLEARINTENA_REG = 0x00070F0FU;
/* Enable the compare 0 interrupt. */
portRTI_SETINTENA_REG = 0x00000001U;
portRTI_GCTRL_REG |= 0x00000001U;
}
VOID bspTickInit (VOID)
{
#if TICK_IN_THREAD > 0
LW_CLASS_THREADATTR threadattr;
#endif /* TICK_IN_THREAD > 0 */
ULONG ulVector = 2;
#if TICK_IN_THREAD > 0
API_ThreadAttrBuild(&threadattr, (8 * LW_CFG_KB_SIZE),
LW_PRIO_T_TICK,
LW_OPTION_THREAD_STK_CHK |
LW_OPTION_THREAD_UNSELECT |
LW_OPTION_OBJECT_GLOBAL |
LW_OPTION_THREAD_SAFE, LW_NULL);
htKernelTicks = API_ThreadCreate("t_tick",
(PTHREAD_START_ROUTINE)__tickThread,
&threadattr,
NULL);
#endif /* TICK_IN_THREAD > 0 */
prvSetupTimerInterrupt();
API_InterVectorConnect(ulVector,
(PINT_SVR_ROUTINE)__tickTimerIsr,
LW_NULL,
"tick_timer");
API_InterVectorEnable(ulVector);
}
CCS调试
新建一CCS工程:
新建它的调试配置:
配置程序:
配置调试开始函数:
配置文件查找路径:
最后可以把这个调试配置复制一份,调试时只需要加载符号,但不下载,用于快速重启调试:
但需要多选择连接时复位: