Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/index.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
* \defgroup hardware_clocks hardware_clocks
* \defgroup hardware_divider hardware_divider
* \defgroup hardware_dma hardware_dma
* \defgroup hardware_exception hardware_exception
* \defgroup hardware_flash hardware_flash
* \defgroup hardware_gpio hardware_gpio
* \defgroup hardware_i2c hardware_i2c
Expand Down
1 change: 1 addition & 0 deletions src/rp2_common/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ pico_add_subdirectory(hardware_adc)
pico_add_subdirectory(hardware_clocks)
pico_add_subdirectory(hardware_dma)
pico_add_subdirectory(hardware_divider)
pico_add_subdirectory(hardware_exception)
pico_add_subdirectory(hardware_flash)
pico_add_subdirectory(hardware_gpio)
pico_add_subdirectory(hardware_i2c)
Expand Down
1 change: 1 addition & 0 deletions src/rp2_common/hardware_exception/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pico_simple_hardware_target(exception)
65 changes: 65 additions & 0 deletions src/rp2_common/hardware_exception/exception.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/

#include "hardware/exception.h"
#include "hardware/regs/m0plus.h"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only a minor nit-pick, but this is already included in hardware/exception.h

#include "hardware/platform_defs.h"
#include "hardware/structs/scb.h"

#include "pico/mutex.h"
#include "pico/assert.h"

#ifndef exception_is_compile_time_default
static bool exception_is_compile_time_default(exception_handler_t handler) {
extern char __default_isrs_start;
extern char __default_isrs_end;
return ((uintptr_t)handler) >= (uintptr_t)&__default_isrs_start &&
((uintptr_t)handler) < (uintptr_t)&__default_isrs_end;
}
#endif

static inline exception_handler_t *get_vtable(void) {
return (exception_handler_t *) scb_hw->vtor;
}

static void set_raw_exception_handler_and_restore_interrupts(enum exception_number num, exception_handler_t handler, uint32_t save) {
// update vtable (vtable_handler may be same or updated depending on cases, but we do it anyway for compactness)
get_vtable()[16 + num] = handler;
__dmb();
restore_interrupts(save);
}

static inline void check_exception_param(__unused enum exception_number num) {
invalid_params_if(EXCEPTION, num < NMI_EXCEPTION || num >=0);
}

exception_handler_t exception_get_vtable_handler(enum exception_number num) {
check_exception_param(num);
return get_vtable()[16 + num];
}

exception_handler_t exception_set_exclusive_handler(enum exception_number num, exception_handler_t handler) {
check_exception_param(num);
#if !PICO_NO_RAM_VECTOR_TABLE
uint32_t save = save_and_disable_interrupts();
exception_handler_t current = exception_get_vtable_handler(num);
hard_assert(exception_is_compile_time_default(current));
set_raw_exception_handler_and_restore_interrupts(num, handler, save);
#else
panic_unsupported();
#endif
return current;
}

void exception_restore_handler(enum exception_number num, exception_handler_t original_handler) {
hard_assert(exception_is_compile_time_default(original_handler));
#if !PICO_NO_RAM_VECTOR_TABLE
uint32_t save = save_and_disable_interrupts();
set_raw_exception_handler_and_restore_interrupts(num, original_handler, save);
#else
panic_unsupported();
#endif
}
106 changes: 106 additions & 0 deletions src/rp2_common/hardware_exception/include/hardware/exception.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/*
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/

#ifndef _HARDWARE_EXCEPTION_H_
#define _HARDWARE_EXCEPTION_H_

#include "pico.h"
#include "hardware/address_mapped.h"
#include "hardware/regs/m0plus.h"

/** \file exception.h
* \defgroup hardware_exception hardware_exception
*
* Methods for setting processor exception handlers
*
* Exceptions are identified by a \ref exception_num which is a number from -15 to -1; these are the numbers relative to
* the index of the first IRQ vector in the vector table. (i.e. vector table index is exception_num plus 16)
*
* There is one set of exception handlers per core, so the exception handlers for each core as set by these methods are independent.
*
* \note That all exception APIs affect the executing core only (i.e. the core calling the function).
*/

// PICO_CONFIG: PARAM_ASSERTIONS_ENABLED_EXCEPTION, Enable/disable assertions in the exception module, type=bool, default=0, group=hardware_exception
#ifndef PARAM_ASSERTIONS_ENABLED_EXCEPTION
#define PARAM_ASSERTIONS_ENABLED_EXCEPTION 0
#endif

#ifdef __cplusplus
extern "C" {
#endif

/*! \brief Exception number definitions
*
* Note for consistency with irq numbers, these numbers are defined to be negative. The VTABLE index is
* the number here plus 16.
*
* Name | Value | Exception
* ---------------------|-------|----------
* NMI_EXCEPTION | -14 | Non Maskable Interrupt
* HARDFAULT_EXCEPTION | -13 | HardFault
* SVCALL_EXCEPTION | -5 | SV Call
* PENDSV_EXCEPTION | -2 | Pend SV
* SYSTICK_EXCEPTION | -1 | System Tick
*
* \ingroup hardware_exception
*/
enum exception_number {
NMI_EXCEPTION = -14, /* Non Maskable Interrupt */
HARDFAULT_EXCEPTION = -13, /* HardFault Interrupt */
SVCALL_EXCEPTION = -5, /* SV Call Interrupt */
PENDSV_EXCEPTION = -2, /* Pend SV Interrupt */
SYSTICK_EXCEPTION = -1, /* System Tick Interrupt */
};
Comment on lines +51 to +57
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens for numbers outside of this list, e.g. -3 ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

they continue to exist

you can set handlers for them, but there is no point


/*! \brief Exception handler function type
* \ingroup hardware_exception
*
* All exceptions handlers should be of this type, and follow normal ARM EABI register saving conventions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"exceptions handlers" -> "exception handlers"

*/
typedef void (*exception_handler_t)(void);

/*! \brief Set the exception handler for an exception on the executing core.
* \ingroup hardware_exception
*
* This method will assert if an exception handler has been set for this exception number on this core via
* this method, without an intervening restore via exception_restore_handler.
*
* \note this method may not be used to override an exception handler that was specified at link time by
* providing a strong replacement for the weakly defined stub exception handlers. It will assert in this case too.
*
* \param num Exception number
* \param handler The handler to set
* \see exception_number
*/
exception_handler_t exception_set_exclusive_handler(enum exception_number num, exception_handler_t handler);

/*! \brief Restore the original exception handler for an exception on this core
* \ingroup hardware_exception
*
* This method may be used to restore the exception handler for an exception on this core to the state
* prior to the call to exception_set_exclusive_handler(), so that exception_set_exclusive_handler()
* may be called again in the future.
*
* \param num Exception number \ref exception_nums
* \param original_handler The original handler returned from \ref exception_set_exclusive_handler
* \see exception_set_exclusive_handler()
*/
void exception_restore_handler(enum exception_number, exception_handler_t original_handler);

/*! \brief Get the current exception handler for the specified exception from the currently installed vector table
* of the execution core
* \ingroup hardware_exception
*
* \param num Exception number
* \return the address stored in the VTABLE for the given exception number
*/
exception_handler_t exception_get_vtable_handler(enum exception_number num);
#ifdef __cplusplus
}
#endif

#endif
2 changes: 1 addition & 1 deletion src/rp2_common/hardware_irq/include/hardware/irq.h
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ static inline void irq_clear(uint int_num) {
void irq_set_pending(uint num);


/*! \brief Perform IRQ priority intiialization for the current core
/*! \brief Perform IRQ priority initialization for the current core
*
* \note This is an internal method and user should generally not call it.
*/
Expand Down
8 changes: 8 additions & 0 deletions src/rp2_common/pico_standard_link/crt0.S
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,11 @@ __vectors:
.word isr_irq30
.word isr_irq31

// all default exception handlers do nothing, and we can check for them being set to our
// default values by them pointing to between __defaults_isrs_start and __default_isrs_end
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I initially thought "by them pointing to" was a typo for "by pointing them to", but then I reread it a couple of times and figured out what it actually meant 😉
Perhaps "by seeing if they point to somewhere" would be clearer?

.global __default_isrs_start
__default_isrs_start:

// Declare a weak symbol for each ISR.
// By default, they will fall through to the undefined IRQ handler below (breakpoint),
// but can be overridden by C functions with correct name.
Expand All @@ -94,6 +99,9 @@ decl_isr_bkpt isr_svcall
decl_isr_bkpt isr_pendsv
decl_isr_bkpt isr_systick

.global __default_isrs_end
__default_isrs_end:

.macro decl_isr name
.weak \name
.type \name,%function
Expand Down
1 change: 1 addition & 0 deletions test/kitchen_sink/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ target_link_libraries(kitchen_sink_libs INTERFACE
hardware_adc
hardware_clocks
hardware_divider
hardware_exception
hardware_dma
hardware_flash
hardware_gpio
Expand Down
1 change: 1 addition & 0 deletions test/kitchen_sink/kitchen_sink.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "hardware/clocks.h"
#include "hardware/divider.h"
#include "hardware/dma.h"
#include "hardware/exception.h"
#include "hardware/flash.h"
#include "hardware/gpio.h"
#include "hardware/i2c.h"
Expand Down