260 lines
8.3 KiB
C
260 lines
8.3 KiB
C
/* ------------------------------------------
|
|
* Copyright (c) 2017, Synopsys, Inc. All rights reserved.
|
|
|
|
* Redistribution and use in source and binary forms, with or without modification,
|
|
* are permitted provided that the following conditions are met:
|
|
|
|
* 1) Redistributions of source code must retain the above copyright notice, this
|
|
* list of conditions and the following disclaimer.
|
|
|
|
* 2) Redistributions in binary form must reproduce the above copyright notice,
|
|
* this list of conditions and the following disclaimer in the documentation and/or
|
|
* other materials provided with the distribution.
|
|
|
|
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
|
|
* be used to endorse or promote products derived from this software without
|
|
* specific prior written permission.
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*
|
|
--------------------------------------------- */
|
|
#include "embARC.h"
|
|
#include "embARC_debug.h"
|
|
|
|
#define MAX_SYS_COUNTER_VALUE (0xffffffff)
|
|
|
|
#ifndef BOARD_SYS_TIMER_HZ
|
|
#define BOARD_SYS_TIMER_HZ (1000)
|
|
#endif
|
|
|
|
#ifndef EMBARC_BANNER_TYPE
|
|
#define EMBARC_BANNER_TYPE 1
|
|
#endif
|
|
|
|
static const char *embarc_banner =
|
|
#if EMBARC_BANNER_TYPE == 1
|
|
"----------------------------------------------------------- \r\n\
|
|
____ _ ____ \r\n\
|
|
| _ \\ _____ _____ _ __ ___ __| | __ ) _ _ \r\n\
|
|
| |_) / _ \\ \\ /\\ / / _ \\ '__/ _ \\/ _` | _ \\| | | | \r\n\
|
|
| __/ (_) \\ V V / __/ | | __/ (_| | |_) | |_| | \r\n\
|
|
|_| \\___/ \\_/\\_/ \\___|_| \\___|\\__,_|____/ \\__, | \r\n\
|
|
|___/ \r\n\
|
|
_ _ ____ ____ \r\n\
|
|
___ _ __ ___ | |__ / \\ | _ \\ / ___| \r\n\
|
|
/ _ \\ '_ ` _ \\| '_ \\ / _ \\ | |_) | | \r\n\
|
|
| __/ | | | | | |_) / ___ \\| _ <| |___ \r\n\
|
|
\\___|_| |_| |_|_.__/_/ \\_\\_| \\_\\\\____| \r\n\
|
|
------------------------------------------------------------ \r\n\
|
|
";
|
|
#else
|
|
"-----------------------------------------------------------------------------------------------\r\n\
|
|
_/_/_/ _/ _/_/_/ \r\n\
|
|
_/ _/ _/_/ _/ _/ _/ _/_/ _/ _/_/ _/_/ _/_/_/ _/ _/ _/ _/ \r\n\
|
|
_/_/_/ _/ _/ _/ _/ _/ _/_/_/_/ _/_/ _/_/_/_/ _/ _/ _/_/_/ _/ _/ \r\n\
|
|
_/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ \r\n\
|
|
_/ _/_/ _/ _/ _/_/_/ _/ _/_/_/ _/_/_/ _/_/_/ _/_/_/ \r\n\
|
|
_/ \r\n\
|
|
_/_/ \r\n\
|
|
_/ _/_/ _/_/_/ _/_/_/ \r\n\
|
|
_/_/ _/_/_/ _/_/ _/_/_/ _/ _/ _/ _/ _/ \r\n\
|
|
_/_/_/_/ _/ _/ _/ _/ _/ _/_/_/_/ _/_/_/ _/ \r\n\
|
|
_/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ \r\n\
|
|
_/_/_/ _/ _/ _/ _/_/_/ _/ _/ _/ _/ _/_/_/ \r\n\
|
|
------------------------------------------------------------------------------------------------\r\n\
|
|
";
|
|
#endif
|
|
|
|
/** board timer interrupt reset count */
|
|
static uint32_t cyc_hz_count = (BOARD_CPU_CLOCK / BOARD_SYS_TIMER_HZ);
|
|
|
|
/** board timer counter in timer interrupt */
|
|
static volatile uint64_t gl_sys_hz_cnt = 0;
|
|
/** board 1ms counter */
|
|
static volatile uint32_t gl_ms_cnt = 0;
|
|
|
|
#define HZ_COUNT_CONV(precision, base) ((precision) / (base))
|
|
|
|
/**
|
|
* @brief Board bare-metal timer interrupt.
|
|
* Interrupt frequency is based on the defined @ref BOARD_SYS_TIMER_HZ
|
|
*/
|
|
static void board_timer_isr(void *ptr)
|
|
{
|
|
timer_int_clear(BOARD_SYS_TIMER_ID);
|
|
|
|
board_timer_update(BOARD_SYS_TIMER_HZ);
|
|
}
|
|
|
|
/**
|
|
* @brief Initialise bare-metal board timer and interrupt
|
|
* @details
|
|
* This function is called in @ref board_init, and
|
|
* it initializes the 1-MS timer interrupt for bare-metal mode
|
|
*/
|
|
static void board_timer_init(void)
|
|
{
|
|
if (timer_present(BOARD_SYS_TIMER_ID)) {
|
|
int_disable(BOARD_SYS_TIMER_INTNO); /* disable first then enable */
|
|
int_handler_install(BOARD_SYS_TIMER_INTNO, board_timer_isr);
|
|
timer_start(BOARD_SYS_TIMER_ID, TIMER_CTRL_IE | TIMER_CTRL_NH, cyc_hz_count); /* start 1ms timer interrupt */
|
|
|
|
int_enable(BOARD_SYS_TIMER_INTNO);
|
|
}
|
|
}
|
|
|
|
static void platform_print_banner(void)
|
|
{
|
|
EMBARC_PRINTF("%s\r\n", embarc_banner);
|
|
EMBARC_PRINTF("embARC Build Time: %s, %s\r\n", __DATE__, __TIME__);
|
|
#if defined(__GNU__)
|
|
EMBARC_PRINTF("Compiler Version: ARC GNU, %s\r\n", __VERSION__);
|
|
#else
|
|
EMBARC_PRINTF("Compiler Version: Metaware, %s\r\n\r\n", __VERSION__);
|
|
#endif
|
|
}
|
|
|
|
EMBARC_WEAK void platform_main(void)
|
|
{
|
|
#ifdef LIB_CONSOLE
|
|
xprintf_setup();
|
|
#endif
|
|
platform_print_banner();
|
|
arc_goto_main(0, NULL);
|
|
}
|
|
|
|
EMBARC_WEAK void board_main(void)
|
|
{
|
|
#if defined(__MW__)
|
|
/* Metaware toolchain C++ init */
|
|
arc_mwdt_init();
|
|
#elif defined(__GNU__)
|
|
/* ARC GNU toolchain C++ init */
|
|
|
|
arc_gnu_do_global_ctors_aux();
|
|
arc_gnu_do_init_array_aux();
|
|
#endif
|
|
/* init core level interrupt & exception management */
|
|
exc_int_init();
|
|
/* init cache */
|
|
arc_cache_init();
|
|
/* necessary board level init */
|
|
board_init();
|
|
/* Initialise bare-metal board timer and interrupt */
|
|
board_timer_init();
|
|
/* platform (e.g RTOS, baremetal)level init */
|
|
platform_main();
|
|
#if defined(__MW__)
|
|
arc_mwdt_fini();
|
|
#elif defined(__GNU__)
|
|
arc_gnu_do_global_dtors_aux();
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* @brief Update timer counter and other MS period operation
|
|
* in cycling interrupt and must be called periodically.
|
|
* @param precision interrupt-period precision in Hz
|
|
*/
|
|
void board_timer_update(uint32_t precision)
|
|
{
|
|
static uint32_t sys_hz_update = 0;
|
|
static uint32_t sys_ms_update = 0;
|
|
uint32_t hz_conv = 0;
|
|
|
|
/** count sys hz */
|
|
hz_conv = HZ_COUNT_CONV(precision, BOARD_SYS_TIMER_HZ);
|
|
sys_hz_update++;
|
|
if (sys_hz_update >= hz_conv) {
|
|
sys_hz_update = 0;
|
|
gl_sys_hz_cnt++;
|
|
}
|
|
|
|
/** count ms */
|
|
hz_conv = HZ_COUNT_CONV(precision, BOARD_SYS_TIMER_MS_HZ);
|
|
sys_ms_update++;
|
|
if (sys_ms_update >= hz_conv) {
|
|
sys_ms_update = 0;
|
|
gl_ms_cnt++;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Get current timer's counter value in ticks
|
|
* @retval Ticks count in 64 bit format
|
|
*/
|
|
uint64_t board_get_hwticks(void)
|
|
{
|
|
uint32_t sub_ticks;
|
|
uint64_t total_ticks;
|
|
|
|
timer_current(TIMER_0, &sub_ticks);
|
|
|
|
total_ticks = (uint64_t)GET_CUR_MS() * (BOARD_CPU_CLOCK / BOARD_SYS_TIMER_HZ);
|
|
total_ticks += (uint64_t)sub_ticks;
|
|
|
|
return total_ticks;
|
|
}
|
|
|
|
/**
|
|
* @brief Get current passed us since timer init
|
|
* @retval us Count in 64 bit format
|
|
*/
|
|
uint64_t board_get_cur_us(void)
|
|
{
|
|
uint32_t sub_us;
|
|
uint64_t total_us;
|
|
|
|
timer_current(TIMER_0, &sub_us);
|
|
|
|
sub_us = ((uint64_t)sub_us * 1000000) / BOARD_CPU_CLOCK;
|
|
total_us = ((uint64_t)GET_CUR_MS()) * 1000 + (uint64_t)sub_us;
|
|
|
|
return total_us;
|
|
}
|
|
|
|
/**
|
|
* @brief Get current passed ms since timer init
|
|
* @retval ms Count in 32 bit format
|
|
*/
|
|
uint32_t board_get_cur_ms(void)
|
|
{
|
|
return gl_ms_cnt;
|
|
}
|
|
|
|
/**
|
|
* @brief Get board timer counter in timer interrupt
|
|
* @retval Count in 64 bit format
|
|
*/
|
|
uint64_t board_get_cur_syshz(void)
|
|
{
|
|
return gl_sys_hz_cnt;
|
|
}
|
|
|
|
/**
|
|
* @brief Function for delaying execution for number of milliseconds
|
|
* @details
|
|
* This function needs a 1-MS timer interrupt to work.
|
|
* For bare-metal, it is implemented in this file.
|
|
* @param ms Delay in milliseconds
|
|
*/
|
|
void board_delay_ms(uint32_t ms)
|
|
{
|
|
uint64_t start_us, us_delayed;
|
|
|
|
us_delayed = ((uint64_t)ms * 1000);
|
|
start_us = board_get_cur_us();
|
|
while ((board_get_cur_us() - start_us) < us_delayed) {
|
|
;
|
|
}
|
|
}
|