文章目录
  1. 1. 硬件连接
  2. 2. sylixos-base裁减
  3. 3. libsylixos裁减
  4. 4. libsylixos配置
  5. 5. HALCoGen使用
  6. 6. BSP编写
    1. 6.1. 链接脚本 SylixOSBSP.ld
    2. 6.2. config.h
    3. 6.3. bsparmr5.mk
    4. 6.4. bspInit.c关键内容
    5. 6.5. bspLib.c 关键内容
  7. 7. CCS调试
  8. 8. 晒图

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,如下图:
Image 22.png

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 \
SylixOS/fs/yaffs2/yaffs_attribs.c \
SylixOS/fs/yaffs2/yaffs_bitmap.c \
SylixOS/fs/yaffs2/yaffs_checkptrw.c \
SylixOS/fs/yaffs2/yaffs_ecc.c \
SylixOS/fs/yaffs2/yaffs_guts.c \
SylixOS/fs/yaffs2/yaffs_mtdif_multi.c \
SylixOS/fs/yaffs2/yaffs_nameval.c \
SylixOS/fs/yaffs2/yaffs_nand.c \
SylixOS/fs/yaffs2/yaffs_nor.c \
SylixOS/fs/yaffs2/yaffs_packedtags1.c \
SylixOS/fs/yaffs2/yaffs_packedtags2.c \
SylixOS/fs/yaffs2/yaffs_summary.c \
SylixOS/fs/yaffs2/yaffs_sylixos.c \
SylixOS/fs/yaffs2/yaffs_sylixosproc.c \
SylixOS/fs/yaffs2/yaffs_tagscompat.c \
SylixOS/fs/yaffs2/yaffs_tagsmarshall.c \
SylixOS/fs/yaffs2/yaffs_verify.c \
SylixOS/fs/yaffs2/yaffs_yaffs1.c \
SylixOS/fs/yaffs2/yaffs_yaffs2.c \
SylixOS/fs/yaffs2/direct/yaffscfg.c \
SylixOS/fs/yaffs2/direct/yaffsfs.c \
SylixOS/fs/yaffs2/direct/yaffs_hweight.c \
SylixOS/fs/yaffs2/direct/yaffs_qsort.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:
Image 3.png

使能 GIO、SCI3、RTI驱动:
Image 4.png

配置SCI3的管脚复用:
Image 5.png

配置SCI3的波特率为115200:
Image 6.png

配置SCI3的PORT:
Image 7.png

配置异常向量表:
Image 8.png

配置各处理器模式的堆栈空间大小:
Image 9.png

配置GIO PORTB BIT6为输出:
Image 10.png

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 );
PROVIDE ( _end = _ebss );

/*********************************************************************************************************
内核堆段
*********************************************************************************************************/

.heap (NOLOAD) : {
. = ALIGN(8);
PROVIDE (__heap_start = .);

__heap_end = ORIGIN(RAM) + LENGTH(RAM) - 128;
PROVIDE (__heap_end = .);
} > RAM

config.h

内容如下,需要根据芯片的 Flash 和 RAM 的地址、容量来修改:

#define BSP_CFG_ROM_BASE (0x00000000)
#define BSP_CFG_ROM_SIZE (4 * 1024 * 1024)

#define BSP_CFG_RAM_BASE (0x08000000)
#define BSP_CFG_RAM_SIZE (512 * 1024)

bsparmr5.mk

关键变量如下:

LOCAL_INC_PATH :=  \
-I"./SylixOS" \
-I"./SylixOS/bsp" \
-I"$(WORKSPACE_bsparmr5)/SylixOS\driver\HCG\include"

LOCAL_DSYMBOL :=  \
-D__BOOT_INROM=1 \
-D__SYLIXOS_LITE=1

加入SylixOS/driver/HCG/source/HL_sys_core.s的编译,它需要使用浮点才能编译通过:

ARM_FPU_ASFLAGS = -mfloat-abi=softfp -mfpu=vfpv3

$(OBJPATH)/$(LOCAL_TARGET_NAME)/SylixOS/driver/HCG/source/HL_sys_core.o: ./SylixOS/driver/HCG/source/HL_sys_core.s
@if [ ! -d "$(dir $@)" ]; then \
mkdir -p "$(dir $@)"; fi
@if [ ! -d "$(dir $(__DEP))" ]; then \
mkdir -p "$(dir $(__DEP))"; fi
$(AS) $(ARM_FPU_ASFLAGS) $($(__TARGET)_ASFLAGS_WITHOUT_FPUFLAGS) -MMD -MP -MF $(__DEP) -c $< -o $@

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)
{
vimInit();
}

中断处理(暂时只支持定时器中断):

VOID  bspIntHandle (VOID)
{
REGISTER UINT32 uiVector = 2;

archIntHandle((ULONG)uiVector, LW_FALSE);
}

开关中断:

VOID  bspIntVectorEnable (ULONG  ulVector)
{
vimChannelMap(ulVector, ulVector, archIntEntry);
vimEnableInterrupt(ulVector, SYS_IRQ);
}


VOID bspIntVectorDisable (ULONG ulVector)
{
vimDisableInterrupt(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工程:
Image 11.png

新建它的调试配置:

配置程序:
Image 12.png

配置调试开始函数:
Image 13.png

配置文件查找路径:
Image 14.png

最后可以把这个调试配置复制一份,调试时只需要加载符号,但不下载,用于快速重启调试:
Image 16.png

但需要多选择连接时复位:
Image 17.png

晒图

Image 19.png
Image 20.png

文章目录
  1. 1. 硬件连接
  2. 2. sylixos-base裁减
  3. 3. libsylixos裁减
  4. 4. libsylixos配置
  5. 5. HALCoGen使用
  6. 6. BSP编写
    1. 6.1. 链接脚本 SylixOSBSP.ld
    2. 6.2. config.h
    3. 6.3. bsparmr5.mk
    4. 6.4. bspInit.c关键内容
    5. 6.5. bspLib.c 关键内容
  7. 7. CCS调试
  8. 8. 晒图