drv_rtp.c 5.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250
/**************************************************************************//**
* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date            Author       Notes
* 2022-9-27       Wayne        First version
*
******************************************************************************/

#include <rtconfig.h>

#if !defined(USE_MA35D1_SUBM)

#define LOG_TAG    "drv.rtp"
#undef  DBG_ENABLE
#define DBG_SECTION_NAME   LOG_TAG
#define DBG_LEVEL      LOG_LVL_DBG
#define DBG_COLOR
#include <rtdbg.h>

#include <rtdevice.h>
#include "drv_sys.h"
#include <dfs_file.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/statfs.h>

#define RTP_USING_AT_STARTUP

/* Link to rtthread.bin in ma35-rtp folder. */
#define PATH_RTP_INCBIN          "..//ma35-rtp//rtthread.bin"

#define READ_BLOCK_SIZE       128
#define REGION_ADDR_SRAM0     0x24000000
#define REGION_ADDR_DDR       (0x80020000|UNCACHEABLE)
#define REGION_MAXSIZE_SRAM0  (128*1024)
#define REGION_MAXSIZE_DDR    (4*1024*1024-REGION_MAXSIZE_SRAM0)
#define REGION_MAXSIZE_LIMIT  (REGION_MAXSIZE_SRAM0+REGION_MAXSIZE_DDR)

#if !defined(PATH_RTP_FW_FILE)
    #define PATH_RTP_FW_FILE "/mnt/sd1p0/rtp.bin"
#endif

#if defined(RTP_USING_AT_STARTUP)

#define STR2(x) #x
#define STR(x) STR2(x)

#define INCBIN(name, file) \
    __asm__(".section .rodata\n" \
            ".global incbin_" STR(name) "_start\n" \
            ".balign 16\n" \
            "incbin_" STR(name) "_start:\n" \
            ".incbin \"" file "\"\n" \
            \
            ".global incbin_" STR(name) "_end\n" \
            ".balign 1\n" \
            "incbin_" STR(name) "_end:\n" \
            ".byte 0\n" \
    ); \
    extern const __attribute__((aligned(16))) void* incbin_ ## name ## _start; \
    extern const void* incbin_ ## name ## _end; \

INCBIN(rtp, PATH_RTP_INCBIN);

static int nu_rtp_load_from_memory(void *pvBuf, int len)
{
    int remaining;

    if (!pvBuf || !len)
        goto exit_nu_rtp_load_from_memory;

    /* Limit memory usage to 4MB. */
    if (len > REGION_MAXSIZE_LIMIT)
        goto exit_nu_rtp_load_from_memory;

    remaining = len;

    /* Copy to SRAM0 */
    if (remaining > REGION_MAXSIZE_SRAM0)
    {
        rt_memcpy((void *)REGION_ADDR_SRAM0, pvBuf, REGION_MAXSIZE_SRAM0);
        remaining -= REGION_MAXSIZE_SRAM0;
    }
    else
    {
        rt_memcpy((void *)REGION_ADDR_SRAM0, pvBuf, remaining);
        remaining -= remaining;
    }

    /* Copy to non-cacheable DDR memory if the size over 128KB. */
    if (remaining > 0)
    {
        rt_memcpy((void *)REGION_ADDR_DDR, (pvBuf + REGION_MAXSIZE_SRAM0), remaining);
        remaining -= remaining;
    }

    return 0;

exit_nu_rtp_load_from_memory:

    return -1;
}
#endif

RT_WEAK void nu_rtp_sspcc_setup(void)
{
    SSPCC_SET_REALM(SSPCC_UART16, SSPCC_SSET_SUBM);

    SSPCC_SET_GPIO_REALM(PK, 0, SSPCC_SSET_SUBM);
    SSPCC_SET_GPIO_REALM(PK, 1, SSPCC_SSET_SUBM);
    SSPCC_SET_GPIO_REALM(PK, 2, SSPCC_SSET_SUBM);
    SSPCC_SET_GPIO_REALM(PK, 3, SSPCC_SSET_SUBM);
}

static void nu_rtp_init(void)
{
    /* Enable WDT1/WDT2 reset */
    SYS->MISCRFCR |= SYS_MISCRFCR_WDT1RSTAEN_Msk | SYS_MISCRFCR_WDT2RSTAEN_Msk | SYS_MISCRFCR_WDT1RSTMEN_Msk;

    /* Enable M4 I/D cache */
    SYS->MISCFCR0 |= (SYS_MISCFCR0_RTPICACHEN_Msk | SYS_MISCFCR0_RTPDCACHEN_Msk | SYS_MISCFCR0_RTPDRMAEN_Msk);

    nu_rtp_sspcc_setup();
}

void nu_rtp_start(void)
{
    /* Enable RTP clock */
    CLK_EnableModuleClock(RTP_MODULE);

    /* Disable M4 Core reset*/
    SYS->IPRST0 &= ~SYS_IPRST0_CM4RST_Msk;
}
MSH_CMD_EXPORT(nu_rtp_start, start rtp);

void nu_rtp_stop(void)
{
    /* Enable M4 Core reset*/
    SYS->IPRST0 |= SYS_IPRST0_CM4RST_Msk;

    /* Disable RTP clock */
    CLK_DisableModuleClock(RTP_MODULE);
}
MSH_CMD_EXPORT(nu_rtp_stop, stop rtp);


#if defined(RT_USING_DFS)
static int nu_rtp_load_from_file(char *szAbsFilePath)
{
    int fd, ret = -1;
    char *buff_ptr = RT_NULL;
    rt_size_t offset = 0;

    fd = open(szAbsFilePath, O_RDONLY);
    if (fd < 0)
    {
        LOG_E("Could not open %s for rtp loading.", szAbsFilePath);
        goto exit_nu_rtp_load_from_file;
    }

    while (1)
    {
        int length;

        if (offset < REGION_MAXSIZE_SRAM0)
        {
            buff_ptr = (char *)(REGION_ADDR_SRAM0 + offset);
        }
        else
        {
            buff_ptr = (char *)(REGION_ADDR_DDR + offset - REGION_MAXSIZE_SRAM0);
        }

        /* Limit memory usage to 4MB. */
        if ((offset + READ_BLOCK_SIZE) >= REGION_MAXSIZE_SRAM0)
            goto exit_nu_rtp_load_from_file;

        length = read(fd, buff_ptr, READ_BLOCK_SIZE);

        if (length <= 0) break;
        offset += length;

        //rt_kprintf("readed (%d/%d) to %08x\n", length, offset, buff_ptr);
    }

    ret = 0;

exit_nu_rtp_load_from_file:

    if (fd >= 0)
        close(fd);

    return ret;
}

int nu_rtp_load_run(int argc, char *argv[])
{
    char *szFilePath = RT_NULL;

    if (argc == 1)
    {
        szFilePath = PATH_RTP_FW_FILE;
    }
    else if (argc == 2)
    {
        szFilePath = argv[1];
    }

    nu_rtp_stop();
    nu_rtp_init();

    if (!szFilePath || nu_rtp_load_from_file(szFilePath) < 0)
        return -1;

    rt_kprintf("Loaded %s, then run...\n", szFilePath);

    nu_rtp_start();

    return 0;
}
MSH_CMD_EXPORT(nu_rtp_load_run, load rtp code then run);
#endif

int rt_hw_rtp_init(void)
{
    int fw_size;

    fw_size = (int)((char *)&incbin_rtp_end - (char *)&incbin_rtp_start);
    rt_kprintf("INCBIN RTP Start = %p\n", &incbin_rtp_start);
    rt_kprintf("INCBIN RTP Size = %p\n", fw_size);

    /* Enable RTP and reset M4 reset */
    nu_rtp_init();

#if defined(RTP_USING_AT_STARTUP)
    nu_rtp_stop();
    nu_rtp_load_from_memory(&incbin_rtp_start, fw_size);
#endif

    nu_rtp_start();

    return 0;
}
INIT_BOARD_EXPORT(rt_hw_rtp_init);

#endif //#if defined(USE_MA35D1_SUBM)