diff options
Diffstat (limited to '')
-rw-r--r-- | cpukit/score/cpu/microblaze/cpu.c | 290 |
1 files changed, 160 insertions, 130 deletions
diff --git a/cpukit/score/cpu/microblaze/cpu.c b/cpukit/score/cpu/microblaze/cpu.c index ca4a3ec2f6..823825d2b1 100644 --- a/cpukit/score/cpu/microblaze/cpu.c +++ b/cpukit/score/cpu/microblaze/cpu.c @@ -1,7 +1,16 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file + * + * @ingroup RTEMSScoreCPUMicroBlaze + * + * @brief MicroBlaze architecture support implementation + */ + /* - * Copyright (c) 2015, Hesham Almatary - * COPYRIGHT (c) 1989-2011. - * On-Line Applications Research Corporation (OAR). + * Copyright (c) 2015, Hesham Almatary + * Copyright (C) 2021 On-Line Applications Research Corporation (OAR) * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -9,8 +18,8 @@ * 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. + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE @@ -29,31 +38,16 @@ #include "config.h" #endif -#include <rtems/system.h> +#include <inttypes.h> + +#include <rtems/bspIo.h> +#include <rtems/fatal.h> #include <rtems/score/isr.h> +#include <rtems/score/tls.h> #include <rtems/score/wkspace.h> -/* _CPU_Initialize - * - * This routine performs processor dependent initialization. - * - * INPUT PARAMETERS: NONE - * - * NO_CPU Specific Information: - * - * XXX document implementation including references if appropriate - */ - -void _CPU_Initialize(void) +void _CPU_Initialize( void ) { - /* - * If there is not an easy way to initialize the FP context - * during Context_Initialize, then it is usually easier to - * save an "uninitialized" FP context here and copy it to - * the task's during Context_Initialize. - */ - - /* FP context initialization support goes here */ } void _CPU_Context_Initialize( @@ -66,136 +60,172 @@ void _CPU_Context_Initialize( void *tls_area ) { - uint32_t stack = ((uint32_t) stack_area_begin); + uint32_t stack = (uint32_t) stack_area_begin; uint32_t stack_high = stack + stack_area_size; - memset(context, 0, sizeof(*context)); + memset( context, 0, sizeof(*context) ) ; + + context->r1 = stack_high - 64; + context->r15 = (uint32_t) entry_point; - context->r[0] = stack_high; - context->r[3] = (uint32_t) entry_point; + uint32_t msr; + _CPU_MSR_GET( msr ); + context->rmsr = msr; + + if ( tls_area != NULL ) { + context->thread_pointer = _TLS_Initialize_area( tls_area ); + } } -/*PAGE - * - * _CPU_ISR_Get_level - * - * NO_CPU Specific Information: - * - * XXX document implementation including references if appropriate - */ +void _CPU_Exception_frame_print( const CPU_Exception_frame *ctx ) +{ + printk( + "\n" + "R0 = 0x%08" PRIx32 " R17 = %p\n" + "R1 = 0x%08" PRIx32 " R18 = 0x%08" PRIx32 "\n" + "R2 = 0x%08" PRIx32 " R19 = 0x%08" PRIx32 "\n" + "R3 = 0x%08" PRIx32 " R20 = 0x%08" PRIx32 "\n" + "R4 = 0x%08" PRIx32 " R21 = 0x%08" PRIx32 "\n" + "R5 = 0x%08" PRIx32 " R22 = 0x%08" PRIx32 "\n" + "R6 = 0x%08" PRIx32 " R23 = 0x%08" PRIx32 "\n" + "R7 = 0x%08" PRIx32 " R24 = 0x%08" PRIx32 "\n" + "R8 = 0x%08" PRIx32 " R25 = 0x%08" PRIx32 "\n" + "R9 = 0x%08" PRIx32 " R26 = 0x%08" PRIx32 "\n" + "R10 = 0x%08" PRIx32 " R27 = 0x%08" PRIx32 "\n" + "R11 = 0x%08" PRIx32 " R28 = 0x%08" PRIx32 "\n" + "R12 = 0x%08" PRIx32 " R29 = 0x%08" PRIx32 "\n" + "R13 = 0x%08" PRIx32 " R30 = 0x%08" PRIx32 "\n" + "R14 = %p" " R31 = 0x%08" PRIx32 "\n" + "R15 = %p" " ESR = 0x%08" PRIx32 "\n" + "R16 = %p" " EAR = %p\n", + 0, ctx->r17, + ctx->r1, ctx->r18, + ctx->r2, ctx->r19, + ctx->r3, ctx->r20, + ctx->r4, ctx->r21, + ctx->r5, ctx->r22, + ctx->r6, ctx->r23, + ctx->r7, ctx->r24, + ctx->r8, ctx->r25, + ctx->r9, ctx->r26, + ctx->r10, ctx->r27, + ctx->r11, ctx->r28, + ctx->r12, ctx->r29, + ctx->r13, ctx->r30, + ctx->r14, ctx->r31, + ctx->r15, ctx->esr, + ctx->r16, ctx->ear + ); + + printk( + "MSR = 0x%08" PRIx32 " %s%s%s%s%s%s%s%s%s%s%s%s\n", + ctx->msr, + ( ctx->msr & MICROBLAZE_MSR_VM ) ? "VM " : "", + ( ctx->msr & MICROBLAZE_MSR_UM ) ? "UM " : "", + ( ctx->msr & MICROBLAZE_MSR_PVR ) ? "PVR " : "", + ( ctx->msr & MICROBLAZE_MSR_EIP ) ? "EiP " : "", + ( ctx->msr & MICROBLAZE_MSR_EE ) ? "EE " : "", + ( ctx->msr & MICROBLAZE_MSR_DCE ) ? "DCE " : "", + ( ctx->msr & MICROBLAZE_MSR_DZO ) ? "DZO " : "", + ( ctx->msr & MICROBLAZE_MSR_ICE ) ? "ICE " : "", + ( ctx->msr & MICROBLAZE_MSR_FSL ) ? "FSL " : "", + ( ctx->msr & MICROBLAZE_MSR_BIP ) ? "BiP " : "", + ( ctx->msr & MICROBLAZE_MSR_C ) ? "C " : "", + ( ctx->msr & MICROBLAZE_MSR_IE ) ? "IE " : "" + ); +} -uint32_t _CPU_ISR_Get_level( void ) +void _CPU_ISR_Set_level( uint32_t level ) { - /* - * This routine returns the current interrupt level. - */ + uint32_t microblaze_switch_reg; - return 0; -} + _CPU_MSR_GET( microblaze_switch_reg ); -/*PAGE - * - * _CPU_ISR_install_raw_handler - * - * NO_CPU Specific Information: - * - * XXX document implementation including references if appropriate - */ + if ( level == 0 ) { + microblaze_switch_reg |= MICROBLAZE_MSR_IE; + } else { + microblaze_switch_reg &= ~(MICROBLAZE_MSR_IE); + } -void _CPU_ISR_install_raw_handler( - uint32_t vector, - proc_ptr new_handler, - proc_ptr *old_handler -) -{ - /* - * This is where we install the interrupt handler into the "raw" interrupt - * table used by the CPU to dispatch interrupt handlers. - */ + _CPU_MSR_SET( microblaze_switch_reg ); } -/*PAGE - * - * _CPU_ISR_install_vector - * - * This kernel routine installs the RTEMS handler for the - * specified vector. - * - * Input parameters: - * vector - interrupt vector number - * old_handler - former ISR for this vector number - * new_handler - replacement ISR for this vector number - * - * Output parameters: NONE - * - * - * NO_CPU Specific Information: - * - * XXX document implementation including references if appropriate - */ +uint32_t _CPU_ISR_Get_level( void ) +{ + uint32_t level; + + _CPU_MSR_GET( level ); + + /* This is unique. The MSR register contains an interrupt enable flag where + * most other architectures have an interrupt disable flag. */ + return ( level & MICROBLAZE_MSR_IE ) == 0; +} void _CPU_ISR_install_vector( - uint32_t vector, - proc_ptr new_handler, - proc_ptr *old_handler + uint32_t vector, + CPU_ISR_handler new_handler, + CPU_ISR_handler *old_handler ) { - *old_handler = _ISR_Vector_table[ vector ]; + *old_handler = _ISR_Vector_table[ vector ]; + _ISR_Vector_table[ vector ] = new_handler; +} - /* - * If the interrupt vector table is a table of pointer to isr entry - * points, then we need to install the appropriate RTEMS interrupt - * handler for this vector number. - */ +void *_CPU_Thread_Idle_body( uintptr_t ignored ) +{ + while ( true ) { + } +} - _CPU_ISR_install_raw_handler( vector, new_handler, old_handler ); +MicroBlaze_Exception_handler installed_exception_handler = NULL; - /* - * We put the actual user ISR address in '_ISR_vector_table'. This will - * be used by the _ISR_Handler so the user gets control. - */ +void _MicroBlaze_Exception_install_handler( + MicroBlaze_Exception_handler new_handler, + MicroBlaze_Exception_handler *old_handler +) +{ + if ( old_handler != NULL ) { + *old_handler = installed_exception_handler; + } - _ISR_Vector_table[ vector ] = new_handler; + installed_exception_handler = new_handler; } -/*PAGE - * - * _CPU_Install_interrupt_stack - * - * NO_CPU Specific Information: - * - * XXX document implementation including references if appropriate - */ - -void _CPU_Install_interrupt_stack( void ) +void _MicroBlaze_Exception_handle( CPU_Exception_frame *ef ) { + /* EiP is not set for user exceptions which are unused and not hooked */ + if ( + ( ef->msr & MICROBLAZE_MSR_EIP ) != 0 + && installed_exception_handler != NULL + ) { + installed_exception_handler( ef ); + } + + rtems_fatal( RTEMS_FATAL_SOURCE_EXCEPTION, (rtems_fatal_code) ef ); } -/*PAGE - * - * _CPU_Thread_Idle_body - * - * NOTES: - * - * 1. This is the same as the regular CPU independent algorithm. - * - * 2. If you implement this using a "halt", "idle", or "shutdown" - * instruction, then don't forget to put it in an infinite loop. - * - * 3. Be warned. Some processors with onboard DMA have been known - * to stop the DMA if the CPU were put in IDLE mode. This might - * also be a problem with other on-chip peripherals. So use this - * hook with caution. - * - * NO_CPU Specific Information: - * - * XXX document implementation including references if appropriate - */ +MicroBlaze_Exception_handler installed_debug_handler = NULL; -void *_CPU_Thread_Idle_body( uintptr_t ignored ) +void _MicroBlaze_Debug_install_handler( + MicroBlaze_Exception_handler new_handler, + MicroBlaze_Exception_handler *old_handler +) +{ + if ( old_handler != NULL ) { + *old_handler = installed_debug_handler; + } + + installed_debug_handler = new_handler; +} + +void _MicroBlaze_Debug_handle( CPU_Exception_frame *ef ) { + /* BiP is not set for software debug events, set it here */ + ef->msr |= MICROBLAZE_MSR_BIP; + + if ( installed_debug_handler != NULL ) { + installed_debug_handler( ef ); + } - for( ; ; ) - /* insert your "halt" instruction here */ ; - return NULL; + rtems_fatal( RTEMS_FATAL_SOURCE_EXCEPTION, (rtems_fatal_code) ef ); } |