基于IAR for RH850的瑞萨RH850 FCL库用法介绍

博主联系方式:QQ:1256153255 ,email:1256153255@qq.com

website for get 瑞萨RH850F1x开发板和瑞萨E1仿真器

1、简介

本文介绍了RH850 FCL的使用以及相关的经验技巧,使用的环境如下
MCU:瑞萨RH850F1K
型号:R7F701557
在这里插入图片描述
编译器:IAR for RH850
在这里插入图片描述
编译器版本:IAR Embeded Workbench for Renesas RH850 V2.10.1
IAR Embeded Workbench shared components V8.1.1.5550
在这里插入图片描述
仿真器:瑞萨E1仿真器

Flash烧录软件:Renesas Flash Programmer V3.08
在这里插入图片描述
FCL库版本:RENESAS_FCL_RH850_T01_V2.13

瑞萨的资料本身就少,而有讲解FCL的文章更是少之又少,搜索了FCL的资料,找来找去也就那几篇介绍的,而且大家用的还是瑞萨自己的CS+编译器,用的MCU系列也不是F1K的,所以看了很多遍都无济于事。
介于以上,自己就根据FCL库的官方介绍文档(RH850 Family Code Flash Library)一点点的摸索,这篇文档前后看了不下5遍,最终还是成功地将FCL移植到自己的开发板上了。

2、R7F701557资源介绍

既然在移植中使用的开发板芯片时R7F701557,那么就必须对R7F701557的片上资源(主要时ROM和RAM)有个明确的了解,查询芯片的用户手册得到
在这里插入图片描述
也就是说R7F701557的ROM:1MBytes RAM:64KBytes,地址范围分别如下。
在这里插入图片描述在这里插入图片描述

3、Section配置

有前辈在blog中这样写到Section的配置
在这里插入图片描述
在这里插入图片描述
这样的配置方法都是在CS+中操作的,那么我用的IAR是否已经将这些Section配置好了?如果配置好了,那么在那里配置的?如果没有配置好,那么怎么配置?

首先从.map文件入手,看看是否已经有这些section了,查找之后确实有

File name:*.map
"ROM1ST", part 1 of 2:                          0x2ba2
  FCL_LIBRARY                            0x1f8  0x28b0  <Block>
    R_FCL_CODE_ROM                       0x1f8   0x2c4  <Block>
      R_FCL_CODE_ROM      ro code        0x1f8   0x228  r_fcl_user_if.o [1]
      R_FCL_CODE_ROM      ro code        0x420    0x9c  r_fcl_hw_access_asm.o [1]
    R_FCL_CODE_USRINT                    0x4bc     0x0  <Block>
      R_FCL_CODE_USRINT   ro code        0x4bc     0x0  r_fcl_hw_access_asm.o [1]
    R_FCL_CODE_USR                       0x4bc   0x1e0  <Block>
      R_FCL_CODE_USR      ro code        0x4bc   0x15a  fcl_ctrl.o [1]
      R_FCL_CODE_USR      ro code        0x618    0x84  fcl_user.o [1]
      R_FCL_CODE_USR      ro code        0x69c     0x0  r_fcl_hw_access_asm.o [1]
    R_FCL_CODE_RAM                       0x69c  0x1508  <Block>
      R_FCL_CODE_RAM      ro code        0x69c  0x13ac  r_fcl_hw_access.o [1]
      R_FCL_CODE_RAM      ro code       0x1a48    0x98  r_fcl_hw_access_asm.o [1]
      R_FCL_CODE_RAM      ro code       0x1ae0    0xc4  r_fcl_user_if.o [1]
    R_FCL_CODE_ROMRAM                   0x1ba4   0xeb4  <Block>
      R_FCL_CODE_ROMRAM   ro code       0x1ba4   0xb9a  r_fcl_hw_access.o [1]
      R_FCL_CODE_ROMRAM   ro code       0x2740   0x318  r_fcl_user_if.o [1]
      R_FCL_CODE_ROMRAM   ro code       0x2a58     0x0  r_fcl_hw_access_asm.o [1]
    R_FCL_CODE_RAM_EX_PROT
                                        0x2a58    0x50  <Block>
      R_FCL_CODE_RAM_EX_PROT
File name:*.map
"LOC1ST":                                       0x8000
  FCL_RAM_BLOCK_FCL_RESERVED
                                   0xfebe'0000  0x8000  <Block>
    FCL_RESERVED          uninit   0xfebe'0000  0x8000  main.o [1]
                                 - 0xfebe'8000  0x8000

"RAM1ST":                                         0x80
  FCL_RAM_BLOCK_R_FCL_DATA
                                   0xfede'8000    0x80  <Block>
    R_FCL_DATA            uninit   0xfede'8000    0x80  r_fcl_user_if.o [1]
                                 - 0xfede'8080    0x80

既然有这些section,那么是在哪里定义的呢?请看这两份文件layout.icf和lnkr7f701557.icf,这可是工程自带的,这两个文件里边应该是有猫腻的。关于.icf文件有看不懂的童鞋,请自行百度,此处不详述。
在layout.icf中有这样两段定义

File name:layout.icf
define block FCL_RAM_BLOCK_FCL_RESERVED with fixed order, alignment=4 { rw section FCL_RESERVED };
define block FCL_RAM_BLOCK_R_FCL_DATA with fixed order, alignment=4 { rw data section R_FCL_DATA };


keep { section FCL_RESERVED };

define block R_FCL_CODE_ROM with alignment=4 {ro code section R_FCL_CODE_ROM};
define block R_FCL_CODE_USRINT with alignment=4 {ro code section R_FCL_CODE_USRINT};
define block R_FCL_CODE_USR with alignment=4 {ro code section R_FCL_CODE_USR};
define block R_FCL_CODE_RAM with alignment=4 {ro code section R_FCL_CODE_RAM};
define block R_FCL_CODE_ROMRAM with alignment=4 {ro code section R_FCL_CODE_ROMRAM};
define block R_FCL_CODE_RAM_EX_PROT with alignment=4 {ro code section R_FCL_CODE_RAM_EX_PROT};

define block FCL_LIBRARY with fixed order, alignment=4  { ro section R_FCL_CONST,
                                                         block R_FCL_CODE_ROM,
                                                         block R_FCL_CODE_USRINT,
                                                         block R_FCL_CODE_USR,
                                                         block R_FCL_CODE_RAM,
                                                         block R_FCL_CODE_ROMRAM,
                                                         block R_FCL_CODE_RAM_EX_PROT
                                                        };

既然有了section的定义,那么每个section分配的地址空间又是在哪儿定义的?继续找,找到这里

File name:layout.icf
"ROM1ST":place in ROM_1ST_region
{ 
  block CALLT,
  block TRAP,
  block FETRAP,
  block HVTRAP,
  ro,
  block FCL_LIBRARY,
  block .syscalltable,
  block .hvcalltable,
  block ROM_BLOCK
};
尤其要注意这里的FCL_LIBRARY

也就是说,那些R_FCL_CODE_*的block都是属于FCL_LIBRARY这个大的block,而FCL_LIBRARY这个block属于ROM1ST,而ROM1ST又是place in ROM_1ST_region。那么ROM_1ST_region在哪儿定义的?继续找,发现layout.icf中没有了,那就去lnkr7f701557.icf中找找看,结果还真找到了

File name:lnkrr7f701557.icf
define region ROM_1ST_region = mem:[from 0x00000000 to 0x000FFFFF];      // <code default>  Code FLASH

至此也就明白了,FCL_LIBRARY下的block是在哪儿定义的,以及是在哪儿分配的地址空间。

OK,找完了ROM的section,还有两个在RAM中的section(R_FCL_DATA和FCL_RESERVED)也是同样的方法找

File name:layout.icf
"LOC1ST":place at start of LOC_1ST_region { block FCL_RAM_BLOCK_FCL_RESERVED };
"LOC1ST":place in LOC_1ST_region
{ 
  rw section LOCAL1_RAM*
};
File name:lnkrr7f701557.icf
define exported symbol _LOC_1ST_BEG = 0xFEBE0000;
define exported symbol _LOC_1ST_END = 0xFEBEFFFF;
define region LOC_1ST_region = mem:[from _LOC_1ST_BEG to _LOC_1ST_END];  // LOCAL1_RAM      Local RAM for PE1

很好,也找完了。

4、文件修改

fcl_descriptor.h

#define FCL_CPU_FREQUENCY_MHZ  (80)                          /*!< CPU frequency in MHz */
#define FCL_AUTHENTICATION_ID {0xFFFFFFFF, \
                               0xFFFFFFFF, \
                               0xFFFFFFFF, \
                               0xFFFFFFFF}                    /*!< 128Bit authentication ID */
#define FCL_RAM_ADDRESS        0xFEDE0000                     /*!< RAM address range blocked for FCL */

我们只需修改CPU频率和RAM地址
从上边可以知道557的CPU频率是80MHz,RAM起始地址是0xFEDE 0000。

5、main()函数执行

5.1 ret = R_FCL_Init (&sampleApp_fclConfig_enu);

该函数用于初始化FCL,这个函数在ROM中执行。

5.2 ret = R_FCL_CopySections ();

该函数用于将一些FCL代码块copy到RAM中一个特定的地址中。在这个位置上,虽然Code Flash不可使用但是代码依然可以被执行。
函数R_FCL_CopySections在ROM中被执行。

5.3 fpFct = ( uint32_t (*)() )R_FCL_CalcFctAddr ( (uint32_t)(&FCL_Ctrl) );

fpFct ();
这个函数用于计算一个从ROM复制到RAM的函数的新地址。也就是说R_FCL_CalcFctAddr是为了计算出一个新的RAM地址,这个地址用于在RAM中运行一个特定的函数,这个特定的函数是从ROM中搬到RAM中运行的。为了能够计算这个特定函数的新RAM地址,这个特定的函数必须是FCL linker segments之一。
R_FCL_CalcFctAddr在ROM中被执行。

其实看这两行代码还是挺有意思的,函数R_FCL_CalcFctAddr()的形参是地址,用法(uint32_t)(&FCL_Ctrl) 是取函数FCL_Ctrl的地址,也就是说作为R_FCL_CalcFctAddr()的实参。R_FCL_CalcFctAddr()的返回值是destination address也就是新的RAM地址,经过强制类型转换( uint32_t (*)() )之后,R_FCL_CalcFctAddr成了一个函数指针,返回值是一个指针,指向新的RAM地址。因此fpFct ();是在RAM中执行的。从而实现了将FCL_Ctrl从ROM搬到RAM执行。

5.4 最后就是while(1)这个主循环了。
由于FCL_Ctrl在RAM中执行,那么在仿真时就没法看到FCL_Ctrl函数体的执行情况了。
所以在此为了能够看到FCL_Ctrl的执行结果,就定义了一个全局变量test_value用于观察FCL_Ctrl的执行结果。
5.4.1 获取Flash的Block Counter
void FCL_Ctrl (void)
{
    r_fcl_request_t     myRequest;
#if R_FCL_COMMAND_EXECUTION_MODE == R_FCL_HANDLER_CALL_USER
        r_fcl_request_t mySecRequest;
#endif
    uint8_t             writeBuffer_u08[512];
    uint32_t            readBuffer_u32[8];
    uint16_t            i;

    REINITIALIZE_BUFFER;

    FCLUser_Open ();

    /* prepare environment */
    myRequest.command_enu = R_FCL_CMD_PREPARE_ENV;
    R_FCL_Execute (&myRequest);
    #if R_FCL_COMMAND_EXECUTION_MODE == R_FCL_HANDLER_CALL_USER
        while (R_FCL_BUSY == myRequest.status_enu)
        {
            R_FCL_Handler ();
        }
    #endif

    /* get block count */
    myRequest.command_enu   = R_FCL_CMD_GET_BLOCK_CNT;
    myRequest.bufferAdd_u32 = (uint32_t)&readBuffer_u32[0];
    R_FCL_Execute (&myRequest);
    #if R_FCL_COMMAND_EXECUTION_MODE == R_FCL_HANDLER_CALL_USER
        while (R_FCL_BUSY == myRequest.status_enu)
        {
            R_FCL_Handler ();
        }
    #endif
    test_value = myRequest.bufferAdd_u32;

//    /* get block end address of block 2 */
//    REINITIALIZE_BUFFER;
//    myRequest.command_enu   = R_FCL_CMD_GET_BLOCK_END_ADDR;
//    myRequest.bufferAdd_u32 = (uint32_t)&readBuffer_u32[0];
//    myRequest.idx_u32       = 0x2;                   /* result: 0x5fff */
//    R_FCL_Execute (&myRequest);
//    test_value = myRequest.bufferAdd_u32;
//
//    /* erase block 2 and 3 */
//    myRequest.command_enu = R_FCL_CMD_ERASE;
//    myRequest.idx_u32     = 0x2;                   /* erased range = 0x4000 to 0x7fff */
//    myRequest.cnt_u16     = 2;
//    R_FCL_Execute (&myRequest);
//    #if R_FCL_COMMAND_EXECUTION_MODE == R_FCL_HANDLER_CALL_USER
//        while (R_FCL_BUSY == myRequest.status_enu)
//        {
//            R_FCL_Handler ();
//        }
//    #endif
//
//    /* write 512 bytes to address 0x40000 (start of block 2) */
//    REINITIALIZE_BUFFER;
//    myRequest.command_enu = R_FCL_CMD_WRITE;
//    myRequest.bufferAdd_u32 = (uint32_t)&writeBuffer_u08[0];
//    myRequest.idx_u32       = 0x4000;
//    myRequest.cnt_u16       = 2;                    /* written bytes = 256 * cnt_u16 */
//    R_FCL_Execute (&myRequest);
//    #if R_FCL_COMMAND_EXECUTION_MODE == R_FCL_HANDLER_CALL_USER
//        while (R_FCL_BUSY == myRequest.status_enu)
//        {
//            R_FCL_Handler ();
//        }
//    #endif
//    test_value = 0x4004;

    FCLUser_Close ();
} /* FCL_Ctrl */

经Debug,返回值是38个Block,正确。
在这里插入图片描述

5.4.2 获取指定Block的end address
void FCL_Ctrl (void)
{
    r_fcl_request_t     myRequest;
#if R_FCL_COMMAND_EXECUTION_MODE == R_FCL_HANDLER_CALL_USER
        r_fcl_request_t mySecRequest;
#endif
    uint8_t             writeBuffer_u08[512];
    uint32_t            readBuffer_u32[8];
    uint16_t            i;

    REINITIALIZE_BUFFER;

    FCLUser_Open ();

    /* prepare environment */
    myRequest.command_enu = R_FCL_CMD_PREPARE_ENV;
    R_FCL_Execute (&myRequest);
    #if R_FCL_COMMAND_EXECUTION_MODE == R_FCL_HANDLER_CALL_USER
        while (R_FCL_BUSY == myRequest.status_enu)
        {
            R_FCL_Handler ();
        }
    #endif

    /* get block count */
    myRequest.command_enu   = R_FCL_CMD_GET_BLOCK_CNT;
    myRequest.bufferAdd_u32 = (uint32_t)&readBuffer_u32[0];
    R_FCL_Execute (&myRequest);
    #if R_FCL_COMMAND_EXECUTION_MODE == R_FCL_HANDLER_CALL_USER
        while (R_FCL_BUSY == myRequest.status_enu)
        {
            R_FCL_Handler ();
        }
    #endif
    test_value = myRequest.bufferAdd_u32;

    /* get block end address of block 2 */
    REINITIALIZE_BUFFER;
    myRequest.command_enu   = R_FCL_CMD_GET_BLOCK_END_ADDR;
    myRequest.bufferAdd_u32 = (uint32_t)&readBuffer_u32[0];
    myRequest.idx_u32       = 0x2;                   /* result: 0x5fff */
    R_FCL_Execute (&myRequest);
    test_value = myRequest.bufferAdd_u32;

//    /* erase block 2 and 3 */
//    myRequest.command_enu = R_FCL_CMD_ERASE;
//    myRequest.idx_u32     = 0x2;                   /* erased range = 0x4000 to 0x7fff */
//    myRequest.cnt_u16     = 2;
//    R_FCL_Execute (&myRequest);
//    #if R_FCL_COMMAND_EXECUTION_MODE == R_FCL_HANDLER_CALL_USER
//        while (R_FCL_BUSY == myRequest.status_enu)
//        {
//            R_FCL_Handler ();
//        }
//    #endif
//
//    /* write 512 bytes to address 0x40000 (start of block 2) */
//    REINITIALIZE_BUFFER;
//    myRequest.command_enu = R_FCL_CMD_WRITE;
//    myRequest.bufferAdd_u32 = (uint32_t)&writeBuffer_u08[0];
//    myRequest.idx_u32       = 0x4000;
//    myRequest.cnt_u16       = 2;                    /* written bytes = 256 * cnt_u16 */
//    R_FCL_Execute (&myRequest);
//    #if R_FCL_COMMAND_EXECUTION_MODE == R_FCL_HANDLER_CALL_USER
//        while (R_FCL_BUSY == myRequest.status_enu)
//        {
//            R_FCL_Handler ();
//        }
//    #endif
//    test_value = 0x4004;

    FCLUser_Close ();
} /* FCL_Ctrl */

经Debug,block2的end address返回值是0x0000 5FFFF,正确。
在这里插入图片描述

5.4.3 对Code Flash进行write,然后读取,确认数值是否正确

注意:write之前要先Erase

void FCL_Ctrl (void)
{
    r_fcl_request_t     myRequest;
#if R_FCL_COMMAND_EXECUTION_MODE == R_FCL_HANDLER_CALL_USER
        r_fcl_request_t mySecRequest;
#endif
    uint8_t             writeBuffer_u08[512];
    uint32_t            readBuffer_u32[8];
    uint16_t            i;

    REINITIALIZE_BUFFER;

    FCLUser_Open ();

    /* prepare environment */
    myRequest.command_enu = R_FCL_CMD_PREPARE_ENV;
    R_FCL_Execute (&myRequest);
    #if R_FCL_COMMAND_EXECUTION_MODE == R_FCL_HANDLER_CALL_USER
        while (R_FCL_BUSY == myRequest.status_enu)
        {
            R_FCL_Handler ();
        }
    #endif

    /* get block count */
    myRequest.command_enu   = R_FCL_CMD_GET_BLOCK_CNT;
    myRequest.bufferAdd_u32 = (uint32_t)&readBuffer_u32[0];
    R_FCL_Execute (&myRequest);
    #if R_FCL_COMMAND_EXECUTION_MODE == R_FCL_HANDLER_CALL_USER
        while (R_FCL_BUSY == myRequest.status_enu)
        {
            R_FCL_Handler ();
        }
    #endif
    test_value = myRequest.bufferAdd_u32;

    /* get block end address of block 2 */
    REINITIALIZE_BUFFER;
    myRequest.command_enu   = R_FCL_CMD_GET_BLOCK_END_ADDR;
    myRequest.bufferAdd_u32 = (uint32_t)&readBuffer_u32[0];
    myRequest.idx_u32       = 0x2;                   /* result: 0x5fff */
    R_FCL_Execute (&myRequest);
    test_value = myRequest.bufferAdd_u32;

    /* erase block 2 and 3 */
    myRequest.command_enu = R_FCL_CMD_ERASE;
    myRequest.idx_u32     = 0x2;                   /* erased range = 0x4000 to 0x7fff */
    myRequest.cnt_u16     = 2;
    R_FCL_Execute (&myRequest);
    #if R_FCL_COMMAND_EXECUTION_MODE == R_FCL_HANDLER_CALL_USER
        while (R_FCL_BUSY == myRequest.status_enu)
        {
            R_FCL_Handler ();
        }
    #endif

    /* write 512 bytes to address 0x40000 (start of block 2) */
    REINITIALIZE_BUFFER;
    myRequest.command_enu = R_FCL_CMD_WRITE;
    myRequest.bufferAdd_u32 = (uint32_t)&writeBuffer_u08[0];
    myRequest.idx_u32       = 0x4000;
    myRequest.cnt_u16       = 2;                    /* written bytes = 256 * cnt_u16 */
    R_FCL_Execute (&myRequest);
    #if R_FCL_COMMAND_EXECUTION_MODE == R_FCL_HANDLER_CALL_USER
        while (R_FCL_BUSY == myRequest.status_enu)
        {
            R_FCL_Handler ();
        }
    #endif
    test_value = 0x4004;

    FCLUser_Close ();
} /* FCL_Ctrl */

经Debug,地址0x0000 4004开始的4Bytes数据是0x04 0x05 0x06 0x07,正确。
在这里插入图片描述
解释:因为我们数据存储使用的是Motorola格式(高字节在前),所以Debug出来结果显示是0x07060504
在这里插入图片描述
关于Erase和Write质量要特别注意一点:
很多时候执行力Erase之后,返回的myRequest.status_enu为R_FCL_ERR_PROTECTION,这是由于Flash被保护起来了,解决办法就是使用RFP对真个chip进行Erase再进行这些指令。
在这里插入图片描述

有疑问或需要探讨的地方,欢迎留言交流

本店铺有瑞萨E1仿真器,瑞萨RH850F1x开发板(RH850F1L,RH850F1K,RH850F1H,RH850F1KM,RH850F1KH),CANPiggy/LINPiggy,CANBOX(CANcase XL/VN1630替代款),CANoe,GHS,欢迎大家进店咨询。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值