Red · 2022年08月22日 · 江苏

【MM32F5270开发板试用】一、移植 TencentOS 到 PLUS-F5270

【MM32F5270开发板试用】一、移植 TencentOS 到 PLUS-F5270

感谢有这次机会试用 PLUS-F5270 开发板,我计划在使用这个开发板实现一个 SmartSensor 项目,这个项目我放在了仓库 SmartSensor。会逐渐记录开发的进度。
本篇会分为两个部分:

  1. 修改 openocd 支持链接 STAR-MC1 处理器,并提交了一个 pr 已经 merge target/arm: Add support with identify STAR-MC1,在此基础上使用 stm32f1x 的 flash 驱动目前可以烧录程序到芯片的内置 flash
  2. 移植 TOS 到 PLUS-F5270

在 Linux 使用 openocd 链接 PLUS-F5270

如果需要使用 openocd 链接 STAR-MC1,需要打上这个 pr

diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c
index aeaeb1829..1bb37797a 100644
--- a/src/target/cortex_m.c
+++ b/src/target/cortex_m.c
@@ -91,6 +91,12 @@ static const struct cortex_m_part_info cortex_m_parts[] = {
         .arch = ARM_ARCH_V8M,
         .flags = CORTEX_M_F_HAS_FPV5,
     },
+    {
+        .partno = START_MC1_PARTNO,
+        .name = "START-MC1",
+        .arch = ARM_ARCH_V8M,
+        .flags = CORTEX_M_F_HAS_FPV5,
+    },
     {
         .partno = CORTEX_M35P_PARTNO,
         .name = "Cortex-M35P",
diff --git a/src/target/cortex_m.h b/src/target/cortex_m.h
index 69368a919..89dfd6669 100644
--- a/src/target/cortex_m.h
+++ b/src/target/cortex_m.h
@@ -44,6 +44,7 @@ enum cortex_m_partno {
     CORTEX_M0P_PARTNO  = 0xC60,
     CORTEX_M23_PARTNO  = 0xD20,
     CORTEX_M33_PARTNO  = 0xD21,
+    START_MC1_PARTNO   = 0x132,
     CORTEX_M35P_PARTNO = 0xD31,
     CORTEX_M55_PARTNO  = 0xD22,
 };

如果还要通过 openocd 下载程序到 flash, 还需要再打下 patch:

diff --git a/src/flash/nor/stm32f1x.c b/src/flash/nor/stm32f1x.c
index 455a06a9b..8721c1278 100644
--- a/src/flash/nor/stm32f1x.c
+++ b/src/flash/nor/stm32f1x.c
@@ -761,6 +761,7 @@ static int stm32x_get_property_addr(struct target *target, struct stm32x_propert
         addr->flash_size = 0x1FFFF7E0;
         return ERROR_OK;
     case CORTEX_M_PARTNO_INVALID:
+    case START_MC1_PARTNO:
         /* Check for GD32VF103 with RISC-V CPU */
         if (strcmp(target_type_name(target), "riscv") == 0
                 && target_address_bits(target) == 32) {
@@ -771,6 +772,12 @@ static int stm32x_get_property_addr(struct target *target, struct stm32x_propert
             addr->flash_size = 0x1FFFF7E0;
             return ERROR_OK;
         }
+        else
+        {
+            addr->device_id = 0x40007080;
+            addr->flash_size = 0x1FFFE920;
+            return ERROR_OK;
+        }
         /* fallthrough */
     default:
         LOG_ERROR("Cannot identify target as a stm32x");
@@ -869,6 +876,7 @@ static int stm32x_probe(struct flash_bank *bank)
         stm32x_info->can_load_options = true;
         break;
     case 0x410: /* stm32f1x medium-density */
+    case 0x800: /* mm32f527x medium-density */
         page_size = 1024;
         stm32x_info->ppage_size = 4;
         max_flash_size_in_kb = 128;
@@ -882,6 +890,7 @@ static int stm32x_probe(struct flash_bank *bank)
            because of unexpected active hardware watchog. */
         switch (rev_id) {
         case 0x1303: /* gd32f1x0 */
+        case 0x4d4d: /* mm32f527x */
             stm32x_info->user_data_offset = 16;
             stm32x_info->option_offset = 6;
             max_flash_size_in_kb = 64;

还有两个 cfg 配置文件板级的 mmplus.cfg:

#adapter list

source [find interface/jlink.cfg]

transport select swd

adapter speed 100

#jink config

source [find mm32f5270.cfg]

proc mmd { pos } {
    if { $pos == 0 } {
        reset;
        halt;
        flash write_image erase TencentOS_tiny.bin 0x8000000;
        reset;
        echo "mmd down firm 2 internal flash success"
    } else {
        echo "mmd down firm 2 spi flash"
    }
}

和平台级的 mm32f5270.cfg:

source [find target/swj-dp.tcl]
#source [find mem_helper.tcl]

if { [info exists CHIPNAME] } {
set _CHIPNAME $CHIPNAME
} else {
set _CHIPNAME mm32f5270
}

set FLASH_SIZE 0x40000

# Allow overriding the Flash bank size
if { [info exists FLASH_SIZE] } {
    set _FLASH_SIZE $FLASH_SIZE
} else {
    # autodetect size
    set _FLASH_SIZE 0
}

# ONLY use ENDIAN with targets that can change it.
if { [info exists ENDIAN] } {
set _ENDIAN $ENDIAN
} else {
set _ENDIAN little
}

if { [info exists CPUTAPID ] } {
set _CPUTAPID $CPUTAPID
} else {
#set _CPUTAPID 0x1be12aeb
set _CPUTAPID 0x1aeb0015
}

set _TARGETNAME $_CHIPNAME.cpu

#swj_newdap $_CHIPNAME cpu -irlen 5 -ircapture 0x1 -irmask 0xf -ignore-version -expected-id $_CPUTAPID
swj_newdap $_CHIPNAME cpu -irlen 5 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID
dap create $_CHIPNAME.dap -chain-position $_TARGETNAME
target create $_TARGETNAME cortex_m -dap $_CHIPNAME.dap -ap-num 0

# 定义一块内存区域用来烧录程序到 flash 临时使用
# 定义一块内存区域的起始地址,在 MMU 未开启时使用
$_TARGETNAME configure -work-area-phys 0x30000000 -work-area-size 0x4000

set _FLASHNAME $_CHIPNAME.flash
flash bank $_FLASHNAME stm32f1x 0x08000000 $_FLASH_SIZE 0 0 $_TARGETNAME
#flash bank $_FLASHNAME mm32f527x 0x08000000 $_FLASH_SIZE 0 0 $_TARGETNAME

proc mm32f5270_reset_init {} {
    # 配置 PLL 时钟
    # mww
}

$_TARGETNAME configure -event reset-init { mm32f5270_reset_init }

cortex_m reset_config sysresetreq

#$CHIPNAME init

至此就可以正常连接 STAR-MC1 了

移植 TOS 到 PLUS-F5270

花费了好几天的时间完成了 TOS 在 PLUS-F5270 上的部署,移植过程中发现在执行到函数port_sched_startLDMFD SP!, {R4 - R11} 这句话的时候就会进入到 HardFault.经过多番排查,定位到是 ARMv8-M 指令集的 stack limit 功能导致的。该功能具体描述是:

官方的代码在 Reset_Handler 中赋值了 msplim 和 psplim 寄存器,所以在线程调度的时候,当使用线程栈指针时,超过了 stack limit 导致系统异常。其中 psplim 是检查 thread mode 的栈指针即 psp,msplim 检查的是 handler mode 的栈指针即 msp。特别地,在异常(handler mode)中一直使用的是 msp,异常一般被当作内核态,在 thread mode 时候,会根据 CONTROL.nPRIV determines whether execution in Thread mode is unprivileged 确定使用的是特权还是非特权。特权使用的是 msp, 非特权则是 psp 指针。

ldr      r0, =__STACK_LIMIT
msr      msplim, r0
msr      psplim, r0

为了避免这个问题可以有多种方案:

  1. 关闭 stack limit 检查,CCR, Configuration and Control Register 寄存器的 bit 10

    修改该 bit 位为 1
  2. 在线程调度过程中更新 psplim,目前我看 RT-Thread 使用的是这种方法,但是这个 psplim 实际一直是 0(所以也可以认为并没有使用硬件进行 stack limit 检查).
  3. 直接设置 msplim 和 psplim 为 0

解决这个问题后,就可以正常运行 TOS 了。有关这部分移植工作,我提交了一个 pr Add support with PLUS-F5270 Board #351 ,目前也已经 merge.

推荐阅读
关注数
6151
内容数
276
灵动MM32 MCU相关技术知识,欢迎关注~
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息