* arch/ceva/src/common/ceva_start.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <nuttx/arch.h>
#include <nuttx/init.h>
#include <nuttx/userspace.h>
#include <arch/board/board.h>
#include <string.h>
#include "mpu.h"
#include "ceva_internal.h"
#if CONFIG_ARCH_NR_MEMORY >= 2
# define _START_TEXT2 _stext2
# define _END_TEXT2 _etext2
# define _START_BSS2 _sbss2
# define _END_BSS2 _ebss2
# define _DATA_INIT2 _eronly2
# define _START_DATA2 _sdata2
# define _END_DATA2 _edata2
#else
# define _START_TEXT2 NULL
# define _END_TEXT2 NULL
# define _START_BSS2 NULL
# define _END_BSS2 NULL
# define _DATA_INIT2 NULL
# define _START_DATA2 NULL
# define _END_DATA2 NULL
#endif
#if CONFIG_ARCH_NR_MEMORY >= 3
# define _START_TEXT3 _stext3
# define _END_TEXT3 _etext3
# define _START_BSS3 _sbss3
# define _END_BSS3 _ebss3
# define _DATA_INIT3 _eronly3
# define _START_DATA3 _sdata3
# define _END_DATA3 _edata3
#else
# define _START_TEXT3 NULL
# define _END_TEXT3 NULL
# define _START_BSS3 NULL
# define _END_BSS3 NULL
# define _DATA_INIT3 NULL
# define _START_DATA3 NULL
# define _END_DATA3 NULL
#endif
#if CONFIG_ARCH_NR_MEMORY >= 4
# define _START_TEXT4 _stext4
# define _END_TEXT4 _etext4
# define _START_BSS4 _sbss4
# define _END_BSS4 _ebss4
# define _DATA_INIT4 _eronly4
# define _START_DATA4 _sdata4
# define _END_DATA4 _edata4
#else
# define _START_TEXT4 NULL
# define _END_TEXT4 NULL
# define _START_BSS4 NULL
# define _END_BSS4 NULL
# define _DATA_INIT4 NULL
# define _START_DATA4 NULL
# define _END_DATA4 NULL
#endif
#if CONFIG_ARCH_NR_MEMORY >= 5
# error CONFIG_ARCH_NR_MEMORY must between 1 to 4
#endif
* Private Function prototypes
****************************************************************************/
static void init_bss_section(bool priv,
void *const bssstart[],
void *const bssend[]);
static void init_data_section(bool priv,
const void *const datasource[],
void *const datastart[],
void *const dataend[]);
static void init_text_section(bool priv,
const void *const textstart[],
const void *const textend[]);
static void init_kernelspace(void);
#ifdef CONFIG_BUILD_PROTECTED
static void init_userspace(void);
#endif
* Private Functions
****************************************************************************/
static void init_bss_section(bool priv,
void *const bssstart[],
void *const bssend[])
{
int i;
for (i = 0; bssstart[i] != _END_MEM || bssend[i] != _END_MEM; i++)
{
if (priv)
{
mpu_priv_data(bssstart[i], bssend[i] - bssstart[i]);
}
else
{
mpu_user_data(bssstart[i], bssend[i] - bssstart[i]);
}
memset(bssstart[i], 0, bssend[i] - bssstart[i]);
}
}
static void init_data_section(bool priv,
const void *const datasource[],
void *const datastart[],
void *const dataend[])
{
int i;
for (i = 0; datasource[i] != _END_MEM
|| datastart[i] != _END_MEM
|| dataend[i] != _END_MEM; i++)
{
if (priv)
{
mpu_priv_data(datastart[i], dataend[i] - datastart[i]);
}
else
{
mpu_user_data(datastart[i], dataend[i] - datastart[i]);
}
if (datasource[i] != datastart[i])
{
memcpy(datastart[i], datasource[i], dataend[i] - datastart[i]);
}
}
}
static void init_text_section(bool priv,
const void *const textstart[],
const void *const textend[])
{
int i;
for (i = 0; textstart[i] != _END_MEM || textend[i] != _END_MEM; i++)
{
if (priv)
{
mpu_priv_code(textstart[i], textend[i] - textstart[i]);
}
else
{
mpu_user_code(textstart[i], textend[i] - textstart[i]);
}
}
}
static void init_kernelspace(void)
{
const void *const textstart[] =
{
_START_TEXT, _START_TEXT2, _START_TEXT3, _START_TEXT4, _END_MEM,
};
const void *const textend[] =
{
_END_TEXT, _END_TEXT2, _END_TEXT3, _END_TEXT4, _END_MEM,
};
const void *const datasource[] =
{
_DATA_INIT, _DATA_INIT2, _DATA_INIT3, _DATA_INIT4, _END_MEM,
};
void *const datastart[] =
{
_START_DATA, _START_DATA2, _START_DATA3, _START_DATA4, _END_MEM,
};
void *const dataend[] =
{
_END_DATA, _END_DATA2, _END_DATA3, _END_DATA4, _END_MEM,
};
void *const bssstart[] =
{
_START_BSS, _START_BSS2, _START_BSS3, _START_BSS4, _END_MEM,
};
void *const bssend[] =
{
_END_BSS, _END_BSS2, _END_BSS3, _END_BSS4, _END_MEM,
};
init_text_section(true, textstart, textend);
* FLASH into the correct place in SRAM. The correct place in SRAM is
* give by _sdata and _edata. The temporary location is in FLASH at the
* end of all of the other read-only data (.text, .rodata) at _eronly.
*/
init_data_section(true, datasource, datastart, dataend);
* certain that there are no issues with the state of global variables.
*/
init_bss_section(true, bssstart, bssend);
mpu_priv_data(g_idle_basestack,
g_idle_topstack - g_idle_basestack);
}
#ifdef CONFIG_BUILD_PROTECTED
static void init_userspace(void)
{
DEBUGASSERT(
USERSPACE->us_datasource != 0 &&
USERSPACE->us_datastart != 0 &&
USERSPACE->us_dataend != 0);
init_text_section(false,
(const void *const *)USERSPACE->us_textstart,
(const void *const *)USERSPACE->us_textend);
init_data_section(false,
(const void *const *)USERSPACE->us_datasource,
(void *const *)USERSPACE->us_datastart,
(void *const *)USERSPACE->us_dataend);
DEBUGASSERT(
USERSPACE->us_bssstart != 0 &&
USERSPACE->us_bssend != 0);
init_bss_section(false,
(void *const *)USERSPACE->us_bssstart,
(void *const *)USERSPACE->us_bssend);
}
#else
# define init_userspace()
#endif
* Public Functions
****************************************************************************/
* Name: up_start
*
* Description:
* This is the reset entry point.
*
****************************************************************************/
void up_start(void)
{
up_enable_icache();
up_enable_dcache();
init_kernelspace();
init_userspace();
mpu_control(true);
ceva_earlyserialinit();
ceva_earlyinitialize();
board_earlyinitialize();
nx_start();
}