mirror of
https://github.com/RT-Thread/rt-thread.git
synced 2026-02-07 01:44:41 +08:00
[libcpu] add c-sky ck802 support
This commit is contained in:
152
libcpu/c-sky/ck802/contex_ck802_gcc.S
Normal file
152
libcpu/c-sky/ck802/contex_ck802_gcc.S
Normal file
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* File : contex_ck802.S
|
||||
* This file is part of RT-Thread RTOS
|
||||
* COPYRIGHT (C) 2006 - 2017, RT-Thread Development Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2017-01-01 Urey first version
|
||||
* 2018-06-05 tanek clean code
|
||||
*/
|
||||
|
||||
.file "contex_ck802.S"
|
||||
|
||||
#undef VIC_TSPDR
|
||||
#define VIC_TSPDR 0XE000EC08
|
||||
|
||||
.global rt_thread_switch_interrupt_flag
|
||||
.global rt_interrupt_from_thread
|
||||
.global rt_interrupt_to_thread
|
||||
|
||||
.text
|
||||
.align 2
|
||||
|
||||
/*
|
||||
* rt_base_t rt_hw_interrupt_disable(void);
|
||||
*/
|
||||
.global rt_hw_interrupt_disable
|
||||
.type rt_hw_interrupt_disable, %function
|
||||
rt_hw_interrupt_disable:
|
||||
mfcr r0, psr
|
||||
psrclr ie
|
||||
rts
|
||||
|
||||
/*
|
||||
* void rt_hw_interrupt_enable(rt_base_t psr);
|
||||
*/
|
||||
.global rt_hw_interrupt_enable
|
||||
.type rt_hw_interrupt_enable, %function
|
||||
rt_hw_interrupt_enable:
|
||||
mtcr r0, psr
|
||||
rts
|
||||
|
||||
/*
|
||||
* void rt_hw_context_switch_to(rt_uint32 to);
|
||||
* R0 --> to
|
||||
*/
|
||||
.global rt_hw_context_switch_to
|
||||
.type rt_hw_context_switch_to, %function
|
||||
rt_hw_context_switch_to:
|
||||
lrw r2, rt_interrupt_to_thread
|
||||
stw r0, (r2)
|
||||
|
||||
/* set form thread = 0 */
|
||||
lrw r2, rt_interrupt_from_thread
|
||||
movi r0, 0
|
||||
stw r0, (r2)
|
||||
|
||||
psrclr ie
|
||||
jbr __tspend_handler_nosave
|
||||
|
||||
/*
|
||||
* void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to);
|
||||
* r0 --> from
|
||||
* r1 --> to
|
||||
*/
|
||||
.global rt_hw_context_switch_interrupt
|
||||
.type rt_hw_context_switch_interrupt, %function
|
||||
rt_hw_context_switch_interrupt:
|
||||
lrw r2, rt_interrupt_from_thread /* set rt_interrupt_from_thread */
|
||||
stw r0, (r2)
|
||||
|
||||
lrw r2, rt_interrupt_to_thread /* set rt_interrupt_to_thread */
|
||||
stw r1, (r2)
|
||||
|
||||
lrw r0, VIC_TSPDR
|
||||
bgeni r1, 0
|
||||
stw r1, (r0)
|
||||
rts
|
||||
|
||||
/*
|
||||
* void rt_hw_context_switch(rt_uint32 from, rt_uint32 to)
|
||||
* r0 --> from
|
||||
* r1 --> to
|
||||
*/
|
||||
.global rt_hw_context_switch
|
||||
.type rt_hw_context_switch, %function
|
||||
rt_hw_context_switch:
|
||||
lrw r2, rt_interrupt_from_thread /* set rt_interrupt_from_thread */
|
||||
stw r0, (r2)
|
||||
|
||||
lrw r2, rt_interrupt_to_thread /* set rt_interrupt_to_thread */
|
||||
stw r1, (r2)
|
||||
|
||||
lrw r0, VIC_TSPDR
|
||||
bgeni r1, 0
|
||||
stw r1, (r0)
|
||||
rts
|
||||
|
||||
.global PendSV_Handler
|
||||
.type PendSV_Handler, %function
|
||||
PendSV_Handler:
|
||||
subi sp, 68
|
||||
stm r0-r13, (sp)
|
||||
stw r15, (sp, 56)
|
||||
mfcr r0, epsr
|
||||
stw r0, (sp, 60)
|
||||
mfcr r0, epc
|
||||
stw r0, (sp, 64)
|
||||
|
||||
lrw r0, rt_interrupt_from_thread
|
||||
ldw r1, (r0)
|
||||
stw sp, (r1)
|
||||
|
||||
__tspend_handler_nosave:
|
||||
lrw r6, rt_interrupt_to_thread
|
||||
lrw r7, rt_interrupt_from_thread
|
||||
ldw r8, (r6)
|
||||
stw r8, (r7)
|
||||
|
||||
ldw sp, (r8)
|
||||
|
||||
#ifdef CONFIG_STACK_GUARD
|
||||
mfcr r3, cr<0, 4>
|
||||
bseti r3, 0
|
||||
bseti r3, 1
|
||||
mtcr r3, cr<0, 4>
|
||||
#endif
|
||||
|
||||
ldw r0, (sp, 64)
|
||||
mtcr r0, epc
|
||||
ldw r0, (sp, 60)
|
||||
bseti r0, 6
|
||||
mtcr r0, epsr
|
||||
ldw r15, (sp, 56)
|
||||
ldm r0-r13, (sp)
|
||||
addi sp, 68
|
||||
rte
|
||||
|
||||
337
libcpu/c-sky/ck802/core_ck802.c
Normal file
337
libcpu/c-sky/ck802/core_ck802.c
Normal file
@@ -0,0 +1,337 @@
|
||||
/*
|
||||
* File : core_ck802.c
|
||||
* This file is part of RT-Thread RTOS
|
||||
* COPYRIGHT (C) 2006 - 2017, RT-Thread Development Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2017-01-01 Urey first version
|
||||
*/
|
||||
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <core_ck802.h>
|
||||
|
||||
/* flag in interrupt handling */
|
||||
rt_uint32_t rt_interrupt_from_thread, rt_interrupt_to_thread;
|
||||
rt_uint32_t rt_thread_switch_interrupt_flag;
|
||||
|
||||
/*******************************************************************************
|
||||
* Hardware Abstraction Layer
|
||||
Core Function Interface contains:
|
||||
- Core VIC Functions
|
||||
- Core CORET Functions
|
||||
- Core Register Access Functions
|
||||
******************************************************************************/
|
||||
/**
|
||||
\defgroup CSI_Core_FunctionInterface Functions and Instructions Reference
|
||||
*/
|
||||
|
||||
/* ########################## NVIC functions #################################### */
|
||||
/**
|
||||
\ingroup CSI_Core_FunctionInterface
|
||||
\defgroup CSI_Core_NVICFunctions NVIC Functions
|
||||
\brief Functions that manage interrupts and exceptions via the NVIC.
|
||||
@{
|
||||
*/
|
||||
|
||||
/* Interrupt Priorities are WORD accessible only under CSKYv6M */
|
||||
/* The following MACROS handle generation of the register offset and byte masks */
|
||||
#define _BIT_SHIFT(IRQn) ( ((((uint32_t)(int32_t)(IRQn)) ) & 0x03UL) * 8UL)
|
||||
#define _IP_IDX(IRQn) ( (((uint32_t)(int32_t)(IRQn)) >> 2UL) )
|
||||
|
||||
static uint32_t s_nvic_prio_bits = __NVIC_PRIO_BITS;
|
||||
|
||||
/**
|
||||
\brief initialize the NVIC interrupt controller
|
||||
\param [in] prio_bits the priority bits of NVIC interrupt controller.
|
||||
*/
|
||||
void drv_nvic_init(uint32_t prio_bits)
|
||||
{
|
||||
if (s_nvic_prio_bits >= 8U)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
s_nvic_prio_bits = prio_bits;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Enable External Interrupt
|
||||
\details Enables a device-specific interrupt in the NVIC interrupt controller.
|
||||
\param [in] IRQn External interrupt number. Value cannot be negative.
|
||||
*/
|
||||
void drv_nvic_enable_irq(int32_t IRQn)
|
||||
{
|
||||
NVIC->ISER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
|
||||
#ifdef CONFIG_SYSTEM_SECURE
|
||||
NVIC->ISSR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Disable External Interrupt
|
||||
\details Disables a device-specific interrupt in the NVIC interrupt controller.
|
||||
\param [in] IRQn External interrupt number. Value cannot be negative.
|
||||
*/
|
||||
void drv_nvic_disable_irq(int32_t IRQn)
|
||||
{
|
||||
NVIC->ICER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Enable External Secure Interrupt
|
||||
\details Enables a secure device-specific interrupt in the NVIC interrupt controller.
|
||||
\param [in] IRQn External interrupt number. Value cannot be negative.
|
||||
*/
|
||||
void drv_nvic_enable_sirq(int32_t IRQn)
|
||||
{
|
||||
NVIC->ISSR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Get Pending Interrupt
|
||||
\details Reads the pending register in the NVIC and returns the pending bit for the specified interrupt.
|
||||
\param [in] IRQn Interrupt number.
|
||||
\return 0 Interrupt status is not pending.
|
||||
\return 1 Interrupt status is pending.
|
||||
*/
|
||||
uint32_t drv_nvic_get_pending_irq(int32_t IRQn)
|
||||
{
|
||||
return ((uint32_t)(((NVIC->ISPR[0U] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Set Pending Interrupt
|
||||
\details Sets the pending bit of an external interrupt.
|
||||
\param [in] IRQn Interrupt number. Value cannot be negative.
|
||||
*/
|
||||
void drv_nvic_set_pending_irq(int32_t IRQn)
|
||||
{
|
||||
NVIC->ISPR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Clear Pending Interrupt
|
||||
\details Clears the pending bit of an external interrupt.
|
||||
\param [in] IRQn External interrupt number. Value cannot be negative.
|
||||
*/
|
||||
void drv_nvic_clear_pending_irq(int32_t IRQn)
|
||||
{
|
||||
NVIC->ICPR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Get Wake up Interrupt
|
||||
\details Reads the wake up register in the NVIC and returns the pending bit for the specified interrupt.
|
||||
\param [in] IRQn Interrupt number.
|
||||
\return 0 Interrupt is not set as wake up interrupt.
|
||||
\return 1 Interrupt is set as wake up interrupt.
|
||||
*/
|
||||
uint32_t drv_nvic_get_wakeup_irq(int32_t IRQn)
|
||||
{
|
||||
return ((uint32_t)(((NVIC->IWER[0U] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Set Wake up Interrupt
|
||||
\details Sets the wake up bit of an external interrupt.
|
||||
\param [in] IRQn Interrupt number. Value cannot be negative.
|
||||
*/
|
||||
void drv_nvic_set_wakeup_irq(int32_t IRQn)
|
||||
{
|
||||
NVIC->IWER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Clear Wake up Interrupt
|
||||
\details Clears the wake up bit of an external interrupt.
|
||||
\param [in] IRQn External interrupt number. Value cannot be negative.
|
||||
*/
|
||||
void drv_nvic_clear_wakeup_irq(int32_t IRQn)
|
||||
{
|
||||
NVIC->IWDR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Get Active Interrupt
|
||||
\details Reads the active register in the NVIC and returns the active bit for the device specific interrupt.
|
||||
\param [in] IRQn Device specific interrupt number.
|
||||
\return 0 Interrupt status is not active.
|
||||
\return 1 Interrupt status is active.
|
||||
\note IRQn must not be negative.
|
||||
*/
|
||||
uint32_t drv_nvic_get_active(int32_t IRQn)
|
||||
{
|
||||
return ((uint32_t)(((NVIC->IABR[0] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Set Threshold register
|
||||
\details set the threshold register in the NVIC.
|
||||
\param [in] VectThreshold specific vecter threshold.
|
||||
\param [in] PrioThreshold specific priority threshold.
|
||||
*/
|
||||
void drv_nvic_set_threshold(uint32_t VectThreshold, uint32_t PrioThreshold)
|
||||
{
|
||||
NVIC->IPTR = 0x80000000 | (((VectThreshold + 32) & 0xFF) << 8) | ((PrioThreshold & 0x3) << 6);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Set Interrupt Priority
|
||||
\details Sets the priority of an interrupt.
|
||||
\note The priority cannot be set for every core interrupt.
|
||||
\param [in] IRQn Interrupt number.
|
||||
\param [in] priority Priority to set.
|
||||
*/
|
||||
void drv_nvic_set_prio(int32_t IRQn, uint32_t priority)
|
||||
{
|
||||
NVIC->IPR[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IPR[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
|
||||
(((priority << (8U - s_nvic_prio_bits)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn)));
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Get Interrupt Priority
|
||||
\details Reads the priority of an interrupt.
|
||||
The interrupt number can be positive to specify an external (device specific) interrupt,
|
||||
or negative to specify an internal (core) interrupt.
|
||||
\param [in] IRQn Interrupt number.
|
||||
\return Interrupt Priority.
|
||||
Value is aligned automatically to the implemented priority bits of the microcontroller.
|
||||
*/
|
||||
uint32_t drv_nvic_get_prio(int32_t IRQn)
|
||||
{
|
||||
return ((uint32_t)(((NVIC->IPR[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn)) & (uint32_t)0xFFUL) >> (8U - s_nvic_prio_bits)));
|
||||
}
|
||||
|
||||
|
||||
/*@} end of CSI_Core_NVICFunctions */
|
||||
|
||||
/* ################################## SysTick function ############################################ */
|
||||
/**
|
||||
\ingroup CSI_Core_FunctionInterface
|
||||
\defgroup CSI_Core_SysTickFunctions SysTick Functions
|
||||
\brief Functions that configure the System.
|
||||
@{
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
\brief CORE timer Configuration
|
||||
\details Initializes the System Timer and its interrupt, and starts the System Tick Timer.
|
||||
Counter is in free running mode to generate periodic interrupts.
|
||||
\param [in] ticks Number of ticks between two interrupts.
|
||||
\param [in] IRQn core timer Interrupt number.
|
||||
\return 0 Function succeeded.
|
||||
\return 1 Function failed.
|
||||
\note When the variable <b>__Vendor_SysTickConfig</b> is set to 1, then the
|
||||
function <b>SysTick_Config</b> is not included. In this case, the file <b><i>device</i>.h</b>
|
||||
must contain a vendor-specific implementation of this function.
|
||||
*/
|
||||
uint32_t drv_coret_config(uint32_t ticks, int32_t IRQn)
|
||||
{
|
||||
if ((ticks - 1UL) > CORET_LOAD_RELOAD_Msk)
|
||||
{
|
||||
return (1UL); /* Reload value impossible */
|
||||
}
|
||||
|
||||
CORET->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */
|
||||
drv_nvic_set_prio(IRQn, (1UL << s_nvic_prio_bits) - 1UL); /* set Priority for Systick Interrupt */
|
||||
CORET->VAL = 0UL; /* Load the CORET Counter Value */
|
||||
CORET->CTRL = CORET_CTRL_CLKSOURCE_Msk |
|
||||
CORET_CTRL_TICKINT_Msk |
|
||||
CORET_CTRL_ENABLE_Msk; /* Enable CORET IRQ and CORET Timer */
|
||||
return (0UL); /* Function successful */
|
||||
}
|
||||
|
||||
/**
|
||||
\brief get CORE timer reload value
|
||||
\return CORE timer counter value.
|
||||
*/
|
||||
uint32_t drv_coret_get_load(void)
|
||||
{
|
||||
return CORET->LOAD;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief get CORE timer counter value
|
||||
\return CORE timer counter value.
|
||||
*/
|
||||
uint32_t drv_coret_get_value(void)
|
||||
{
|
||||
return CORET->VAL;
|
||||
}
|
||||
|
||||
/*@} end of CSI_Core_SysTickFunctions */
|
||||
|
||||
#if 0
|
||||
/* ##################################### DCC function ########################################### */
|
||||
/**
|
||||
\ingroup CSI_Core_FunctionInterface
|
||||
\defgroup CSI_core_DebugFunctions HAD Functions
|
||||
\brief Functions that access the HAD debug interface.
|
||||
@{
|
||||
*/
|
||||
|
||||
/**
|
||||
\brief HAD Send Character
|
||||
\details Transmits a character via the HAD channel 0, and
|
||||
\li Just returns when no debugger is connected that has booked the output.
|
||||
\li Is blocking when a debugger is connected, but the previous character sent has not been transmitted.
|
||||
\param [in] ch Character to transmit.
|
||||
\returns Character to transmit.
|
||||
*/
|
||||
uint32_t HAD_SendChar(uint32_t ch)
|
||||
{
|
||||
DCC->DERJR = (uint8_t)ch;
|
||||
|
||||
return (ch);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief HAD Receive Character
|
||||
\details Inputs a character via the external variable \ref HAD_RxBuffer.
|
||||
\return Received character.
|
||||
\return -1 No character pending.
|
||||
*/
|
||||
int32_t HAD_ReceiveChar(void)
|
||||
{
|
||||
int32_t ch = -1; /* no character available */
|
||||
|
||||
if (_FLD2VAL(DCC_EHSR_JW, DCC->EHSR))
|
||||
{
|
||||
ch = DCC->DERJW;
|
||||
}
|
||||
|
||||
return (ch);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief HAD Check Character
|
||||
\details Checks whether a character is pending for reading in the variable \ref HAD_RxBuffer.
|
||||
\return 0 No character available.
|
||||
\return 1 Character available.
|
||||
*/
|
||||
int32_t HAD_CheckChar(void)
|
||||
{
|
||||
return _FLD2VAL(DCC_EHSR_JW, DCC->EHSR); /* no character available */
|
||||
}
|
||||
|
||||
#endif
|
||||
552
libcpu/c-sky/ck802/core_ck802.h
Normal file
552
libcpu/c-sky/ck802/core_ck802.h
Normal file
File diff suppressed because it is too large
Load Diff
55
libcpu/c-sky/ck802/stack_ck802.c
Normal file
55
libcpu/c-sky/ck802/stack_ck802.c
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* File : stack_ck802.c
|
||||
* This file is part of RT-Thread RTOS
|
||||
* COPYRIGHT (C) 2006 - 2017, RT-Thread Development Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2017-01-01 Urey first version
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
|
||||
rt_uint8_t *rt_hw_stack_init(void *tentry, void *parameter, rt_uint8_t *stack_addr, void *texit)
|
||||
{
|
||||
rt_uint32_t *stk = (rt_uint32_t *)stack_addr;
|
||||
|
||||
stk = (rt_uint32_t *)(stack_addr + sizeof(rt_uint32_t));
|
||||
stk = (rt_uint32_t *)RT_ALIGN_DOWN((rt_uint32_t)stk, 8);
|
||||
|
||||
*(--stk) = (rt_uint32_t)tentry; /* Entry Point */
|
||||
*(--stk) = (rt_uint32_t)0x80000150L; /* PSR */
|
||||
*(--stk) = (rt_uint32_t)texit; /* R15 (LR) (init value will cause fault if ever used) */
|
||||
*(--stk) = (rt_uint32_t)0x13131313L; /* R13 */
|
||||
*(--stk) = (rt_uint32_t)0x12121212L; /* R12 */
|
||||
*(--stk) = (rt_uint32_t)0x11111111L; /* R11 */
|
||||
*(--stk) = (rt_uint32_t)0x10101010L; /* R10 */
|
||||
*(--stk) = (rt_uint32_t)0x09090909L; /* R9 */
|
||||
*(--stk) = (rt_uint32_t)0x08080808L; /* R8 */
|
||||
*(--stk) = (rt_uint32_t)0x07070707L; /* R7 */
|
||||
*(--stk) = (rt_uint32_t)0x06060606L; /* R6 */
|
||||
*(--stk) = (rt_uint32_t)0x05050505L; /* R5 */
|
||||
*(--stk) = (rt_uint32_t)0x04040404L; /* R4 */
|
||||
*(--stk) = (rt_uint32_t)0x03030303L; /* R3 */
|
||||
*(--stk) = (rt_uint32_t)0x02020202L; /* R2 */
|
||||
*(--stk) = (rt_uint32_t)0x01010101L; /* R1 */
|
||||
*(--stk) = (rt_uint32_t)parameter; /* R0 : argument */
|
||||
|
||||
/* return task's current stack address */
|
||||
return (rt_uint8_t *)stk;
|
||||
}
|
||||
|
||||
248
libcpu/c-sky/common/csi_core.h
Normal file
248
libcpu/c-sky/common/csi_core.h
Normal file
@@ -0,0 +1,248 @@
|
||||
/*
|
||||
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
|
||||
*
|
||||
* Licensed 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.
|
||||
*/
|
||||
|
||||
/******************************************************************************
|
||||
* @file csi_core.h
|
||||
* @brief CSI Core Layer Header File
|
||||
* @version V1.0
|
||||
* @date 02. June 2017
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef _CORE_H_
|
||||
#define _CORE_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include "csi_gcc.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/* ################################## NVIC function ############################################ */
|
||||
|
||||
/**
|
||||
\brief initialize the NVIC interrupt controller
|
||||
\param [in] prio_bits the priority bits of NVIC interrupt controller.
|
||||
*/
|
||||
void drv_nvic_init(uint32_t prio_bits);
|
||||
|
||||
/**
|
||||
\brief Enable External Interrupt
|
||||
\details Enables a device-specific interrupt in the NVIC interrupt controller.
|
||||
\param [in] irq_num External interrupt number. Value cannot be negative.
|
||||
*/
|
||||
void drv_nvic_enable_irq(int32_t irq_num);
|
||||
/**
|
||||
\brief Disable External Interrupt
|
||||
\details Disables a device-specific interrupt in the NVIC interrupt controller.
|
||||
\param [in] irq_num External interrupt number. Value cannot be negative.
|
||||
*/
|
||||
void drv_nvic_disable_irq(int32_t irq_num);
|
||||
|
||||
/**
|
||||
\brief Get Pending Interrupt
|
||||
\details Reads the pending register in the NVIC and returns the pending bit for the specified interrupt.
|
||||
\param [in] irq_num Interrupt number.
|
||||
\return 0 Interrupt status is not pending.
|
||||
\return 1 Interrupt status is pending.
|
||||
*/
|
||||
uint32_t drv_nvic_get_pending_irq(int32_t irq_num);
|
||||
|
||||
/**
|
||||
\brief Set Pending Interrupt
|
||||
\details Sets the pending bit of an external interrupt.
|
||||
\param [in] irq_num Interrupt number. Value cannot be negative.
|
||||
*/
|
||||
void drv_nvic_set_pending_irq(int32_t irq_num);
|
||||
|
||||
/**
|
||||
\brief Clear Pending Interrupt
|
||||
\details Clears the pending bit of an external interrupt.
|
||||
\param [in] irq_num External interrupt number. Value cannot be negative.
|
||||
*/
|
||||
void drv_nvic_clear_pending_irq(int32_t irq_num);
|
||||
|
||||
/**
|
||||
\brief Get Active Interrupt
|
||||
\details Reads the active register in the NVIC and returns the active bit for the device specific interrupt.
|
||||
\param [in] irq_num Device specific interrupt number.
|
||||
\return 0 Interrupt status is not active.
|
||||
\return 1 Interrupt status is active.
|
||||
\note irq_num must not be negative.
|
||||
*/
|
||||
uint32_t drv_nvic_get_active(int32_t irq_num);
|
||||
|
||||
/**
|
||||
\brief Set Interrupt Priority
|
||||
\details Sets the priority of an interrupt.
|
||||
\note The priority cannot be set for every core interrupt.
|
||||
\param [in] irq_num Interrupt number.
|
||||
\param [in] priority Priority to set.
|
||||
*/
|
||||
void drv_nvic_set_prio(int32_t irq_num, uint32_t priority);
|
||||
/**
|
||||
\brief Get Interrupt Priority
|
||||
\details Reads the priority of an interrupt.
|
||||
The interrupt number can be positive to specify an external (device specific) interrupt,
|
||||
or negative to specify an internal (core) interrupt.
|
||||
\param [in] irq_num Interrupt number.
|
||||
\return Interrupt Priority.
|
||||
Value is aligned automatically to the implemented priority bits of the microcontroller.
|
||||
*/
|
||||
uint32_t drv_nvic_get_prio(int32_t irq_num);
|
||||
|
||||
/*@} end of CSI_Core_NVICFunctions */
|
||||
|
||||
|
||||
/* ########################## Cache functions #################################### */
|
||||
|
||||
/**
|
||||
\brief Enable I-Cache
|
||||
\details Turns on I-Cache
|
||||
*/
|
||||
void drv_icache_enable(void);
|
||||
|
||||
/**
|
||||
\brief Disable I-Cache
|
||||
\details Turns off I-Cache
|
||||
*/
|
||||
void drv_icache_disable(void);
|
||||
|
||||
/**
|
||||
\brief Invalidate I-Cache
|
||||
\details Invalidates I-Cache
|
||||
*/
|
||||
void drv_icache_invalid(void);
|
||||
|
||||
/**
|
||||
\brief Enable D-Cache
|
||||
\details Turns on D-Cache
|
||||
\note I-Cache also turns on.
|
||||
*/
|
||||
void drv_dcache_enable(void);
|
||||
|
||||
/**
|
||||
\brief Disable D-Cache
|
||||
\details Turns off D-Cache
|
||||
\note I-Cache also turns off.
|
||||
*/
|
||||
void drv_dcache_disable(void);
|
||||
|
||||
/**
|
||||
\brief Invalidate D-Cache
|
||||
\details Invalidates D-Cache
|
||||
\note I-Cache also invalid
|
||||
*/
|
||||
void drv_dcache_invalid(void);
|
||||
|
||||
/**
|
||||
\brief Clean D-Cache
|
||||
\details Cleans D-Cache
|
||||
\note I-Cache also cleans
|
||||
*/
|
||||
void drv_dcache_clean(void);
|
||||
|
||||
/**
|
||||
\brief Clean & Invalidate D-Cache
|
||||
\details Cleans and Invalidates D-Cache
|
||||
\note I-Cache also flush.
|
||||
*/
|
||||
void drv_dcache_clean_invalid(void);
|
||||
|
||||
|
||||
/**
|
||||
\brief D-Cache Invalidate by address
|
||||
\details Invalidates D-Cache for the given address
|
||||
\param[in] addr address (aligned to 16-byte boundary)
|
||||
\param[in] dsize size of memory block (in number of bytes)
|
||||
*/
|
||||
void drv_dcache_invalid_range(uint32_t *addr, int32_t dsize);
|
||||
|
||||
/**
|
||||
\brief D-Cache Clean by address
|
||||
\details Cleans D-Cache for the given address
|
||||
\param[in] addr address (aligned to 16-byte boundary)
|
||||
\param[in] dsize size of memory block (in number of bytes)
|
||||
*/
|
||||
void drv_dcache_clean_range(uint32_t *addr, int32_t dsize);
|
||||
|
||||
/**
|
||||
\brief D-Cache Clean and Invalidate by address
|
||||
\details Cleans and invalidates D_Cache for the given address
|
||||
\param[in] addr address (aligned to 16-byte boundary)
|
||||
\param[in] dsize size of memory block (in number of bytes)
|
||||
*/
|
||||
void drv_dcache_clean_invalid_range(uint32_t *addr, int32_t dsize);
|
||||
|
||||
/**
|
||||
\brief setup cacheable range Cache
|
||||
\details setup Cache range
|
||||
*/
|
||||
void drv_cache_set_range(uint32_t index, uint32_t baseAddr, uint32_t size, uint32_t enable);
|
||||
|
||||
/**
|
||||
\brief Enable cache profile
|
||||
\details Turns on Cache profile
|
||||
*/
|
||||
void drv_cache_enable_profile(void);
|
||||
|
||||
/**
|
||||
\brief Disable cache profile
|
||||
\details Turns off Cache profile
|
||||
*/
|
||||
void drv_cache_disable_profile(void);
|
||||
/**
|
||||
\brief Reset cache profile
|
||||
\details Reset Cache profile
|
||||
*/
|
||||
void drv_cache_reset_profile(void);
|
||||
|
||||
/**
|
||||
\brief cache access times
|
||||
\details Cache access times
|
||||
\note every 256 access add 1.
|
||||
*/
|
||||
uint32_t drv_cache_get_access_time(void);
|
||||
|
||||
/**
|
||||
\brief cache miss times
|
||||
\details Cache miss times
|
||||
\note every 256 miss add 1.
|
||||
*/
|
||||
uint32_t drv_cache_get_miss_time(void);
|
||||
|
||||
/* ################################## SysTick function ############################################ */
|
||||
|
||||
/**
|
||||
\brief CORE timer Configuration
|
||||
\details Initializes the System Timer and its interrupt, and starts the System Tick Timer.
|
||||
Counter is in free running mode to generate periodic interrupts.
|
||||
\param [in] ticks Number of ticks between two interrupts.
|
||||
\param [in] irq_num core timer Interrupt number.
|
||||
\return 0 Function succeeded.
|
||||
\return 1 Function failed.
|
||||
\note When the variable <b>__Vendor_SysTickConfig</b> is set to 1, then the
|
||||
function <b>SysTick_Config</b> is not included. In this case, the file <b><i>device</i>.h</b>
|
||||
must contain a vendor-specific implementation of this function.
|
||||
*/
|
||||
uint32_t drv_coret_config(uint32_t ticks, int32_t irq_num);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _CORE_H_ */
|
||||
36
libcpu/c-sky/common/csi_gcc.h
Normal file
36
libcpu/c-sky/common/csi_gcc.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
|
||||
*
|
||||
* Licensed 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.
|
||||
*/
|
||||
|
||||
/******************************************************************************
|
||||
* @file csi_gcc.h
|
||||
* @brief CSI Header File for GCC.
|
||||
* @version V1.0
|
||||
* @date 02. June 2017
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef _CSI_GCC_H_
|
||||
#define _CSI_GCC_H_
|
||||
|
||||
#define __ASM __asm /*!< asm keyword for GNU Compiler */
|
||||
#define __INLINE inline /*!< inline keyword for GNU Compiler */
|
||||
#define __ALWAYS_INLINE __attribute__((always_inline)) static inline
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "csi_reg.h"
|
||||
#include "csi_instr.h"
|
||||
#include "csi_simd.h"
|
||||
|
||||
#endif /* _CSI_GCC_H_ */
|
||||
447
libcpu/c-sky/common/csi_instr.h
Normal file
447
libcpu/c-sky/common/csi_instr.h
Normal file
@@ -0,0 +1,447 @@
|
||||
/*
|
||||
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
|
||||
*
|
||||
* Licensed 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.
|
||||
*/
|
||||
|
||||
/******************************************************************************
|
||||
* @file csi_instr.h
|
||||
* @brief CSI Header File for instruct.
|
||||
* @version V1.0
|
||||
* @date 02. June 2017
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef _CSI_INSTR_H_
|
||||
#define _CSI_INSTR_H_
|
||||
|
||||
|
||||
#define __CSI_GCC_OUT_REG(r) "=r" (r)
|
||||
#define __CSI_GCC_USE_REG(r) "r" (r)
|
||||
|
||||
/**
|
||||
\brief No Operation
|
||||
\details No Operation does nothing. This instruction can be used for code alignment purposes.
|
||||
*/
|
||||
__ALWAYS_INLINE void __NOP(void)
|
||||
{
|
||||
__ASM volatile("nop");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Wait For Interrupt
|
||||
\details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs.
|
||||
*/
|
||||
__ALWAYS_INLINE void __WFI(void)
|
||||
{
|
||||
__ASM volatile("wait");
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Wait For Interrupt
|
||||
\details Wait For Interrupt is a hint instruction that suspends execution until one interrupt occurs.
|
||||
*/
|
||||
__ALWAYS_INLINE void __WAIT(void)
|
||||
{
|
||||
__ASM volatile("wait");
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Doze For Interrupt
|
||||
\details Doze For Interrupt is a hint instruction that suspends execution until one interrupt occurs.
|
||||
*/
|
||||
__ALWAYS_INLINE void __DOZE(void)
|
||||
{
|
||||
__ASM volatile("doze");
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Stop For Interrupt
|
||||
\details Stop For Interrupt is a hint instruction that suspends execution until one interrupt occurs.
|
||||
*/
|
||||
__ALWAYS_INLINE void __STOP(void)
|
||||
{
|
||||
__ASM volatile("stop");
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Instruction Synchronization Barrier
|
||||
\details Instruction Synchronization Barrier flushes the pipeline in the processor,
|
||||
so that all instructions following the ISB are fetched from cache or memory,
|
||||
after the instruction has been completed.
|
||||
*/
|
||||
__ALWAYS_INLINE void __ISB(void)
|
||||
{
|
||||
__ASM volatile("sync"::: "memory");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Data Synchronization Barrier
|
||||
\details Acts as a special kind of Data Memory Barrier.
|
||||
It completes when all explicit memory accesses before this instruction complete.
|
||||
*/
|
||||
__ALWAYS_INLINE void __DSB(void)
|
||||
{
|
||||
__ASM volatile("sync"::: "memory");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Data Memory Barrier
|
||||
\details Ensures the apparent order of the explicit memory operations before
|
||||
and after the instruction, without ensuring their completion.
|
||||
*/
|
||||
__ALWAYS_INLINE void __DMB(void)
|
||||
{
|
||||
__ASM volatile("sync"::: "memory");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Reverse byte order (32 bit)
|
||||
\details Reverses the byte order in integer value.
|
||||
\param [in] value Value to reverse
|
||||
\return Reversed value
|
||||
*/
|
||||
__ALWAYS_INLINE uint32_t __REV(uint32_t value)
|
||||
{
|
||||
return __builtin_bswap32(value);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Reverse byte order (16 bit)
|
||||
\details Reverses the byte order in two unsigned short values.
|
||||
\param [in] value Value to reverse
|
||||
\return Reversed value
|
||||
*/
|
||||
__ALWAYS_INLINE uint32_t __REV16(uint32_t value)
|
||||
{
|
||||
uint32_t result;
|
||||
#if (__CK80X >= 2)
|
||||
__ASM volatile("revh %0, %1" : __CSI_GCC_OUT_REG(result) : __CSI_GCC_USE_REG(value));
|
||||
#else
|
||||
result = ((value & 0xFF000000) >> 8) | ((value & 0x00FF0000) << 8) |
|
||||
((value & 0x0000FF00) >> 8) | ((value & 0x000000FF) << 8);
|
||||
#endif
|
||||
return (result);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Reverse byte order in signed short value
|
||||
\details Reverses the byte order in a signed short value with sign extension to integer.
|
||||
\param [in] value Value to reverse
|
||||
\return Reversed value
|
||||
*/
|
||||
__ALWAYS_INLINE int32_t __REVSH(int32_t value)
|
||||
{
|
||||
return (short)(((value & 0xFF00) >> 8) | ((value & 0x00FF) << 8));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Rotate Right in unsigned value (32 bit)
|
||||
\details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits.
|
||||
\param [in] op1 Value to rotate
|
||||
\param [in] op2 Number of Bits to rotate
|
||||
\return Rotated value
|
||||
*/
|
||||
__ALWAYS_INLINE uint32_t __ROR(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
return (op1 >> op2) | (op1 << (32U - op2));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Breakpoint
|
||||
\details Causes the processor to enter Debug state
|
||||
Debug tools can use this to investigate system state when the instruction at a particular address is reached.
|
||||
*/
|
||||
__ALWAYS_INLINE void __BKPT()
|
||||
{
|
||||
__ASM volatile("bkpt");
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Reverse bit order of value
|
||||
\details Reverses the bit order of the given value.
|
||||
\param [in] value Value to reverse
|
||||
\return Reversed value
|
||||
*/
|
||||
__ALWAYS_INLINE uint32_t __RBIT(uint32_t value)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
#if (__CK80X >= 0x03U)
|
||||
__ASM volatile("brev %0, %1" : "=r"(result) : "r"(value));
|
||||
#else
|
||||
int32_t s = 4 /*sizeof(v)*/ * 8 - 1; /* extra shift needed at end */
|
||||
|
||||
result = value; /* r will be reversed bits of v; first get LSB of v */
|
||||
|
||||
for (value >>= 1U; value; value >>= 1U)
|
||||
{
|
||||
result <<= 1U;
|
||||
result |= value & 1U;
|
||||
s--;
|
||||
}
|
||||
|
||||
result <<= s; /* shift when v's highest bits are zero */
|
||||
#endif
|
||||
return (result);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Count leading zeros
|
||||
\details Counts the number of leading zeros of a data value.
|
||||
\param [in] value Value to count the leading zeros
|
||||
\return number of leading zeros in value
|
||||
*/
|
||||
#define __CLZ __builtin_clz
|
||||
/**
|
||||
\details This function saturates a signed value.
|
||||
\param [in] x Value to be saturated
|
||||
\param [in] y Bit position to saturate to [1..32]
|
||||
\return Saturated value.
|
||||
*/
|
||||
__ALWAYS_INLINE int32_t __SSAT(int32_t x, uint32_t y)
|
||||
{
|
||||
int32_t posMax, negMin;
|
||||
uint32_t i;
|
||||
|
||||
posMax = 1;
|
||||
|
||||
for (i = 0; i < (y - 1); i++)
|
||||
{
|
||||
posMax = posMax * 2;
|
||||
}
|
||||
|
||||
if (x > 0)
|
||||
{
|
||||
posMax = (posMax - 1);
|
||||
|
||||
if (x > posMax)
|
||||
{
|
||||
x = posMax;
|
||||
}
|
||||
|
||||
// x &= (posMax * 2 + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
negMin = -posMax;
|
||||
|
||||
if (x < negMin)
|
||||
{
|
||||
x = negMin;
|
||||
}
|
||||
|
||||
// x &= (posMax * 2 - 1);
|
||||
}
|
||||
|
||||
return (x);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Unsigned Saturate
|
||||
\details Saturates an unsigned value.
|
||||
\param [in] value Value to be saturated
|
||||
\param [in] sat Bit position to saturate to (0..31)
|
||||
\return Saturated value
|
||||
*/
|
||||
__ALWAYS_INLINE uint32_t __USAT(uint32_t value, uint32_t sat)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
if ((((0xFFFFFFFF >> sat) << sat) & value) != 0)
|
||||
{
|
||||
result = 0xFFFFFFFF >> (32 - sat);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = value;
|
||||
}
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Unsigned Saturate for internal use
|
||||
\details Saturates an unsigned value, should not call directly.
|
||||
\param [in] value Value to be saturated
|
||||
\param [in] sat Bit position to saturate to (0..31)
|
||||
\return Saturated value
|
||||
*/
|
||||
__ALWAYS_INLINE uint32_t __IUSAT(uint32_t value, uint32_t sat)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
if (value & 0x80000000) /* only overflow set bit-31 */
|
||||
{
|
||||
result = 0;
|
||||
}
|
||||
else if ((((0xFFFFFFFF >> sat) << sat) & value) != 0)
|
||||
{
|
||||
result = 0xFFFFFFFF >> (32 - sat);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = value;
|
||||
}
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Rotate Right with Extend
|
||||
\details This function moves each bit of a bitstring right by one bit.
|
||||
The carry input is shifted in at the left end of the bitstring.
|
||||
\note carry input will always 0.
|
||||
\param [in] op1 Value to rotate
|
||||
\return Rotated value
|
||||
*/
|
||||
__ALWAYS_INLINE uint32_t __RRX(uint32_t op1)
|
||||
{
|
||||
#if (__CK80X >= 2)
|
||||
uint32_t res = 0;
|
||||
__ASM volatile("bgeni t0, 31\n\t"
|
||||
"lsri %0, 1\n\t"
|
||||
"movt %1, t0\n\t"
|
||||
"or %1, %1, %0\n\t"
|
||||
: "=r"(op1), "=r"(res): "0"(op1), "1"(res): "t0");
|
||||
return res;
|
||||
#else
|
||||
uint32_t res = 0;
|
||||
__ASM volatile("movi r7, 0\n\t"
|
||||
"bseti r7, 31\n\t"
|
||||
"lsri %0, 1\n\t"
|
||||
"bf 1f\n\t"
|
||||
"mov %1, r7\n\t"
|
||||
"1:\n\t"
|
||||
"or %1, %1, %0\n\t"
|
||||
: "=r"(op1), "=r"(res): "0"(op1), "1"(res): "r7");
|
||||
return res;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
\brief LDRT Unprivileged (8 bit)
|
||||
\details Executes a Unprivileged LDRT instruction for 8 bit value.
|
||||
\param [in] addr Pointer to location
|
||||
\return value of type uint8_t at (*ptr)
|
||||
*/
|
||||
__ALWAYS_INLINE uint8_t __LDRBT(volatile uint8_t *addr)
|
||||
{
|
||||
uint32_t result;
|
||||
//#warning "__LDRBT"
|
||||
__ASM volatile("ldb %0, (%1, 0)" : "=r"(result) : "r"(addr));
|
||||
return ((uint8_t) result); /* Add explicit type cast here */
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief LDRT Unprivileged (16 bit)
|
||||
\details Executes a Unprivileged LDRT instruction for 16 bit values.
|
||||
\param [in] addr Pointer to location
|
||||
\return value of type uint16_t at (*ptr)
|
||||
*/
|
||||
__ALWAYS_INLINE uint16_t __LDRHT(volatile uint16_t *addr)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
//#warning "__LDRHT"
|
||||
__ASM volatile("ldh %0, (%1, 0)" : "=r"(result) : "r"(addr));
|
||||
return ((uint16_t) result); /* Add explicit type cast here */
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief LDRT Unprivileged (32 bit)
|
||||
\details Executes a Unprivileged LDRT instruction for 32 bit values.
|
||||
\param [in] addr Pointer to location
|
||||
\return value of type uint32_t at (*ptr)
|
||||
*/
|
||||
__ALWAYS_INLINE uint32_t __LDRT(volatile uint32_t *addr)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
//#warning "__LDRT"
|
||||
__ASM volatile("ldw %0, (%1, 0)" : "=r"(result) : "r"(addr));
|
||||
return (result);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief STRT Unprivileged (8 bit)
|
||||
\details Executes a Unprivileged STRT instruction for 8 bit values.
|
||||
\param [in] value Value to store
|
||||
\param [in] addr Pointer to location
|
||||
*/
|
||||
__ALWAYS_INLINE void __STRBT(uint8_t value, volatile uint8_t *addr)
|
||||
{
|
||||
//#warning "__STRBT"
|
||||
__ASM volatile("stb %1, (%0, 0)" :: "r"(addr), "r"((uint32_t)value) : "memory");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief STRT Unprivileged (16 bit)
|
||||
\details Executes a Unprivileged STRT instruction for 16 bit values.
|
||||
\param [in] value Value to store
|
||||
\param [in] addr Pointer to location
|
||||
*/
|
||||
__ALWAYS_INLINE void __STRHT(uint16_t value, volatile uint16_t *addr)
|
||||
{
|
||||
//#warning "__STRHT"
|
||||
__ASM volatile("sth %1, (%0, 0)" :: "r"(addr), "r"((uint32_t)value) : "memory");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief STRT Unprivileged (32 bit)
|
||||
\details Executes a Unprivileged STRT instruction for 32 bit values.
|
||||
\param [in] value Value to store
|
||||
\param [in] addr Pointer to location
|
||||
*/
|
||||
__ALWAYS_INLINE void __STRT(uint32_t value, volatile uint32_t *addr)
|
||||
{
|
||||
//#warning "__STRT"
|
||||
__ASM volatile("stw %1, (%0, 0)" :: "r"(addr), "r"(value) : "memory");
|
||||
}
|
||||
|
||||
/*@}*/ /* end of group CSI_Core_InstructionInterface */
|
||||
|
||||
|
||||
/* ########################## FPU functions #################################### */
|
||||
|
||||
/**
|
||||
\brief get FPU type
|
||||
\details returns the FPU type, always 0.
|
||||
\returns
|
||||
- \b 0: No FPU
|
||||
- \b 1: Single precision FPU
|
||||
- \b 2: Double + Single precision FPU
|
||||
*/
|
||||
__ALWAYS_INLINE uint32_t __get_FPUType(void)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile("mfcr %0, cr<13, 0>" : "=r"(result));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#endif /* _CSI_INSTR_H_ */
|
||||
366
libcpu/c-sky/common/csi_reg.h
Normal file
366
libcpu/c-sky/common/csi_reg.h
Normal file
@@ -0,0 +1,366 @@
|
||||
/*
|
||||
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
|
||||
*
|
||||
* Licensed 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.
|
||||
*/
|
||||
|
||||
/******************************************************************************
|
||||
* @file csi_reg.h
|
||||
* @brief CSI Header File for reg.
|
||||
* @version V1.0
|
||||
* @date 02. June 2017
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef _CSI_REG_H_
|
||||
#define _CSI_REG_H_
|
||||
|
||||
#include<csi_gcc.h>
|
||||
|
||||
/**
|
||||
\brief Enable IRQ Interrupts
|
||||
\details Enables IRQ interrupts by setting the IE-bit in the PSR.
|
||||
Can only be executed in Privileged modes.
|
||||
*/
|
||||
__ALWAYS_INLINE void __enable_irq(void)
|
||||
{
|
||||
__ASM volatile("psrset ie");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
\brief Disable IRQ Interrupts
|
||||
\details Disables IRQ interrupts by clearing the IE-bit in the PSR.
|
||||
Can only be executed in Privileged modes.
|
||||
*/
|
||||
__ALWAYS_INLINE void __disable_irq(void)
|
||||
{
|
||||
__ASM volatile("psrclr ie");
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Get PSR
|
||||
\details Returns the content of the PSR Register.
|
||||
\return PSR Register value
|
||||
*/
|
||||
__ALWAYS_INLINE uint32_t __get_PSR(void)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile("mfcr %0, psr" : "=r"(result));
|
||||
return (result);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Set PSR
|
||||
\details Writes the given value to the PSR Register.
|
||||
\param [in] psr PSR Register value to set
|
||||
*/
|
||||
__ALWAYS_INLINE void __set_PSR(uint32_t psr)
|
||||
{
|
||||
__ASM volatile("mtcr %0, psr" : : "r"(psr));
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Get SP
|
||||
\details Returns the content of the SP Register.
|
||||
\return SP Register value
|
||||
*/
|
||||
__ALWAYS_INLINE uint32_t __get_SP(void)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile("mov %0, sp" : "=r"(result));
|
||||
return (result);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Set SP
|
||||
\details Writes the given value to the SP Register.
|
||||
\param [in] sp SP Register value to set
|
||||
*/
|
||||
__ALWAYS_INLINE void __set_SP(uint32_t sp)
|
||||
{
|
||||
__ASM volatile("mov sp, %0" : : "r"(sp): "sp");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Get VBR Register
|
||||
\details Returns the content of the VBR Register.
|
||||
\return VBR Register value
|
||||
*/
|
||||
__ALWAYS_INLINE uint32_t __get_VBR(void)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile("mfcr %0, vbr" : "=r"(result));
|
||||
return (result);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Set VBR
|
||||
\details Writes the given value to the VBR Register.
|
||||
\param [in] vbr VBR Register value to set
|
||||
*/
|
||||
__ALWAYS_INLINE void __set_VBR(uint32_t vbr)
|
||||
{
|
||||
__ASM volatile("mtcr %0, vbr" : : "r"(vbr));
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Get EPC Register
|
||||
\details Returns the content of the EPC Register.
|
||||
\return EPC Register value
|
||||
*/
|
||||
__ALWAYS_INLINE uint32_t __get_EPC(void)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile("mfcr %0, epc" : "=r"(result));
|
||||
return (result);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Set EPC
|
||||
\details Writes the given value to the EPC Register.
|
||||
\param [in] epc EPC Register value to set
|
||||
*/
|
||||
__ALWAYS_INLINE void __set_EPC(uint32_t epc)
|
||||
{
|
||||
__ASM volatile("mtcr %0, epc" : : "r"(epc));
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Get EPSR
|
||||
\details Returns the content of the EPSR Register.
|
||||
\return EPSR Register value
|
||||
*/
|
||||
__ALWAYS_INLINE uint32_t __get_EPSR(void)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile("mfcr %0, epsr" : "=r"(result));
|
||||
return (result);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Set EPSR
|
||||
\details Writes the given value to the EPSR Register.
|
||||
\param [in] epsr EPSR Register value to set
|
||||
*/
|
||||
__ALWAYS_INLINE void __set_EPSR(uint32_t epsr)
|
||||
{
|
||||
__ASM volatile("mtcr %0, epsr" : : "r"(epsr));
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Get CPUID Register
|
||||
\details Returns the content of the CPUID Register.
|
||||
\return CPUID Register value
|
||||
*/
|
||||
__ALWAYS_INLINE uint32_t __get_CPUID(void)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile("mfcr %0, cr<13, 0>" : "=r"(result));
|
||||
return (result);
|
||||
}
|
||||
|
||||
#if (__SOFTRESET_PRESENT == 1U)
|
||||
/**
|
||||
\brief Set SRCR
|
||||
\details Assigns the given value to the SRCR.
|
||||
\param [in] srcr SRCR value to set
|
||||
*/
|
||||
__ALWAYS_INLINE void __set_SRCR(uint32_t srcr)
|
||||
{
|
||||
__ASM volatile("mtcr %0, cr<31, 0>\n" : : "r"(srcr));
|
||||
}
|
||||
#endif /* __SOFTRESET_PRESENT == 1U */
|
||||
|
||||
#if (__MGU_PRESENT == 1U)
|
||||
/**
|
||||
\brief Get CCR
|
||||
\details Returns the current value of the CCR.
|
||||
\return CCR Register value
|
||||
*/
|
||||
__ALWAYS_INLINE uint32_t __get_CCR(void)
|
||||
{
|
||||
register uint32_t result;
|
||||
|
||||
__ASM volatile("mfcr %0, cr<18, 0>\n" : "=r"(result));
|
||||
return (result);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Set CCR
|
||||
\details Assigns the given value to the CCR.
|
||||
\param [in] ccr CCR value to set
|
||||
*/
|
||||
__ALWAYS_INLINE void __set_CCR(uint32_t ccr)
|
||||
{
|
||||
__ASM volatile("mtcr %0, cr<18, 0>\n" : : "r"(ccr));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Get CAPR
|
||||
\details Returns the current value of the CAPR.
|
||||
\return CAPR Register value
|
||||
*/
|
||||
__ALWAYS_INLINE uint32_t __get_CAPR(void)
|
||||
{
|
||||
register uint32_t result;
|
||||
|
||||
__ASM volatile("mfcr %0, cr<19, 0>\n" : "=r"(result));
|
||||
return (result);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Set CAPR
|
||||
\details Assigns the given value to the CAPR.
|
||||
\param [in] capr CAPR value to set
|
||||
*/
|
||||
__ALWAYS_INLINE void __set_CAPR(uint32_t capr)
|
||||
{
|
||||
__ASM volatile("mtcr %0, cr<19, 0>\n" : : "r"(capr));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Set PACR
|
||||
\details Assigns the given value to the PACR.
|
||||
|
||||
\param [in] pacr PACR value to set
|
||||
*/
|
||||
__ALWAYS_INLINE void __set_PACR(uint32_t pacr)
|
||||
{
|
||||
__ASM volatile("mtcr %0, cr<20, 0>\n" : : "r"(pacr));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Get PACR
|
||||
\details Returns the current value of PACR.
|
||||
\return PACR value
|
||||
*/
|
||||
__ALWAYS_INLINE uint32_t __get_PACR(void)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile("mfcr %0, cr<20, 0>" : "=r"(result));
|
||||
return (result);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Set PRSR
|
||||
\details Assigns the given value to the PRSR.
|
||||
|
||||
\param [in] prsr PRSR value to set
|
||||
*/
|
||||
__ALWAYS_INLINE void __set_PRSR(uint32_t prsr)
|
||||
{
|
||||
__ASM volatile("mtcr %0, cr<21, 0>\n" : : "r"(prsr));
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Get PRSR
|
||||
\details Returns the current value of PRSR.
|
||||
\return PRSR value
|
||||
*/
|
||||
__ALWAYS_INLINE uint32_t __get_PRSR(void)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile("mfcr %0, cr<21, 0>" : "=r"(result));
|
||||
return (result);
|
||||
}
|
||||
#endif /* __MGU_PRESENT == 1U */
|
||||
|
||||
/**
|
||||
\brief Get user sp
|
||||
\details Returns the current value of user r14.
|
||||
\return UR14 value
|
||||
*/
|
||||
__ALWAYS_INLINE uint32_t __get_UR14(void)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile("mfcr %0, cr<14, 1>" : "=r"(result));
|
||||
return (result);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Enable interrupts and exceptions
|
||||
\details Enables interrupts and exceptions by setting the IE-bit and EE-bit in the PSR.
|
||||
Can only be executed in Privileged modes.
|
||||
*/
|
||||
__ALWAYS_INLINE void __enable_excp_irq(void)
|
||||
{
|
||||
__ASM volatile("psrset ee, ie");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Disable interrupts and exceptions
|
||||
\details Disables interrupts and exceptions by clearing the IE-bit and EE-bit in the PSR.
|
||||
Can only be executed in Privileged modes.
|
||||
*/
|
||||
__ALWAYS_INLINE void __disable_excp_irq(void)
|
||||
{
|
||||
__ASM volatile("psrclr ee, ie");
|
||||
}
|
||||
|
||||
#if (__GSR_GCR_PRESENT == 1U)
|
||||
/**
|
||||
\brief Get GSR
|
||||
\details Returns the content of the GSR Register.
|
||||
\return GSR Register value
|
||||
*/
|
||||
__ALWAYS_INLINE uint32_t __get_GSR(void)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile("mfcr %0, cr<12, 0>" : "=r"(result));
|
||||
return (result);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Get GCR
|
||||
\details Returns the content of the GCR Register.
|
||||
\return GCR Register value
|
||||
*/
|
||||
__ALWAYS_INLINE uint32_t __get_GCR(void)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile("mfcr %0, cr<11, 0>" : "=r"(result));
|
||||
return (result);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Set GCR
|
||||
\details Writes the given value to the GCR Register.
|
||||
\param [in] gcr GCR Register value to set
|
||||
*/
|
||||
__ALWAYS_INLINE void __set_GCR(uint32_t gcr)
|
||||
{
|
||||
__ASM volatile("mtcr %0, cr<11, 0>" : : "r"(gcr));
|
||||
}
|
||||
|
||||
#endif /* (__GSR_GCR_PRESENT == 1U) */
|
||||
|
||||
|
||||
#endif /* _CSI_REG_H_ */
|
||||
1483
libcpu/c-sky/common/csi_simd.h
Normal file
1483
libcpu/c-sky/common/csi_simd.h
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user