Merge pull request #6060 from neiljay/pr/add_mips32r2_common_v2
mips: Import of mips32r2_common module
This commit is contained in:
commit
ef958cc0e6
@ -63,6 +63,7 @@ buildtest:
|
|||||||
WERROR=$${WERROR} \
|
WERROR=$${WERROR} \
|
||||||
LTO=$${LTO} \
|
LTO=$${LTO} \
|
||||||
TOOLCHAIN=$${TOOLCHAIN} \
|
TOOLCHAIN=$${TOOLCHAIN} \
|
||||||
|
MIPS_ELF_ROOT=$${MIPS_ELF_ROOT} \
|
||||||
$(MAKE) -j$(NPROC) clean all 2>&1) ; \
|
$(MAKE) -j$(NPROC) clean all 2>&1) ; \
|
||||||
if [ "$${?}" = "0" ]; then \
|
if [ "$${?}" = "0" ]; then \
|
||||||
${COLOR_ECHO} "${COLOR_GREEN}success${COLOR_RESET}"; \
|
${COLOR_ECHO} "${COLOR_GREEN}success${COLOR_RESET}"; \
|
||||||
@ -97,6 +98,7 @@ buildtest:
|
|||||||
BINDIRBASE=$${BINDIRBASE} \
|
BINDIRBASE=$${BINDIRBASE} \
|
||||||
RIOTNOLINK=$${RIOTNOLINK} \
|
RIOTNOLINK=$${RIOTNOLINK} \
|
||||||
RIOT_VERSION=$${RIOT_VERSION} \
|
RIOT_VERSION=$${RIOT_VERSION} \
|
||||||
|
MIPS_ELF_ROOT=$${MIPS_ELF_ROOT} \
|
||||||
$(MAKE) clean-intermediates 2>&1 >/dev/null || true; \
|
$(MAKE) clean-intermediates 2>&1 >/dev/null || true; \
|
||||||
done; \
|
done; \
|
||||||
$${BUILDTESTOK}
|
$${BUILDTESTOK}
|
||||||
@ -133,6 +135,7 @@ info-buildsizes:
|
|||||||
RIOTCPU=$${RIOTCPU} \
|
RIOTCPU=$${RIOTCPU} \
|
||||||
RIOTPKG=$${RIOTPKG} \
|
RIOTPKG=$${RIOTPKG} \
|
||||||
BINDIRBASE=$${BINDIRBASE} \
|
BINDIRBASE=$${BINDIRBASE} \
|
||||||
|
MIPS_ELF_ROOT=$${MIPS_ELF_ROOT} \
|
||||||
$(MAKE) info-buildsize 2>/dev/null | tail -n-1 | cut -f-4)" "$${BOARD}"; \
|
$(MAKE) info-buildsize 2>/dev/null | tail -n-1 | cut -f-4)" "$${BOARD}"; \
|
||||||
done;
|
done;
|
||||||
|
|
||||||
@ -150,6 +153,7 @@ info-buildsizes-diff:
|
|||||||
RIOTCPU=$${RIOTCPU} \
|
RIOTCPU=$${RIOTCPU} \
|
||||||
RIOTPKG=$${RIOTPKG} \
|
RIOTPKG=$${RIOTPKG} \
|
||||||
BINDIRBASE=$${BINDIRBASE} \
|
BINDIRBASE=$${BINDIRBASE} \
|
||||||
|
MIPS_ELF_ROOT=$${MIPS_ELF_ROOT} \
|
||||||
$(MAKE) info-buildsize 2>/dev/null | tail -n-1 | cut -f-4; \
|
$(MAKE) info-buildsize 2>/dev/null | tail -n-1 | cut -f-4; \
|
||||||
done | \
|
done | \
|
||||||
while read -a OLD && read -a NEW; do \
|
while read -a OLD && read -a NEW; do \
|
||||||
|
|||||||
3
boards/mips-malta/Makefile
Normal file
3
boards/mips-malta/Makefile
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
MODULE = board
|
||||||
|
|
||||||
|
include $(RIOTBASE)/Makefile.base
|
||||||
9
boards/mips-malta/Makefile.features
Normal file
9
boards/mips-malta/Makefile.features
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
# Put defined MCU peripherals here (in alphabetical order)
|
||||||
|
FEATURES_PROVIDED += periph_timer
|
||||||
|
FEATURES_PROVIDED += periph_uart
|
||||||
|
|
||||||
|
# Various other features (if any)
|
||||||
|
FEATURES_PROVIDED += cpp
|
||||||
|
|
||||||
|
# The board MPU family (used for grouping by the CI system)
|
||||||
|
FEATURES_MCU_GROUP = mips32r2
|
||||||
4
boards/mips-malta/Makefile.include
Normal file
4
boards/mips-malta/Makefile.include
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export CPU = mips32r2_common
|
||||||
|
export INCLUDES += -I$(RIOTBOARD)/$(BOARD)/include/
|
||||||
|
export USE_HARD_FLOAT = 1
|
||||||
|
export USE_DSP = 1
|
||||||
46
boards/mips-malta/include/board.h
Normal file
46
boards/mips-malta/include/board.h
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016, Imagination Technologies Limited and/or its
|
||||||
|
* affiliated group companies.
|
||||||
|
*
|
||||||
|
* This file is subject to the terms and conditions of the GNU Lesser
|
||||||
|
* General Public License v2.1. See the file LICENSE in the top level
|
||||||
|
* directory for more details.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup boards_mips-malta MIPS MALTA
|
||||||
|
* @ingroup boards
|
||||||
|
* @brief Board specific files for the MIPS Malta FPGA system
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief Board specific definitions for the MIPS Malta FPGA System.
|
||||||
|
*
|
||||||
|
* @author Neil Jones <neil.jones@imgtec.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _BOARD_H_
|
||||||
|
#define _BOARD_H_
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set how many increments of the count register per uS
|
||||||
|
* needed by timer code
|
||||||
|
*/
|
||||||
|
#define TICKS_PER_US (15)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Board level initialisation
|
||||||
|
*/
|
||||||
|
void board_init(void);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _BOARD_H_ */
|
||||||
|
/** @} */
|
||||||
59
boards/mips-malta/include/periph_conf.h
Normal file
59
boards/mips-malta/include/periph_conf.h
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016, Imagination Technologies Limited and/or its
|
||||||
|
* affiliated group companies.
|
||||||
|
*
|
||||||
|
* This file is subject to the terms and conditions of the GNU Lesser
|
||||||
|
* General Public License v2.1. See the file LICENSE in the top level
|
||||||
|
* directory for more details.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup boards_mips-malta MIPS MALTA
|
||||||
|
* @ingroup boards
|
||||||
|
* @brief peripheral configuration for the MIPS Malta FPGA system
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief peripheral configuration for the MIPS Malta FPGA system
|
||||||
|
*
|
||||||
|
* @author Neil Jones <neil.jones@imgtec.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _PERIPH_CONF_H_
|
||||||
|
#define _PERIPH_CONF_H_
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Timer definitions
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define TIMER_NUMOF (1)
|
||||||
|
#define TIMER_0_CHANNELS (3)
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief No UART driver for this board currently
|
||||||
|
* Note this value must be set though (to 0)
|
||||||
|
*/
|
||||||
|
#define UART_NUMOF (0)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Enable DSP context save + restore.
|
||||||
|
*/
|
||||||
|
#define MIPS_DSP (1)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Enable FPU context save + restore.
|
||||||
|
*/
|
||||||
|
#define MIPS_HARD_FLOAT (1)
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /*_PERIPH_CONF_H_*/
|
||||||
|
/** @} */
|
||||||
28
boards/mips-malta/malta.c
Normal file
28
boards/mips-malta/malta.c
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016, Imagination Technologies Limited and/or its
|
||||||
|
* affiliated group companies.
|
||||||
|
* This file is subject to the terms and conditions of the GNU Lesser
|
||||||
|
* General Public License v2.1. See the file LICENSE in the top level
|
||||||
|
* directory for more details.
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "periph/uart.h"
|
||||||
|
|
||||||
|
#define MIPS_MALTA_ADDR (0xbf000500)
|
||||||
|
#define MIPS_MALTA_VAL_RST (0x42)
|
||||||
|
|
||||||
|
static void malta_reset(void)
|
||||||
|
{
|
||||||
|
*(volatile long *)MIPS_MALTA_ADDR = MIPS_MALTA_VAL_RST;
|
||||||
|
__asm__ volatile ("wait");
|
||||||
|
}
|
||||||
|
|
||||||
|
void board_init(void)
|
||||||
|
{
|
||||||
|
/* Board initialisation is done by the bootloader (u-boot) on Malta */
|
||||||
|
}
|
||||||
|
|
||||||
|
void pm_reboot(void)
|
||||||
|
{
|
||||||
|
malta_reset();
|
||||||
|
}
|
||||||
4
cpu/mips32r2_common/Makefile
Normal file
4
cpu/mips32r2_common/Makefile
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
MODULE = cpu
|
||||||
|
DIRS = periph
|
||||||
|
|
||||||
|
include $(RIOTBASE)/Makefile.base
|
||||||
48
cpu/mips32r2_common/Makefile.include
Normal file
48
cpu/mips32r2_common/Makefile.include
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
ifndef MIPS_ELF_ROOT
|
||||||
|
$(error "Please set $$(MIPS_ELF_ROOT) and ensure $$(MIPS_ELF_ROOT)/bin is on your PATH")
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Target triple for the build.
|
||||||
|
export TARGET_ARCH ?= mips-mti-elf
|
||||||
|
|
||||||
|
export ABI=32
|
||||||
|
export MEMORY_BASE=0x80000000
|
||||||
|
export MEMORY_SIZE=1M
|
||||||
|
export APP_START=0x80000000
|
||||||
|
|
||||||
|
include $(MIPS_ELF_ROOT)/share/mips/rules/mipshal.mk
|
||||||
|
|
||||||
|
# define build specific options
|
||||||
|
export CFLAGS_CPU = -EL -march=mips32r2 -std=gnu99
|
||||||
|
export CFLAGS_LINK = -ffunction-sections -fdata-sections -fno-builtin -fshort-enums
|
||||||
|
export CFLAGS_DBG = -O0 -g2
|
||||||
|
export CFLAGS_OPT = -Os -g2
|
||||||
|
|
||||||
|
export CFLAGS += $(CFLAGS_CPU) $(CFLAGS_LINK) $(CFLAGS_OPT)
|
||||||
|
#$(CFLAGS_DBG)
|
||||||
|
|
||||||
|
ifeq ($(USE_HARD_FLOAT),1)
|
||||||
|
export CFLAGS += -mhard-float
|
||||||
|
else
|
||||||
|
export CFLAGS += -msoft-float #hard-float is the default so we must set soft-float
|
||||||
|
export LINKFLAGS += -msoft-float
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(USE_DSP),1)
|
||||||
|
export CFLAGS += -mdsp
|
||||||
|
endif
|
||||||
|
|
||||||
|
export ASFLAGS += $(CFLAGS_CPU) $(CFLAGS_OPT) #$(CFLAGS_DBG)
|
||||||
|
|
||||||
|
export LINKFLAGS += $(MIPS_HAL_LDFLAGS) -mabi=$(ABI)
|
||||||
|
export LINKFLAGS += -Tuhi32.ld
|
||||||
|
export LINKFLAGS += $(CFLAGS_CPU) $(CFLAGS_DBG) $(CFLAGS_OPT)
|
||||||
|
export LINKFLAGS += -Wl,--gc-sections
|
||||||
|
|
||||||
|
# This CPU implementation is using the new core/CPU interface:
|
||||||
|
export CFLAGS += -DCOREIF_NG=1
|
||||||
|
|
||||||
|
# use newlib as libc, Actually use toolchains newlib.
|
||||||
|
#export USEMODULE += newlib
|
||||||
|
|
||||||
|
export USEMODULE += periph
|
||||||
77
cpu/mips32r2_common/cpu.c
Normal file
77
cpu/mips32r2_common/cpu.c
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016, Imagination Technologies Limited and/or its
|
||||||
|
* affiliated group companies.
|
||||||
|
*
|
||||||
|
* This file is subject to the terms and conditions of the GNU Lesser
|
||||||
|
* General Public License v2.1. See the file LICENSE in the top level
|
||||||
|
* directory for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <mips/m32c0.h>
|
||||||
|
#include <mips/regdef.h>
|
||||||
|
#include <mips/asm.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "periph/uart.h"
|
||||||
|
#include "periph/timer.h"
|
||||||
|
#include "arch/panic_arch.h"
|
||||||
|
#include "kernel_init.h"
|
||||||
|
#include "cpu.h"
|
||||||
|
#include "board.h"
|
||||||
|
|
||||||
|
void mips_start(void);
|
||||||
|
|
||||||
|
extern void _fini(void);
|
||||||
|
extern void atexit(void (*)(void));
|
||||||
|
extern void _init(void);
|
||||||
|
extern void exit(int);
|
||||||
|
|
||||||
|
#ifdef FLASH_XIP
|
||||||
|
extern char _rom_data_copy __attribute__((section("data")));
|
||||||
|
extern char _fdata __attribute__((section("data")));
|
||||||
|
extern char _edata __attribute__((section("data")));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note the mips toolchain crt expects to jump to main but RIOT wants the user
|
||||||
|
* code to start at main for some perverse reason, but thankfully the crt
|
||||||
|
* does provide this hook function which gets called fairly close to the jump
|
||||||
|
* to main, thus if we finish off the job of the crt here and never returns
|
||||||
|
* we can support this madness.
|
||||||
|
*/
|
||||||
|
void software_init_hook(void)
|
||||||
|
{
|
||||||
|
#ifdef FLASH_XIP
|
||||||
|
/* copy initialised data from its LMA to VMA */
|
||||||
|
memcpy(&_fdata, &_rom_data_copy, (int)&_edata - (int)&_fdata);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
atexit(_fini);
|
||||||
|
_init();
|
||||||
|
|
||||||
|
mips_start();
|
||||||
|
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void mips_start(void)
|
||||||
|
{
|
||||||
|
board_init();
|
||||||
|
|
||||||
|
#if MODULE_NEWLIB
|
||||||
|
#error "This Port is designed to work with the (newlib) C library provided with the mips sdk toolchain"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* kernel_init */
|
||||||
|
kernel_init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void panic_arch(void)
|
||||||
|
{
|
||||||
|
printf("\nPANIC!\n");
|
||||||
|
assert(0);
|
||||||
|
while (1) {
|
||||||
|
}
|
||||||
|
}
|
||||||
48
cpu/mips32r2_common/include/cpu.h
Normal file
48
cpu/mips32r2_common/include/cpu.h
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016, Imagination Technologies Limited and/or its
|
||||||
|
* affiliated group companies.
|
||||||
|
* This file is subject to the terms and conditions of the GNU Lesser
|
||||||
|
* General Public License v2.1. See the file LICENSE in the top level
|
||||||
|
* directory for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup cpu_mips32r2_commom MIPS32R2 Common
|
||||||
|
* @ingroup cpu
|
||||||
|
* @brief Common implementations and headers for mips32r2 compliant devices
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief Common implementations and headers for mips32r2 compliant devices
|
||||||
|
*
|
||||||
|
* @author Neil Jones <neil.jones@imgtec.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CPU_H_
|
||||||
|
#define CPU_H_
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
#include "irq.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Print the last instruction's address
|
||||||
|
*
|
||||||
|
* @todo: Not supported
|
||||||
|
*/
|
||||||
|
static inline void cpu_print_last_instruction(void)
|
||||||
|
{
|
||||||
|
/* This function must exist else RIOT won't compile */
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
/** @} */
|
||||||
70
cpu/mips32r2_common/include/cpu_conf.h
Normal file
70
cpu/mips32r2_common/include/cpu_conf.h
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016, Imagination Technologies Limited and/or its
|
||||||
|
* affiliated group companies.
|
||||||
|
* This file is subject to the terms and conditions of the GNU Lesser
|
||||||
|
* General Public License v2.1. See the file LICENSE in the top level
|
||||||
|
* directory for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _CPU_CONF_H_
|
||||||
|
#define _CPU_CONF_H_
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup cpu_mips32r2_commom MIPS32R2 Common
|
||||||
|
* @ingroup cpu
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief Common CPU definitions for mip32r2 compatable devices.
|
||||||
|
*
|
||||||
|
* @author Neil Jones <neil.jones@imgtec.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Configuration of default stack sizes
|
||||||
|
*
|
||||||
|
* printf takes a pretty tortured route through the C lib
|
||||||
|
* then via UHI syscall exception to end up at the UART
|
||||||
|
* driver.
|
||||||
|
*
|
||||||
|
* When debugging timer code we get printfs on the idle threads
|
||||||
|
* stack which can easily blow its limits.
|
||||||
|
*
|
||||||
|
* Note code must be compiled at -Os with these values, using -O0
|
||||||
|
* you'll overflow these stacks.
|
||||||
|
*
|
||||||
|
* NO ISR stack is in use yet, interrupt use the current running stack
|
||||||
|
* hence the big-ish default stack size.
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef THREAD_EXTRA_STACKSIZE_PRINTF
|
||||||
|
#define THREAD_EXTRA_STACKSIZE_PRINTF (1024)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef THREAD_STACKSIZE_DEFAULT
|
||||||
|
#define THREAD_STACKSIZE_DEFAULT (2048)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef THREAD_STACKSIZE_IDLE
|
||||||
|
#ifdef NDEBUG
|
||||||
|
#define THREAD_STACKSIZE_IDLE (512)
|
||||||
|
#else
|
||||||
|
#define THREAD_STACKSIZE_IDLE (512 + THREAD_EXTRA_STACKSIZE_PRINTF)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ISR_STACKSIZE (0)
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
/** @} */
|
||||||
25
cpu/mips32r2_common/include/periph_cpu.h
Normal file
25
cpu/mips32r2_common/include/periph_cpu.h
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016, Imagination Technologies Limited and/or its
|
||||||
|
* affiliated group companies.
|
||||||
|
* This file is subject to the terms and conditions of the GNU Lesser
|
||||||
|
* General Public License v2.1. See the file LICENSE in the top level
|
||||||
|
* directory for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* This file must exist to get timer code to build */
|
||||||
|
|
||||||
|
/* No peripherals I/O via JTAG or Bootloader using UHI */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note mips32r2_common can be selected in its own right as a CPU
|
||||||
|
* for testing on PFGA systems (like BOARD=mips-malta) with limited
|
||||||
|
* or no peripherals
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
42
cpu/mips32r2_common/irq_arch.c
Normal file
42
cpu/mips32r2_common/irq_arch.c
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016, Imagination Technologies Limited and/or its
|
||||||
|
* affiliated group companies.
|
||||||
|
* This file is subject to the terms and conditions of the GNU Lesser
|
||||||
|
* General Public License v2.1. See the file LICENSE in the top level
|
||||||
|
* directory for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <mips/m32c0.h>
|
||||||
|
#include "arch/irq_arch.h"
|
||||||
|
|
||||||
|
|
||||||
|
unsigned int irq_arch_enable(void)
|
||||||
|
{
|
||||||
|
unsigned int status;
|
||||||
|
|
||||||
|
__asm__ volatile ("ei %0" : "=r" (status));
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int irq_arch_disable(void)
|
||||||
|
{
|
||||||
|
unsigned int status;
|
||||||
|
|
||||||
|
__asm__ volatile ("di %0" : "=r" (status));
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
void irq_arch_restore(unsigned int state)
|
||||||
|
{
|
||||||
|
if (state & SR_IE) {
|
||||||
|
mips32_bs_c0(C0_STATUS, SR_IE);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
mips32_bc_c0(C0_STATUS, SR_IE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int irq_arch_in(void)
|
||||||
|
{
|
||||||
|
return (mips32_get_c0(C0_STATUS) & SR_EXL) != 0;
|
||||||
|
}
|
||||||
151
cpu/mips32r2_common/mips_dsp.S
Normal file
151
cpu/mips32r2_common/mips_dsp.S
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016, Imagination Technologies Limited and/or its
|
||||||
|
* affiliated group companies.
|
||||||
|
* 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 copyright holder 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* ************ PLEASE READ ME !!!! ****************
|
||||||
|
|
||||||
|
This file is missing from $MIPS_ELF_ROOT/share/mips/hal
|
||||||
|
|
||||||
|
Future toolchain versions will have this file included and this local copy will
|
||||||
|
be no longer needed.
|
||||||
|
|
||||||
|
Note the above copyright/license is 3 Clause BSD and as such is compatible with LGPLv2.1
|
||||||
|
as such we grant licensing this file under LGPLv2.1 (See the file LICENSE in the top level
|
||||||
|
directory for more details) as well.
|
||||||
|
|
||||||
|
Thanks for reading.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.set nomips16
|
||||||
|
#include <mips/asm.h>
|
||||||
|
#include <mips/regdef.h>
|
||||||
|
#include <mips/m32c0.h>
|
||||||
|
#include <mips/hal.h>
|
||||||
|
#include <mips/endian.h>
|
||||||
|
|
||||||
|
#
|
||||||
|
# FUNCTION: _dsp_save
|
||||||
|
#
|
||||||
|
# DESCRIPTION: save the DSP context.
|
||||||
|
#
|
||||||
|
# RETURNS: int
|
||||||
|
#
|
||||||
|
# 0: No context saved
|
||||||
|
# CTX_*: Type of conext stored
|
||||||
|
#
|
||||||
|
LEAF(_dsp_save)
|
||||||
|
PTR_S zero, LINKCTX_NEXT(a0)
|
||||||
|
move v0, zero
|
||||||
|
|
||||||
|
# Test for DSP support
|
||||||
|
mfc0 t0, C0_CONFIG3
|
||||||
|
ext t0, t0, CFG3_DSPP_SHIFT, 1
|
||||||
|
beqz t0, 1f
|
||||||
|
|
||||||
|
# Test for DSP enabled
|
||||||
|
mfc0 t0, C0_STATUS
|
||||||
|
ext t0, t0, SR_MX_SHIFT, 1
|
||||||
|
beqz t0, 1f
|
||||||
|
|
||||||
|
lui v0, %hi(LINKCTX_TYPE_DSP)
|
||||||
|
addiu v0, v0, %lo(LINKCTX_TYPE_DSP)
|
||||||
|
.set push
|
||||||
|
.set dsp
|
||||||
|
rddsp t1
|
||||||
|
mfhi t2, $ac1
|
||||||
|
mflo t3, $ac1
|
||||||
|
mfhi t4, $ac2
|
||||||
|
mflo t5, $ac2
|
||||||
|
mfhi t6, $ac3
|
||||||
|
mflo t7, $ac3
|
||||||
|
.set pop
|
||||||
|
sw t1, DSPCTX_DSPC(a0)
|
||||||
|
sw t2, DSPCTX_HI1(a0)
|
||||||
|
sw t3, DSPCTX_LO1(a0)
|
||||||
|
sw t4, DSPCTX_HI2(a0)
|
||||||
|
sw t5, DSPCTX_LO2(a0)
|
||||||
|
sw t6, DSPCTX_HI3(a0)
|
||||||
|
sw t7, DSPCTX_LO3(a0)
|
||||||
|
REG_S v0, LINKCTX_ID(a0)
|
||||||
|
1:
|
||||||
|
jr ra
|
||||||
|
END(_dsp_save)
|
||||||
|
|
||||||
|
#
|
||||||
|
# FUNCTION: _dsp_load
|
||||||
|
#
|
||||||
|
# DESCRIPTION: load the DSP context.
|
||||||
|
#
|
||||||
|
# RETURNS: int
|
||||||
|
#
|
||||||
|
# 0: Unrecognised context
|
||||||
|
# CTX_*: Type of context restored
|
||||||
|
#
|
||||||
|
LEAF(_dsp_load)
|
||||||
|
REG_L v0, LINKCTX_ID(a0)
|
||||||
|
lui v1, %hi(LINKCTX_TYPE_DSP)
|
||||||
|
addiu v1, v1, %lo(LINKCTX_TYPE_DSP)
|
||||||
|
bne v0,v1,1f
|
||||||
|
|
||||||
|
# Test for DSP support
|
||||||
|
mfc0 t0, C0_CONFIG3
|
||||||
|
ext t0, t0, CFG3_DSPP_SHIFT, 1
|
||||||
|
beqz t0, 1f
|
||||||
|
|
||||||
|
# Force on DSP
|
||||||
|
di t3
|
||||||
|
ehb
|
||||||
|
or t3, t3, SR_MX
|
||||||
|
mtc0 t3, C0_STATUS
|
||||||
|
ehb
|
||||||
|
|
||||||
|
lw t1, DSPCTX_DSPC(a0)
|
||||||
|
lw t2, DSPCTX_HI1(a0)
|
||||||
|
lw t3, DSPCTX_LO1(a0)
|
||||||
|
lw t4, DSPCTX_HI2(a0)
|
||||||
|
lw t5, DSPCTX_LO2(a0)
|
||||||
|
lw t6, DSPCTX_HI3(a0)
|
||||||
|
lw t7, DSPCTX_LO3(a0)
|
||||||
|
.set push
|
||||||
|
.set dsp
|
||||||
|
wrdsp t1
|
||||||
|
mthi t2, $ac1
|
||||||
|
mtlo t3, $ac1
|
||||||
|
mthi t4, $ac2
|
||||||
|
mtlo t5, $ac2
|
||||||
|
mthi t6, $ac3
|
||||||
|
mtlo t7, $ac3
|
||||||
|
.set pop
|
||||||
|
jr ra
|
||||||
|
1:
|
||||||
|
# Don't recognise this context, fail
|
||||||
|
move v0, zero
|
||||||
|
jr ra
|
||||||
|
END(_dsp_load)
|
||||||
288
cpu/mips32r2_common/mips_excpt_entry.S
Normal file
288
cpu/mips32r2_common/mips_excpt_entry.S
Normal file
@ -0,0 +1,288 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2014-2015, Imagination Technologies Limited and/or its
|
||||||
|
* affiliated group companies.
|
||||||
|
* 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 copyright holder 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* ************ PLEASE READ ME !!!! ****************
|
||||||
|
|
||||||
|
This file is a copy of the mips_excpt_entry.S from $MIPS_ELF_ROOT/share/mips/hal
|
||||||
|
(from the 2016.05-03 version) with a single modification, we add a global flag
|
||||||
|
'__exception_restore' so we can jump to the restore code sequence from C.
|
||||||
|
|
||||||
|
Future toolchain versions will have this change included and this file will
|
||||||
|
be no longer needed.
|
||||||
|
|
||||||
|
Note the above copyright/license is 3 Clause BSD and as such is compatible with LGPLv2.1
|
||||||
|
as such we grant licensing this file under LGPLv2.1 (See the file LICENSE in the top level
|
||||||
|
directory for more details) as well.
|
||||||
|
|
||||||
|
Thanks for reading.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
# Keep each function in a separate named section
|
||||||
|
#define _FUNCTION_SECTIONS_
|
||||||
|
.set nomips16
|
||||||
|
|
||||||
|
#include <mips/asm.h>
|
||||||
|
#include <mips/regdef.h>
|
||||||
|
#include <mips/cpu.h>
|
||||||
|
#include <mips/hal.h>
|
||||||
|
|
||||||
|
# Context size, adjusted for ABI parameter area
|
||||||
|
#define ADJ (NARGSAVE * SZARG)
|
||||||
|
# Round up to 16-byte boundary (maximum stack alignment required for any
|
||||||
|
# supported ABI)
|
||||||
|
#define CTX_SIZEROUND ((CTX_SIZE + ALSZ) & ALMASK)
|
||||||
|
#define CTX_SIZEADJ (CTX_SIZEROUND + ADJ)
|
||||||
|
|
||||||
|
#define e_ISR s1
|
||||||
|
#define e_CR s3
|
||||||
|
#define e_BADV s4
|
||||||
|
#define e_SR s5
|
||||||
|
#define e_EPC s6
|
||||||
|
#define e_RA s7
|
||||||
|
|
||||||
|
# DESCRIPTION: Exception entry point. This is small because it must go at
|
||||||
|
# EBASE+0x180. It saves enough context to chain onwards to
|
||||||
|
# __exception_save.
|
||||||
|
#
|
||||||
|
LEAF(__exception_entry)
|
||||||
|
.set push
|
||||||
|
.set noat
|
||||||
|
.weak _mips_tlb_refill
|
||||||
|
_mips_tlb_refill = __exception_save
|
||||||
|
__tlb_refill_loop:
|
||||||
|
# Support an alternative entry point at the start of the exception
|
||||||
|
# vector. Since the exception vector is normally placed first
|
||||||
|
# in the link map this allows a user to start execution from the
|
||||||
|
# same address that an executable is loaded to.
|
||||||
|
LA k1, __first_boot
|
||||||
|
lw k1, 0(k1)
|
||||||
|
beqz k1, 1f
|
||||||
|
# The start code is responsible for clearing __first_boot prior
|
||||||
|
# to installing the exception handlers.
|
||||||
|
j _start
|
||||||
|
1:
|
||||||
|
LA k1, _mips_tlb_refill
|
||||||
|
beqz k1, __tlb_refill_loop
|
||||||
|
jr k1
|
||||||
|
|
||||||
|
.org 0x80
|
||||||
|
.weak _mips_xtlb_refill
|
||||||
|
_mips_xtlb_refill = __exception_save
|
||||||
|
__xtlb_refill_loop:
|
||||||
|
LA k1, _mips_xtlb_refill
|
||||||
|
beqz k1, __xtlb_refill_loop
|
||||||
|
jr k1
|
||||||
|
|
||||||
|
.org 0x100
|
||||||
|
.weak _mips_cache_error
|
||||||
|
__cache_error_loop:
|
||||||
|
LA k1, _mips_cache_error
|
||||||
|
beqz k1, __cache_error_loop
|
||||||
|
jr k1
|
||||||
|
|
||||||
|
.org 0x180
|
||||||
|
# Free up k1, defering sp adjustment until later
|
||||||
|
REG_S k1, (-CTX_SIZEROUND + CTX_K1)(sp)
|
||||||
|
|
||||||
|
# Use k1 to invoke __exception_save
|
||||||
|
LA k1, _mips_general_exception
|
||||||
|
jr k1
|
||||||
|
.set pop
|
||||||
|
END(__exception_entry)
|
||||||
|
|
||||||
|
#
|
||||||
|
# FUNCTION: __exception_save
|
||||||
|
#
|
||||||
|
# DESCRIPTION: Exception context save. Save the context, then fake up a call
|
||||||
|
# frame.
|
||||||
|
#
|
||||||
|
ANESTED(__exception_save, _mips_general_exception, CTX_SIZEADJ, zero)
|
||||||
|
.globl __exception_save;
|
||||||
|
.globl __exception_restore;
|
||||||
|
.set push
|
||||||
|
.set noat
|
||||||
|
|
||||||
|
# k1 is already saved, so use it to save the users sp
|
||||||
|
move k1, sp
|
||||||
|
# Finally adjust sp
|
||||||
|
PTR_ADDU sp, sp, -CTX_SIZEADJ # This should be picked up by the backtracer
|
||||||
|
|
||||||
|
# Save context
|
||||||
|
REG_S $1, CTX_REG(1) + ADJ(sp)
|
||||||
|
REG_S $2, CTX_REG(2) + ADJ(sp)
|
||||||
|
REG_S $3, CTX_REG(3) + ADJ(sp)
|
||||||
|
REG_S $4, CTX_REG(4) + ADJ(sp)
|
||||||
|
REG_S $5, CTX_REG(5) + ADJ(sp)
|
||||||
|
REG_S $6, CTX_REG(6) + ADJ(sp)
|
||||||
|
REG_S $7, CTX_REG(7) + ADJ(sp)
|
||||||
|
REG_S $8, CTX_REG(8) + ADJ(sp)
|
||||||
|
REG_S $9, CTX_REG(9) + ADJ(sp)
|
||||||
|
REG_S $10, CTX_REG(10) + ADJ(sp)
|
||||||
|
REG_S $11, CTX_REG(11) + ADJ(sp)
|
||||||
|
REG_S $12, CTX_REG(12) + ADJ(sp)
|
||||||
|
REG_S $13, CTX_REG(13) + ADJ(sp)
|
||||||
|
REG_S $14, CTX_REG(14) + ADJ(sp)
|
||||||
|
REG_S $15, CTX_REG(15) + ADJ(sp)
|
||||||
|
REG_S $16, CTX_REG(16) + ADJ(sp)
|
||||||
|
REG_S $17, CTX_REG(17) + ADJ(sp)
|
||||||
|
REG_S $18, CTX_REG(18) + ADJ(sp)
|
||||||
|
REG_S $19, CTX_REG(19) + ADJ(sp)
|
||||||
|
REG_S $20, CTX_REG(20) + ADJ(sp)
|
||||||
|
REG_S $21, CTX_REG(21) + ADJ(sp)
|
||||||
|
REG_S $22, CTX_REG(22) + ADJ(sp)
|
||||||
|
REG_S $23, CTX_REG(23) + ADJ(sp)
|
||||||
|
REG_S $24, CTX_REG(24) + ADJ(sp)
|
||||||
|
REG_S $25, CTX_REG(25) + ADJ(sp)
|
||||||
|
REG_S $26, CTX_REG(26) + ADJ(sp)
|
||||||
|
# k1/$27 has already been saved
|
||||||
|
REG_S $28, CTX_REG(28) + ADJ(sp)
|
||||||
|
REG_S k1, CTX_REG(29) + ADJ(sp) # Use saved sp from earlier
|
||||||
|
REG_S $30, CTX_REG(30) + ADJ(sp)
|
||||||
|
REG_S $31, CTX_REG(31) + ADJ(sp)
|
||||||
|
PTR_S $0, CTX_LINK + ADJ(sp) # Clear the link field
|
||||||
|
|
||||||
|
#if (__mips_isa_rev < 6)
|
||||||
|
mfhi $9
|
||||||
|
mflo $10
|
||||||
|
REG_S $9, CTX_HI0 + ADJ(sp)
|
||||||
|
REG_S $10, CTX_LO0 + ADJ(sp)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
# Trick the backtracer into stepping back to the point where the exception
|
||||||
|
# occurred.
|
||||||
|
PTR_MFC0 ra, C0_EPC
|
||||||
|
mfc0 e_CR, C0_CR
|
||||||
|
REG_S ra, CTX_EPC + ADJ(sp)
|
||||||
|
|
||||||
|
# Finish storing the rest of the CP0 registers
|
||||||
|
PTR_MFC0 $9, C0_BADVADDR
|
||||||
|
REG_S $9, CTX_BADVADDR + ADJ(sp)
|
||||||
|
sw e_CR, CTX_CAUSE + ADJ(sp)
|
||||||
|
|
||||||
|
move $11, $0
|
||||||
|
move $12, $0
|
||||||
|
mfc0 $9, C0_CONFIG3
|
||||||
|
ext $10, $9, CFG3_BP_SHIFT, 1
|
||||||
|
beqz $10, 1f
|
||||||
|
mfc0 $11, C0_BADPINSTR
|
||||||
|
1:
|
||||||
|
ext $9, $9, CFG3_BI_SHIFT, 1
|
||||||
|
beqz $9, 1f
|
||||||
|
mfc0 $12, C0_BADINSTR
|
||||||
|
1:
|
||||||
|
sw $11, CTX_BADPINSTR + ADJ(sp)
|
||||||
|
sw $12, CTX_BADINSTR + ADJ(sp)
|
||||||
|
|
||||||
|
# Start computing the address of the context for a0
|
||||||
|
move a0, sp
|
||||||
|
|
||||||
|
# Clear EXL. Exceptions can now nest.
|
||||||
|
mfc0 e_SR, C0_SR
|
||||||
|
sw e_SR, CTX_STATUS + ADJ(sp)
|
||||||
|
lui $9, %hi(~SR_EXL)
|
||||||
|
addiu $9, $9, %lo(~SR_EXL)
|
||||||
|
and e_SR, e_SR, $9
|
||||||
|
mtc0 e_SR, C0_SR
|
||||||
|
|
||||||
|
# Manually set up the return address to restore the context below
|
||||||
|
LA ra, __exception_restore
|
||||||
|
# Extract the cause code
|
||||||
|
and a1, e_CR, CR_XMASK
|
||||||
|
|
||||||
|
# Finish computing the address of the context for a0
|
||||||
|
addiu a0, a0, ADJ
|
||||||
|
|
||||||
|
# Shift exception number down into expected range
|
||||||
|
srl a1, a1, 2
|
||||||
|
|
||||||
|
# Call the handler, indirect through t9 albeit not for any specific
|
||||||
|
# reason
|
||||||
|
LA t9, _mips_handle_exception
|
||||||
|
jr t9
|
||||||
|
|
||||||
|
# Return point from handler
|
||||||
|
# Load context
|
||||||
|
# now a function on its own, note save code just falls through.
|
||||||
|
|
||||||
|
|
||||||
|
__exception_restore:
|
||||||
|
|
||||||
|
#if (__mips_isa_rev < 6)
|
||||||
|
REG_L $9, CTX_HI0 + ADJ(sp)
|
||||||
|
REG_L $10, CTX_LO0 + ADJ(sp)
|
||||||
|
mthi $9
|
||||||
|
mtlo $10
|
||||||
|
#endif
|
||||||
|
|
||||||
|
REG_L $1, CTX_REG(1) + ADJ(sp)
|
||||||
|
REG_L $2, CTX_REG(2) + ADJ(sp)
|
||||||
|
REG_L $3, CTX_REG(3) + ADJ(sp)
|
||||||
|
REG_L $4, CTX_REG(4) + ADJ(sp)
|
||||||
|
REG_L $5, CTX_REG(5) + ADJ(sp)
|
||||||
|
REG_L $6, CTX_REG(6) + ADJ(sp)
|
||||||
|
REG_L $7, CTX_REG(7) + ADJ(sp)
|
||||||
|
REG_L $8, CTX_REG(8) + ADJ(sp)
|
||||||
|
REG_L $9, CTX_REG(9) + ADJ(sp)
|
||||||
|
REG_L $10, CTX_REG(10) + ADJ(sp)
|
||||||
|
REG_L $11, CTX_REG(11) + ADJ(sp)
|
||||||
|
REG_L $12, CTX_REG(12) + ADJ(sp)
|
||||||
|
REG_L $13, CTX_REG(13) + ADJ(sp)
|
||||||
|
REG_L $14, CTX_REG(14) + ADJ(sp)
|
||||||
|
REG_L $15, CTX_REG(15) + ADJ(sp)
|
||||||
|
REG_L $16, CTX_REG(16) + ADJ(sp)
|
||||||
|
REG_L $17, CTX_REG(17) + ADJ(sp)
|
||||||
|
REG_L $18, CTX_REG(18) + ADJ(sp)
|
||||||
|
REG_L $19, CTX_REG(19) + ADJ(sp)
|
||||||
|
REG_L $20, CTX_REG(20) + ADJ(sp)
|
||||||
|
REG_L $21, CTX_REG(21) + ADJ(sp)
|
||||||
|
REG_L $22, CTX_REG(22) + ADJ(sp)
|
||||||
|
REG_L $23, CTX_REG(23) + ADJ(sp)
|
||||||
|
REG_L $24, CTX_REG(24) + ADJ(sp)
|
||||||
|
REG_L $25, CTX_REG(25) + ADJ(sp)
|
||||||
|
# $26/K0 and $27/K1 are restored with interrupts disabled
|
||||||
|
REG_L $28, CTX_REG(28) + ADJ(sp)
|
||||||
|
# $29/SP is restored last
|
||||||
|
REG_L $30, CTX_REG(30) + ADJ(sp)
|
||||||
|
REG_L $31, CTX_REG(31) + ADJ(sp)
|
||||||
|
di
|
||||||
|
lw k0, CTX_STATUS + ADJ(sp)
|
||||||
|
REG_L k1, CTX_EPC + ADJ(sp)
|
||||||
|
mtc0 k0, C0_SR
|
||||||
|
PTR_MTC0 k1, C0_EPC
|
||||||
|
ehb
|
||||||
|
REG_L k0, CTX_K0 + ADJ(sp)
|
||||||
|
REG_L k1, CTX_K1 + ADJ(sp)
|
||||||
|
REG_L sp, CTX_SP + ADJ(sp)
|
||||||
|
# Return from exception
|
||||||
|
eret
|
||||||
|
.set pop
|
||||||
|
END(__exception_save)
|
||||||
3
cpu/mips32r2_common/periph/Makefile
Normal file
3
cpu/mips32r2_common/periph/Makefile
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
MODULE = periph
|
||||||
|
|
||||||
|
include $(RIOTBASE)/Makefile.base
|
||||||
37
cpu/mips32r2_common/periph/pm.c
Normal file
37
cpu/mips32r2_common/periph/pm.c
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016, Imagination Technologies Limited and/or its
|
||||||
|
* affiliated group companies.
|
||||||
|
* This file is subject to the terms and conditions of the GNU Lesser
|
||||||
|
* General Public License v2.1. See the file LICENSE in the top level
|
||||||
|
* directory for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup cpu_mips32r2_common
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief common periph/pm functions
|
||||||
|
*
|
||||||
|
* @author Neil Jones <neil.jones@imgtec.com>
|
||||||
|
*
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <mips/m32c0.h>
|
||||||
|
#include "periph/pm.h"
|
||||||
|
|
||||||
|
#ifndef FEATURES_PERIPH_PM
|
||||||
|
void pm_set_lowest(void)
|
||||||
|
{
|
||||||
|
/* Dont wait if interrupts are not enabled - we would never return!*/
|
||||||
|
if (mips32_get_c0(C0_STATUS) & SR_IE) {
|
||||||
|
__asm volatile ("wait");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void pm_off(void)
|
||||||
|
{
|
||||||
|
/* No Generic Power off Mechanism */
|
||||||
|
}
|
||||||
217
cpu/mips32r2_common/periph/timer.c
Normal file
217
cpu/mips32r2_common/periph/timer.c
Normal file
@ -0,0 +1,217 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016, Imagination Technologies Limited and/or its
|
||||||
|
* affiliated group companies.
|
||||||
|
* This file is subject to the terms and conditions of the GNU Lesser
|
||||||
|
* General Public License v2.1. See the file LICENSE in the top level
|
||||||
|
* directory for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <mips/cpu.h>
|
||||||
|
#include <mips/m32c0.h>
|
||||||
|
#include <mips/regdef.h>
|
||||||
|
#include <mips/asm.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <periph/timer.h>
|
||||||
|
#include "cpu_conf.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "sched.h"
|
||||||
|
#include "thread.h"
|
||||||
|
#include "board.h"
|
||||||
|
#include "irq.h"
|
||||||
|
#include "timex.h"
|
||||||
|
#include "div.h"
|
||||||
|
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* setting TIMER_ACCURACY_SHIFT lower will improve accuracy
|
||||||
|
* at the cost of more regular interrupts (hence less power efficient).
|
||||||
|
* */
|
||||||
|
#define TIMER_ACCURACY_SHIFT (10)
|
||||||
|
#define TIMER_ACCURACY (1 << TIMER_ACCURACY_SHIFT)
|
||||||
|
#define CHANNELS (3)
|
||||||
|
|
||||||
|
/* TICKS_PER_US must be set in the board file */
|
||||||
|
#ifndef TICKS_PER_US
|
||||||
|
#error "Please set TICK_PER_US in your board file"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The base MIPS count / compare timer is fixed frequency at core clock / 2
|
||||||
|
* and is pretty basic This timer is currently only supported in Vectored
|
||||||
|
* Interrupt Mode (VI), EIC mode is not supported yet.
|
||||||
|
*
|
||||||
|
* RIOT's xtimer expects the timer to operate at 1MHZ or any 2^n multiple or
|
||||||
|
* factor of this, thus we maintain a software timer which counts at 1MHz.
|
||||||
|
* This is not particularly power efficient and may add latency too.
|
||||||
|
*
|
||||||
|
* If other SoC specific timers are available which are more flexible then
|
||||||
|
* it is advised to use them, this timer is a fallback version
|
||||||
|
* that should work on all MIPS implementations.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
static timer_isr_ctx_t timer_isr_ctx;
|
||||||
|
volatile unsigned int counter;
|
||||||
|
volatile unsigned int compares[CHANNELS];
|
||||||
|
static volatile int spurious_int;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The mips toolchain C library does not implement gettimeofday()
|
||||||
|
*
|
||||||
|
* implement it here using the timer.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int gettimeofday(struct timeval *__restrict __p, void *__restrict __tz)
|
||||||
|
{
|
||||||
|
uint64_t now = counter * US_PER_MS;
|
||||||
|
__p->tv_sec = div_u64_by_1000000(now);
|
||||||
|
__p->tv_usec = now - (__p->tv_sec * US_PER_SEC);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int timer_init(tim_t dev, unsigned long freq, timer_cb_t cb, void *arg)
|
||||||
|
{
|
||||||
|
assert(dev == 0);
|
||||||
|
|
||||||
|
(void)freq; /*Cannot adjust Frequency */
|
||||||
|
|
||||||
|
timer_isr_ctx.cb = cb;
|
||||||
|
timer_isr_ctx.arg = arg;
|
||||||
|
|
||||||
|
/* Clear down soft counters */
|
||||||
|
memset((void *)compares, 0, sizeof(compares));
|
||||||
|
|
||||||
|
counter = (1 << TIMER_ACCURACY_SHIFT);
|
||||||
|
|
||||||
|
/* Set compare up */
|
||||||
|
mips_setcompare(mips_getcount() + TICKS_PER_US * TIMER_ACCURACY);
|
||||||
|
|
||||||
|
/* Start the timer if stopped */
|
||||||
|
mips32_bc_c0(C0_CAUSE, CR_DC);
|
||||||
|
|
||||||
|
/* Enable Timer Interrupts */
|
||||||
|
mips32_bs_c0(C0_STATUS, SR_HINT5);
|
||||||
|
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int timer_set(tim_t dev, int channel, unsigned int timeout)
|
||||||
|
{
|
||||||
|
assert(dev == 0);
|
||||||
|
assert(channel < CHANNELS);
|
||||||
|
|
||||||
|
timeout >>= TIMER_ACCURACY_SHIFT;
|
||||||
|
timeout <<= TIMER_ACCURACY_SHIFT;
|
||||||
|
|
||||||
|
uint32_t status = irq_arch_disable();
|
||||||
|
compares[channel] = counter + timeout;
|
||||||
|
irq_arch_restore(status);
|
||||||
|
|
||||||
|
return channel;
|
||||||
|
}
|
||||||
|
|
||||||
|
int timer_set_absolute(tim_t dev, int channel, unsigned int value)
|
||||||
|
{
|
||||||
|
assert(dev == 0);
|
||||||
|
assert(channel < CHANNELS);
|
||||||
|
|
||||||
|
value >>= TIMER_ACCURACY_SHIFT;
|
||||||
|
value <<= TIMER_ACCURACY_SHIFT;
|
||||||
|
|
||||||
|
uint32_t status = irq_arch_disable();
|
||||||
|
compares[channel] = value;
|
||||||
|
irq_arch_restore(status);
|
||||||
|
|
||||||
|
return channel;
|
||||||
|
}
|
||||||
|
|
||||||
|
int timer_clear(tim_t dev, int channel)
|
||||||
|
{
|
||||||
|
assert(dev == 0);
|
||||||
|
assert(channel < CHANNELS);
|
||||||
|
|
||||||
|
uint32_t status = irq_arch_disable();
|
||||||
|
compares[channel] = 0;
|
||||||
|
irq_arch_restore(status);
|
||||||
|
|
||||||
|
return channel;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int timer_read(tim_t dev)
|
||||||
|
{
|
||||||
|
assert(dev == 0);
|
||||||
|
|
||||||
|
return counter;
|
||||||
|
}
|
||||||
|
|
||||||
|
void timer_start(tim_t dev)
|
||||||
|
{
|
||||||
|
mips32_bc_c0(C0_CAUSE, CR_DC);
|
||||||
|
}
|
||||||
|
|
||||||
|
void timer_stop(tim_t dev)
|
||||||
|
{
|
||||||
|
mips32_bs_c0(C0_CAUSE, CR_DC);
|
||||||
|
}
|
||||||
|
|
||||||
|
void timer_irq_enable(tim_t dev)
|
||||||
|
{
|
||||||
|
mips32_bs_c0(C0_STATUS, SR_HINT5);
|
||||||
|
}
|
||||||
|
|
||||||
|
void timer_irq_disable(tim_t dev)
|
||||||
|
{
|
||||||
|
mips32_bc_c0(C0_STATUS, SR_HINT5);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void __attribute__ ((interrupt("vector=hw5"))) _mips_isr_hw5(void)
|
||||||
|
{
|
||||||
|
register int cr = mips_getcr();
|
||||||
|
|
||||||
|
if (cr & CR_TI) {
|
||||||
|
uint32_t status = irq_arch_disable();
|
||||||
|
counter += TIMER_ACCURACY;
|
||||||
|
irq_arch_restore(status);
|
||||||
|
|
||||||
|
if (counter == compares[0]) {
|
||||||
|
/*
|
||||||
|
* The Xtimer code expects the ISR to take some time
|
||||||
|
* but our counter is a fake software one, so bump it a
|
||||||
|
* bit to give the impression some time elapsed in the ISR.
|
||||||
|
* Without this the callback ( _shoot(timer) on xtimer_core.c )
|
||||||
|
* never fires.
|
||||||
|
*/
|
||||||
|
counter += TIMER_ACCURACY;
|
||||||
|
timer_isr_ctx.cb(timer_isr_ctx.arg, 0);
|
||||||
|
|
||||||
|
if (sched_context_switch_request) {
|
||||||
|
thread_yield();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (counter == compares[1]) {
|
||||||
|
timer_isr_ctx.cb(timer_isr_ctx.arg, 1);
|
||||||
|
|
||||||
|
if (sched_context_switch_request) {
|
||||||
|
thread_yield();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (counter == compares[2]) {
|
||||||
|
timer_isr_ctx.cb(timer_isr_ctx.arg, 2);
|
||||||
|
|
||||||
|
if (sched_context_switch_request) {
|
||||||
|
thread_yield();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mips_setcompare(mips_getcount() + TICKS_PER_US * TIMER_ACCURACY);
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
spurious_int++;
|
||||||
|
}
|
||||||
|
}
|
||||||
400
cpu/mips32r2_common/thread_arch.c
Normal file
400
cpu/mips32r2_common/thread_arch.c
Normal file
@ -0,0 +1,400 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016, Imagination Technologies Limited and/or its
|
||||||
|
* affiliated group companies.
|
||||||
|
*
|
||||||
|
* This file is subject to the terms and conditions of the GNU Lesser
|
||||||
|
* General Public License v2.1. See the file LICENSE in the top level
|
||||||
|
* directory for more details.
|
||||||
|
*/
|
||||||
|
#include <mips/cpu.h>
|
||||||
|
#include <mips/hal.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "thread.h"
|
||||||
|
#include "cpu.h"
|
||||||
|
#include "irq.h"
|
||||||
|
#include "cpu_conf.h"
|
||||||
|
#include "periph_conf.h" /* for debug uart number */
|
||||||
|
#include "periph/uart.h"
|
||||||
|
#include "malloc.h"
|
||||||
|
|
||||||
|
#define STACK_END_PAINT (0xdeadc0de)
|
||||||
|
#define C0_STATUS_EXL (2)
|
||||||
|
#define PADDING (16)
|
||||||
|
#define MICROMIPS_ISA_MODE (1)
|
||||||
|
#define M32_SYSCALL (0xC)
|
||||||
|
#define M32_SYSCALL_MASK (0xfc00003f)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* note the major 16bits of a 32bit MicroMIPS opcode appear first in the
|
||||||
|
* instruction stream
|
||||||
|
*/
|
||||||
|
#define MM_SYSCALL (0x8B7C0000)
|
||||||
|
#define MM_SYSCALL_MASK (0xfffffc00)
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef MIPS_HARD_FLOAT
|
||||||
|
/* pointer to the current and old fpu context for lazy context switching */
|
||||||
|
static struct fp64ctx *currentfpctx; /* fpu context of current running task */
|
||||||
|
static struct fp64ctx *oldfpctx; /* fpu context of last task that executed fpu */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Stack Layout, note struct gpctx is defined in
|
||||||
|
* $MIPS_ELF_ROOT/mips-mti-elf/include/mips/hal.h
|
||||||
|
*
|
||||||
|
* Top Of Stack
|
||||||
|
* ---------------
|
||||||
|
* | |
|
||||||
|
* | User stack |
|
||||||
|
* | |
|
||||||
|
* --------------- <--- gpctx->sp
|
||||||
|
* | |
|
||||||
|
* | gpctx |
|
||||||
|
* | |
|
||||||
|
* ---------------
|
||||||
|
* | 16 byte pad |
|
||||||
|
* --------------- <--- sched_active_thread->sp
|
||||||
|
*/
|
||||||
|
|
||||||
|
char *thread_arch_stack_init(thread_task_func_t task_func, void *arg,
|
||||||
|
void *stack_start, int stack_size)
|
||||||
|
{
|
||||||
|
/* make sure it is aligned to 8 bytes this is a requirement of the O32 ABI */
|
||||||
|
uintptr_t *p = (uintptr_t *)(((long)(stack_start) + stack_size) & ~7);
|
||||||
|
uintptr_t *fp;
|
||||||
|
|
||||||
|
/* paint */
|
||||||
|
p--;
|
||||||
|
*p-- = STACK_END_PAINT;
|
||||||
|
|
||||||
|
/* prepare stack for __exception_restore() */
|
||||||
|
fp = p;
|
||||||
|
p -= sizeof(struct gpctx) / sizeof(unsigned int);
|
||||||
|
|
||||||
|
struct gpctx *initial_ctx = (struct gpctx *)p;
|
||||||
|
initial_ctx->a[0] = (reg_t)arg;
|
||||||
|
initial_ctx->status = mips32_get_c0(C0_STATUS) | SR_IE; /* Enable interrupts */
|
||||||
|
__asm volatile ("sw $gp, 0(%0)" : : "r" (&initial_ctx->gp));
|
||||||
|
initial_ctx->epc = (reg_t)task_func;
|
||||||
|
initial_ctx->ra = (reg_t)sched_task_exit;
|
||||||
|
initial_ctx->sp = (reg_t)fp;
|
||||||
|
initial_ctx->link = (struct linkctx *)NULL;
|
||||||
|
|
||||||
|
#ifdef MIPS_MICROMIPS
|
||||||
|
initial_ctx->epc |= MICROMIPS_ISA_MODE;
|
||||||
|
initial_ctx->ra |= MICROMIPS_ISA_MODE;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MIPS_HARD_FLOAT
|
||||||
|
/*
|
||||||
|
* Disable FPU so we get an exception on first use to allow
|
||||||
|
* Lazy FPU context save and restore
|
||||||
|
*/
|
||||||
|
initial_ctx->status &= ~SR_CU1;
|
||||||
|
initial_ctx->status |= SR_FR; /*use double width FPU */
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
* note the -4 (-16 bytes) as the toolchain exception handling code
|
||||||
|
* adjusts the sp for alignment
|
||||||
|
*/
|
||||||
|
p -= PADDING/sizeof(unsigned int);
|
||||||
|
|
||||||
|
return (void *)p;
|
||||||
|
}
|
||||||
|
|
||||||
|
void thread_arch_stack_print(void)
|
||||||
|
{
|
||||||
|
uintptr_t *sp = (void *)sched_active_thread->sp;
|
||||||
|
|
||||||
|
printf("Stack trace:\n");
|
||||||
|
while (*sp != STACK_END_PAINT) {
|
||||||
|
printf(" 0x%p: 0x%08lx\n", sp, *sp);
|
||||||
|
sp++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* This function calculates the ISR_usage */
|
||||||
|
int thread_arch_isr_stack_usage(void)
|
||||||
|
{
|
||||||
|
/* TODO */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *thread_arch_isr_stack_pointer(void)
|
||||||
|
{
|
||||||
|
/* TODO */
|
||||||
|
return (void *)-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *thread_arch_isr_stack_start(void)
|
||||||
|
{
|
||||||
|
/* TODO */
|
||||||
|
return (void *)-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern void __exception_restore(void);
|
||||||
|
void thread_arch_start_threading(void)
|
||||||
|
{
|
||||||
|
unsigned int status = mips32_get_c0(C0_STATUS);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set Exception level if we are not already running at it
|
||||||
|
* the EXL mode depends on the bootloader.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ((status & C0_STATUS_EXL) == 0) {
|
||||||
|
mips32_set_c0(C0_STATUS, status | C0_STATUS_EXL);
|
||||||
|
}
|
||||||
|
|
||||||
|
sched_run();
|
||||||
|
|
||||||
|
__asm volatile ("lw $sp, 0(%0)" : : "r" (&sched_active_thread->sp));
|
||||||
|
|
||||||
|
__exception_restore();
|
||||||
|
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
void thread_arch_yield(void)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* throw a syscall exception to get into exception level
|
||||||
|
* we context switch at exception level.
|
||||||
|
*
|
||||||
|
* Note syscall 1 is reserved for UHI see:
|
||||||
|
* http://wiki.prplfoundation.org/w/images/4/42/UHI_Reference_Manual.pdf
|
||||||
|
*/
|
||||||
|
__asm volatile ("syscall 2");
|
||||||
|
}
|
||||||
|
|
||||||
|
struct linkctx* exctx_find(reg_t id, struct gpctx *gp)
|
||||||
|
{
|
||||||
|
struct linkctx **ctx = (struct linkctx **)&gp->link;
|
||||||
|
while (*ctx) {
|
||||||
|
if ((*ctx)->id == id) {
|
||||||
|
return *ctx;
|
||||||
|
}
|
||||||
|
ctx = &(*ctx)->next;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* unaligned access helper */
|
||||||
|
static inline uint32_t __attribute__((optimize("-O3")))
|
||||||
|
mem_rw(const void *vaddr)
|
||||||
|
{
|
||||||
|
uint32_t v;
|
||||||
|
memcpy(&v, vaddr, sizeof(v));
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef MIPS_DSP
|
||||||
|
extern int _dsp_save(struct dspctx *ctx);
|
||||||
|
extern int _dsp_load(struct dspctx *ctx);
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
* The nomips16 attribute should not really be needed, it works around a toolchain
|
||||||
|
* issue in 2016.05-03.
|
||||||
|
*/
|
||||||
|
void __attribute__((nomips16))
|
||||||
|
_mips_handle_exception(struct gpctx *ctx, int exception)
|
||||||
|
{
|
||||||
|
unsigned int syscall_num = 0;
|
||||||
|
#ifdef MIPS_DSP
|
||||||
|
struct dspctx dsp_ctx; /* intentionally allocated on current stack */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
switch (exception) {
|
||||||
|
|
||||||
|
case EXC_SYS:
|
||||||
|
#ifdef MIPS_MICROMIPS
|
||||||
|
/* note major 16bits of opcode is first in instruction stream */
|
||||||
|
syscall_num =
|
||||||
|
mem_rw((const void *)(ctx->epc & ~MICROMIPS_ISA_MODE))
|
||||||
|
& 0x3FF;
|
||||||
|
#else
|
||||||
|
syscall_num = (mem_rw((const void *)ctx->epc) >> 6) & 0xFFFF;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DEBUG_VIA_UART
|
||||||
|
#include <mips/uhi_syscalls.h>
|
||||||
|
/*
|
||||||
|
* intercept UHI write syscalls (printf) which would normally
|
||||||
|
* get routed to debug probe or bootloader handler and output
|
||||||
|
* via a UART
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (syscall_num == __MIPS_UHI_SYSCALL_NUM) {
|
||||||
|
if (ctx->t2[1] == __MIPS_UHI_WRITE &&
|
||||||
|
(ctx->a[0] == STDOUT_FILENO || ctx->a[0] == STDERR_FILENO)) {
|
||||||
|
uint32_t status = irq_arch_disable();
|
||||||
|
uart_write(DEBUG_VIA_UART, (uint8_t *)ctx->a[1], ctx->a[2]);
|
||||||
|
ctx->v[0] = ctx->a[2];
|
||||||
|
ctx->epc += 4; /* move PC past the syscall */
|
||||||
|
irq_arch_restore(status);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (ctx->t2[1] == __MIPS_UHI_FSTAT &&
|
||||||
|
(ctx->a[0] == STDOUT_FILENO || ctx->a[0] == STDERR_FILENO)) {
|
||||||
|
/*
|
||||||
|
* Printf fstat's the stdout/stderr file so
|
||||||
|
* fill out a minimal struct stat.
|
||||||
|
*/
|
||||||
|
struct stat *sbuf = (struct stat *)ctx->a[1];
|
||||||
|
memset(sbuf, 0, sizeof(struct stat));
|
||||||
|
sbuf->st_mode = S_IRUSR | S_IWUSR | S_IWGRP;
|
||||||
|
sbuf->st_blksize = BUFSIZ;
|
||||||
|
/* return 0 */
|
||||||
|
ctx->v[0] = 0;
|
||||||
|
ctx->epc += 4; /* move PC past the syscall */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
if (syscall_num == 2) {
|
||||||
|
unsigned int return_instruction = 0;
|
||||||
|
struct gpctx *new_ctx;
|
||||||
|
#ifdef MIPS_DSP
|
||||||
|
struct dspctx *new_dspctx;
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
* Syscall 1 is reserved for UHI.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* save the stack pointer in the thread info
|
||||||
|
* note we want the saved value to include the
|
||||||
|
* saved off context and the 16 bytes padding.
|
||||||
|
* Note we cannot use the current sp value as
|
||||||
|
* the prologue of this function has adjusted it
|
||||||
|
*/
|
||||||
|
sched_active_thread->sp = (char *)(ctx->sp
|
||||||
|
- sizeof(struct gpctx) - PADDING);
|
||||||
|
|
||||||
|
#ifdef MIPS_DSP
|
||||||
|
_dsp_save(&dsp_ctx);
|
||||||
|
_linkctx_append(ctx,&(dsp_ctx.link));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MIPS_HARD_FLOAT
|
||||||
|
if(currentfpctx) {
|
||||||
|
_linkctx_append(ctx,&(currentfpctx->fp.link));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
sched_run();
|
||||||
|
|
||||||
|
new_ctx = (struct gpctx *)((unsigned int)sched_active_thread->sp + PADDING);
|
||||||
|
|
||||||
|
#ifdef MIPS_HARD_FLOAT
|
||||||
|
currentfpctx = (struct fp64ctx *)exctx_find(LINKCTX_TYPE_FP64, new_ctx);
|
||||||
|
if(!currentfpctx) {
|
||||||
|
/* check for half-width FPU ctx in-case hardware doesn't support double. */
|
||||||
|
currentfpctx = (struct fp64ctx *)exctx_find(LINKCTX_TYPE_FP32, new_ctx);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MIPS_DSP
|
||||||
|
new_dspctx = (struct dspctx *)exctx_find(LINKCTX_TYPE_DSP, new_ctx);
|
||||||
|
if (new_dspctx)
|
||||||
|
_dsp_load(new_dspctx);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MIPS_MICROMIPS
|
||||||
|
return_instruction =
|
||||||
|
mem_rw((const void *)(new_ctx->epc & ~MICROMIPS_ISA_MODE));
|
||||||
|
if ((return_instruction & MM_SYSCALL_MASK) == MM_SYSCALL) { /* syscall */
|
||||||
|
new_ctx->epc += 4; /* move PC past the syscall */
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
return_instruction = mem_rw((const void *)new_ctx->epc);
|
||||||
|
if ((return_instruction & M32_SYSCALL_MASK) == M32_SYSCALL) { /* syscall */
|
||||||
|
new_ctx->epc += 4; /* move PC past the syscall */
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The toolchain Exception restore code just wholesale copies the
|
||||||
|
* status register from the context back to the register loosing
|
||||||
|
* any changes that may have occured, 'status' is really global state
|
||||||
|
* You dont enable interrupts on one thread and not another...
|
||||||
|
* So we just copy the current status value into the saved value
|
||||||
|
* so nothing changes on the restore
|
||||||
|
*/
|
||||||
|
|
||||||
|
new_ctx->status = mips32_get_c0(C0_STATUS);
|
||||||
|
|
||||||
|
#ifdef MIPS_HARD_FLOAT
|
||||||
|
/*
|
||||||
|
* Disable FPU so we get an exception on first use to allow
|
||||||
|
* Lazy FPU context save and restore
|
||||||
|
*/
|
||||||
|
new_ctx->status &= ~SR_CU1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
__asm volatile ("lw $sp, 0(%0)" : : "r" (&sched_active_thread->sp));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Jump straight to the exception restore code
|
||||||
|
* if we return this functions prologue messes up
|
||||||
|
* the stack pointer
|
||||||
|
*/
|
||||||
|
__exception_restore();
|
||||||
|
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#ifdef MIPS_HARD_FLOAT
|
||||||
|
case EXC_CPU:
|
||||||
|
{
|
||||||
|
int newly_allocd = false;
|
||||||
|
|
||||||
|
mips_bissr(SR_CU1);
|
||||||
|
ctx->status |= SR_CU1;
|
||||||
|
|
||||||
|
if (!currentfpctx) {
|
||||||
|
currentfpctx = malloc(sizeof(struct fp64ctx));
|
||||||
|
assert(currentfpctx);
|
||||||
|
memset(currentfpctx,0,sizeof(struct fp64ctx));
|
||||||
|
currentfpctx->fp.link.id = LINKCTX_TYPE_FP64;
|
||||||
|
newly_allocd = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* this means no one exec'd fpu since we last run */
|
||||||
|
if (oldfpctx == currentfpctx) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (oldfpctx) {
|
||||||
|
_fpctx_save(&oldfpctx->fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!newly_allocd) {
|
||||||
|
_fpctx_load(¤tfpctx->fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* next fpu exception must save our context as it's not necessarily
|
||||||
|
* the next context switch will cause fpu exception and it's very
|
||||||
|
* hard for any future task to determine which was the last one
|
||||||
|
* that performed fpu operations. so by saving this pointer now we
|
||||||
|
* give this knowledge to that future task
|
||||||
|
*/
|
||||||
|
oldfpctx = currentfpctx;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* default: */
|
||||||
|
}
|
||||||
|
/* Pass all other exceptions through to the toolchain handler */
|
||||||
|
__exception_handle(ctx, exception);
|
||||||
|
}
|
||||||
@ -14,6 +14,8 @@ BOARD_INSUFFICIENT_MEMORY := airfy-beacon cc2650stk maple-mini msb-430 msb-430h
|
|||||||
nucleo-f030 nucleo-f070 microbit calliope-mini \
|
nucleo-f030 nucleo-f070 microbit calliope-mini \
|
||||||
nucleo32-f042 nucleo32-f303 opencm9-04
|
nucleo32-f042 nucleo32-f303 opencm9-04
|
||||||
|
|
||||||
|
BOARD_BLACKLIST += mips-malta # No UART available.
|
||||||
|
|
||||||
# use ethos (ethernet over serial) for network communication and stdio over
|
# use ethos (ethernet over serial) for network communication and stdio over
|
||||||
# UART, but not on native, as native has a tap interface towards the host.
|
# UART, but not on native, as native has a tap interface towards the host.
|
||||||
ifeq (,$(filter native,$(BOARD)))
|
ifeq (,$(filter native,$(BOARD)))
|
||||||
|
|||||||
@ -24,7 +24,7 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#ifdef __WITH_AVRLIBC__
|
#if defined(__WITH_AVRLIBC__) || defined(__mips__)
|
||||||
#include <stdio.h> /* for fwrite() */
|
#include <stdio.h> /* for fwrite() */
|
||||||
#else
|
#else
|
||||||
/* work around broken sys/posix/unistd.h */
|
/* work around broken sys/posix/unistd.h */
|
||||||
|
|||||||
24
sys/od/od.c
24
sys/od/od.c
@ -93,7 +93,7 @@ static inline void _bytes_format(char *format, uint16_t flags)
|
|||||||
strncpy(format, " %024" PRIo64, sizeof(" %024" PRIo64));
|
strncpy(format, " %024" PRIo64, sizeof(" %024" PRIo64));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#if !defined(__MACH__)
|
#if !defined(__MACH__) && !defined(__mips__)
|
||||||
case OD_FLAGS_BYTES_OCTAL | OD_FLAGS_LENGTH_SHORT:
|
case OD_FLAGS_BYTES_OCTAL | OD_FLAGS_LENGTH_SHORT:
|
||||||
sprintf(format, " %%0%do", sizeof(short) * _OCTAL_BYTE_LENGTH);
|
sprintf(format, " %%0%do", sizeof(short) * _OCTAL_BYTE_LENGTH);
|
||||||
break;
|
break;
|
||||||
@ -101,7 +101,7 @@ static inline void _bytes_format(char *format, uint16_t flags)
|
|||||||
case OD_FLAGS_BYTES_OCTAL | OD_FLAGS_LENGTH_LONG:
|
case OD_FLAGS_BYTES_OCTAL | OD_FLAGS_LENGTH_LONG:
|
||||||
sprintf(format, " %%0%dlo", sizeof(long) * _OCTAL_BYTE_LENGTH);
|
sprintf(format, " %%0%dlo", sizeof(long) * _OCTAL_BYTE_LENGTH);
|
||||||
break;
|
break;
|
||||||
#else /* !defined(__MACH__) */
|
#else /* !defined(__MACH__) && !defined(__mips__) */
|
||||||
case OD_FLAGS_BYTES_OCTAL | OD_FLAGS_LENGTH_SHORT:
|
case OD_FLAGS_BYTES_OCTAL | OD_FLAGS_LENGTH_SHORT:
|
||||||
sprintf(format, " %lu", sizeof(short) * _OCTAL_BYTE_LENGTH);
|
sprintf(format, " %lu", sizeof(short) * _OCTAL_BYTE_LENGTH);
|
||||||
break;
|
break;
|
||||||
@ -109,7 +109,7 @@ static inline void _bytes_format(char *format, uint16_t flags)
|
|||||||
case OD_FLAGS_BYTES_OCTAL | OD_FLAGS_LENGTH_LONG:
|
case OD_FLAGS_BYTES_OCTAL | OD_FLAGS_LENGTH_LONG:
|
||||||
sprintf(format, " %lu", sizeof(long) * _OCTAL_BYTE_LENGTH);
|
sprintf(format, " %lu", sizeof(long) * _OCTAL_BYTE_LENGTH);
|
||||||
break;
|
break;
|
||||||
#endif /* !defined(__MACH__) */
|
#endif /* !defined(__MACH__) && !defined(__mips__) */
|
||||||
|
|
||||||
case OD_FLAGS_BYTES_INT | OD_FLAGS_LENGTH_1:
|
case OD_FLAGS_BYTES_INT | OD_FLAGS_LENGTH_1:
|
||||||
strncpy(format, " %4d", sizeof(" %4d"));
|
strncpy(format, " %4d", sizeof(" %4d"));
|
||||||
@ -127,7 +127,7 @@ static inline void _bytes_format(char *format, uint16_t flags)
|
|||||||
strncpy(format, " %24" PRId64, sizeof(" %24" PRId64));
|
strncpy(format, " %24" PRId64, sizeof(" %24" PRId64));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#if !defined(__MACH__)
|
#if !defined(__MACH__) && !defined(__mips__)
|
||||||
case OD_FLAGS_BYTES_INT | OD_FLAGS_LENGTH_SHORT:
|
case OD_FLAGS_BYTES_INT | OD_FLAGS_LENGTH_SHORT:
|
||||||
sprintf(format, " %%%dd", sizeof(short) * _INT_BYTE_LENGTH);
|
sprintf(format, " %%%dd", sizeof(short) * _INT_BYTE_LENGTH);
|
||||||
break;
|
break;
|
||||||
@ -135,7 +135,7 @@ static inline void _bytes_format(char *format, uint16_t flags)
|
|||||||
case OD_FLAGS_BYTES_INT | OD_FLAGS_LENGTH_LONG:
|
case OD_FLAGS_BYTES_INT | OD_FLAGS_LENGTH_LONG:
|
||||||
sprintf(format, " %%%dld", sizeof(long) * _INT_BYTE_LENGTH);
|
sprintf(format, " %%%dld", sizeof(long) * _INT_BYTE_LENGTH);
|
||||||
break;
|
break;
|
||||||
#else /* !defined(__MACH__) */
|
#else /* !defined(__MACH__) && !defined(__mips__) */
|
||||||
case OD_FLAGS_BYTES_INT | OD_FLAGS_LENGTH_SHORT:
|
case OD_FLAGS_BYTES_INT | OD_FLAGS_LENGTH_SHORT:
|
||||||
sprintf(format, " %%%ld", sizeof(short) * _INT_BYTE_LENGTH);
|
sprintf(format, " %%%ld", sizeof(short) * _INT_BYTE_LENGTH);
|
||||||
break;
|
break;
|
||||||
@ -143,7 +143,7 @@ static inline void _bytes_format(char *format, uint16_t flags)
|
|||||||
case OD_FLAGS_BYTES_INT | OD_FLAGS_LENGTH_LONG:
|
case OD_FLAGS_BYTES_INT | OD_FLAGS_LENGTH_LONG:
|
||||||
sprintf(format, " %%%ld", sizeof(long) * _INT_BYTE_LENGTH);
|
sprintf(format, " %%%ld", sizeof(long) * _INT_BYTE_LENGTH);
|
||||||
break;
|
break;
|
||||||
#endif /* !defined(__MACH__) */
|
#endif /* !defined(__MACH__) && !defined(__mips__) */
|
||||||
|
|
||||||
case OD_FLAGS_BYTES_UINT | OD_FLAGS_LENGTH_1:
|
case OD_FLAGS_BYTES_UINT | OD_FLAGS_LENGTH_1:
|
||||||
strncpy(format, " %3u", sizeof(" %3u"));
|
strncpy(format, " %3u", sizeof(" %3u"));
|
||||||
@ -161,7 +161,7 @@ static inline void _bytes_format(char *format, uint16_t flags)
|
|||||||
strncpy(format, " %24" PRIu64, sizeof(" %24" PRIu64));
|
strncpy(format, " %24" PRIu64, sizeof(" %24" PRIu64));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#if !defined(__MACH__)
|
#if !defined(__MACH__) && !defined(__mips__)
|
||||||
case OD_FLAGS_BYTES_UINT | OD_FLAGS_LENGTH_SHORT:
|
case OD_FLAGS_BYTES_UINT | OD_FLAGS_LENGTH_SHORT:
|
||||||
sprintf(format, " %%%uu", (unsigned)sizeof(short) * _INT_BYTE_LENGTH);
|
sprintf(format, " %%%uu", (unsigned)sizeof(short) * _INT_BYTE_LENGTH);
|
||||||
break;
|
break;
|
||||||
@ -169,7 +169,7 @@ static inline void _bytes_format(char *format, uint16_t flags)
|
|||||||
case OD_FLAGS_BYTES_UINT | OD_FLAGS_LENGTH_LONG:
|
case OD_FLAGS_BYTES_UINT | OD_FLAGS_LENGTH_LONG:
|
||||||
sprintf(format, " %%%ulu", sizeof(long) * _INT_BYTE_LENGTH);
|
sprintf(format, " %%%ulu", sizeof(long) * _INT_BYTE_LENGTH);
|
||||||
break;
|
break;
|
||||||
#else /* !defined(__MACH__) */
|
#else /* !defined(__MACH__) && !defined(__mips__) */
|
||||||
case OD_FLAGS_BYTES_UINT | OD_FLAGS_LENGTH_SHORT:
|
case OD_FLAGS_BYTES_UINT | OD_FLAGS_LENGTH_SHORT:
|
||||||
sprintf(format, " %%%lu", sizeof(short) * _INT_BYTE_LENGTH);
|
sprintf(format, " %%%lu", sizeof(short) * _INT_BYTE_LENGTH);
|
||||||
break;
|
break;
|
||||||
@ -177,7 +177,7 @@ static inline void _bytes_format(char *format, uint16_t flags)
|
|||||||
case OD_FLAGS_BYTES_UINT | OD_FLAGS_LENGTH_LONG:
|
case OD_FLAGS_BYTES_UINT | OD_FLAGS_LENGTH_LONG:
|
||||||
sprintf(format, " %%%lu", sizeof(long) * _INT_BYTE_LENGTH);
|
sprintf(format, " %%%lu", sizeof(long) * _INT_BYTE_LENGTH);
|
||||||
break;
|
break;
|
||||||
#endif /* !defined(__MACH__) */
|
#endif /* !defined(__MACH__) && !defined(__mips__) */
|
||||||
|
|
||||||
case OD_FLAGS_BYTES_HEX | OD_FLAGS_LENGTH_1:
|
case OD_FLAGS_BYTES_HEX | OD_FLAGS_LENGTH_1:
|
||||||
strncpy(format, " %02x", sizeof(" %02x"));
|
strncpy(format, " %02x", sizeof(" %02x"));
|
||||||
@ -195,7 +195,7 @@ static inline void _bytes_format(char *format, uint16_t flags)
|
|||||||
strncpy(format, " %016" PRIx64, sizeof(" %016" PRIx64));
|
strncpy(format, " %016" PRIx64, sizeof(" %016" PRIx64));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#if !defined(__MACH__)
|
#if !defined(__MACH__) && !defined(__mips__)
|
||||||
case OD_FLAGS_BYTES_HEX | OD_FLAGS_LENGTH_SHORT:
|
case OD_FLAGS_BYTES_HEX | OD_FLAGS_LENGTH_SHORT:
|
||||||
sprintf(format, " %%0%ux", (unsigned)sizeof(short) * _HEX_BYTE_LENGTH);
|
sprintf(format, " %%0%ux", (unsigned)sizeof(short) * _HEX_BYTE_LENGTH);
|
||||||
break;
|
break;
|
||||||
@ -203,7 +203,7 @@ static inline void _bytes_format(char *format, uint16_t flags)
|
|||||||
case OD_FLAGS_BYTES_HEX | OD_FLAGS_LENGTH_LONG:
|
case OD_FLAGS_BYTES_HEX | OD_FLAGS_LENGTH_LONG:
|
||||||
sprintf(format, " %%0%ulx", (unsigned)sizeof(long) * _HEX_BYTE_LENGTH);
|
sprintf(format, " %%0%ulx", (unsigned)sizeof(long) * _HEX_BYTE_LENGTH);
|
||||||
break;
|
break;
|
||||||
#else /* !defined(__MACH__) */
|
#else /* !defined(__MACH__) && !defined(__mips__) */
|
||||||
case OD_FLAGS_BYTES_HEX | OD_FLAGS_LENGTH_SHORT:
|
case OD_FLAGS_BYTES_HEX | OD_FLAGS_LENGTH_SHORT:
|
||||||
sprintf(format, " %%0%lx", sizeof(short) * _HEX_BYTE_LENGTH);
|
sprintf(format, " %%0%lx", sizeof(short) * _HEX_BYTE_LENGTH);
|
||||||
break;
|
break;
|
||||||
@ -211,7 +211,7 @@ static inline void _bytes_format(char *format, uint16_t flags)
|
|||||||
case OD_FLAGS_BYTES_HEX | OD_FLAGS_LENGTH_LONG:
|
case OD_FLAGS_BYTES_HEX | OD_FLAGS_LENGTH_LONG:
|
||||||
sprintf(format, " %%0%lx", sizeof(long) * _HEX_BYTE_LENGTH);
|
sprintf(format, " %%0%lx", sizeof(long) * _HEX_BYTE_LENGTH);
|
||||||
break;
|
break;
|
||||||
#endif /* !defined(__MACH__) */
|
#endif /* !defined(__MACH__) && !defined(__mips__) */
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -19,6 +19,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "board.h"
|
#include "board.h"
|
||||||
#include "periph_conf.h"
|
#include "periph_conf.h"
|
||||||
|
|||||||
@ -4,6 +4,8 @@ include ../Makefile.tests_common
|
|||||||
BOARD_INSUFFICIENT_MEMORY := msb-430 msb-430h nucleo-f334 stm32f0discovery weio \
|
BOARD_INSUFFICIENT_MEMORY := msb-430 msb-430h nucleo-f334 stm32f0discovery weio \
|
||||||
nucleo-f030 nucleo32-f042
|
nucleo-f030 nucleo32-f042
|
||||||
|
|
||||||
|
BOARD_BLACKLIST += mips-malta
|
||||||
|
|
||||||
USEMODULE += auto_init_gnrc_netif
|
USEMODULE += auto_init_gnrc_netif
|
||||||
USEMODULE += gnrc
|
USEMODULE += gnrc
|
||||||
USEMODULE += gnrc_pktdump
|
USEMODULE += gnrc_pktdump
|
||||||
|
|||||||
@ -23,6 +23,7 @@
|
|||||||
*
|
*
|
||||||
* @}
|
* @}
|
||||||
*/
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "thread.h"
|
#include "thread.h"
|
||||||
#include "msg.h"
|
#include "msg.h"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user