From 95646426fab14aaf58eb6150f51dbd10a9b923f4 Mon Sep 17 00:00:00 2001 From: rtel Date: Tue, 16 Sep 2014 12:24:14 +0000 Subject: [PATCH] SAM4L tickless implementation: Bug fix and update the demo project to exercise the fix. git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@2305 1d2547de-c912-0410-9cb9-b8ca96c0e9e2 --- .../FreeRTOS_Demo.cproj | 284 +++++++--------- .../src/SAM4L_low_power_tick_management.c | 1 + .../CORTEX_M4_ATSAM4L_Atmel_Studio/src/asf.h | 5 +- .../src/asf/sam/drivers/eic/eic.c | 244 ++++++++++++++ .../src/asf/sam/drivers/eic/eic.h | 310 ++++++++++++++++++ .../src/config/conf_board.h | 2 + .../CORTEX_M4_ATSAM4L_Atmel_Studio/src/main.c | 28 ++ 7 files changed, 715 insertions(+), 159 deletions(-) create mode 100644 FreeRTOS/Demo/CORTEX_M4_ATSAM4L_Atmel_Studio/src/asf/sam/drivers/eic/eic.c create mode 100644 FreeRTOS/Demo/CORTEX_M4_ATSAM4L_Atmel_Studio/src/asf/sam/drivers/eic/eic.h diff --git a/FreeRTOS/Demo/CORTEX_M4_ATSAM4L_Atmel_Studio/FreeRTOS_Demo.cproj b/FreeRTOS/Demo/CORTEX_M4_ATSAM4L_Atmel_Studio/FreeRTOS_Demo.cproj index 44f28a52d..ee91e87e1 100644 --- a/FreeRTOS/Demo/CORTEX_M4_ATSAM4L_Atmel_Studio/FreeRTOS_Demo.cproj +++ b/FreeRTOS/Demo/CORTEX_M4_ATSAM4L_Atmel_Studio/FreeRTOS_Demo.cproj @@ -2,7 +2,7 @@ 2.0 - 6.1 + 6.2 com.Atmel.ARMGCC.C {dfc77570-bc67-4ee7-8143-c34e75167169} ATSAM4LC4C @@ -23,120 +23,123 @@ 3.5.1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SWD com.atmel.avrdbg.tool.samice com.atmel.avrdbg.tool.samice J-Link - 000480008423 + 480008423 127.0.0.1 1882 @@ -154,7 +157,7 @@ 0 0 0 - 32000 + 5950000 @@ -202,6 +205,7 @@ ../src ../src/config ../src/asf/sam/drivers/ast + ../src/ASF/sam/drivers/eic Optimize for size (-Os) @@ -226,30 +230,7 @@ -D__ATSAM4LC4C__ -D__ATSAM4LC4C__ -D__ATSAM4LC4C__ -D__ATSAM4LC4C__ -D__ATSAM4LC4C__ -D__ATSAM4LC4C__ - ../src/asf/sam/utils/preprocessor - ../src/asf/sam/drivers/lcdca/example/sam4lc4c_sam4l_ek - ../src/asf/sam/utils/cmsis/sam4l/include - ../src/asf/common/services/sleepmgr - ../src/asf/sam/utils - ../src/asf/common/boards - ../src/asf/sam/drivers/flashcalw - ../src/asf/sam/boards - ../src/asf/common/services/clock - ../src/asf/sam/drivers/bpm - ../src/asf/thirdparty/CMSIS/Include - ../src/asf/sam/boards/sam4l_ek - ../src/asf/sam/utils/header_files - ../src/asf/common/services/ioport - ../src/asf/sam/utils/cmsis/sam4l/source/templates - ../src/asf/common/utils - ../src/asf/thirdparty/CMSIS/Lib/GCC - ../src - ../src/config - ../src/asf/sam/drivers/ast - %24(ToolchainDir)\..\..\CMSIS_Atmel - %24(ToolchainDir)\..\..\CMSIS_Atmel\CMSIS\Include - %24(ToolchainDir)\..\..\CMSIS_Atmel\Device\ATMEL - %24(ToolchainDir)\..\..\CMSIS_Atmel\Device\ATMEL\sam4l\include + ../src/ASF/sam/drivers/eic -DARM_MATH_CM4=true -DBOARD=SAM4L_EK -D__ATSAM4LC4C__ -D__ATSAM4LC4C__ -D__ATSAM4LC4C__ -D__ATSAM4LC4C__ -D__ATSAM4LC4C__ -D__ATSAM4LC4C__ -D__ATSAM4LC4C__ @@ -279,6 +260,7 @@ %24(ToolchainDir)\..\..\CMSIS_Atmel\CMSIS\Include %24(ToolchainDir)\..\..\CMSIS_Atmel\Device\ATMEL %24(ToolchainDir)\..\..\CMSIS_Atmel\Device\ATMEL\sam4l\include + ../src/ASF/sam/drivers/eic @@ -326,6 +308,7 @@ ../../../Source/include ../../../Source/portable/GCC/ARM_CM3 ../../Common/include + ../src/ASF/sam/drivers/eic -fdata-sections @@ -349,30 +332,7 @@ -D__ATSAM4LC4C__ -D__ATSAM4LC4C__ -D__ATSAM4LC4C__ -D__ATSAM4LC4C__ -D__ATSAM4LC4C__ -D__ATSAM4LC4C__ - ../src/asf/sam/utils/preprocessor - ../src/asf/sam/drivers/lcdca/example/sam4lc4c_sam4l_ek - ../src/asf/sam/utils/cmsis/sam4l/include - ../src/asf/common/services/sleepmgr - ../src/asf/sam/utils - ../src/asf/common/boards - ../src/asf/sam/drivers/flashcalw - ../src/asf/sam/boards - ../src/asf/common/services/clock - ../src/asf/sam/drivers/bpm - ../src/asf/thirdparty/CMSIS/Include - ../src/asf/sam/boards/sam4l_ek - ../src/asf/sam/utils/header_files - ../src/asf/common/services/ioport - ../src/asf/sam/utils/cmsis/sam4l/source/templates - ../src/asf/common/utils - ../src/asf/thirdparty/CMSIS/Lib/GCC - ../src - ../src/config - ../src/asf/sam/drivers/ast - %24(ToolchainDir)\..\..\CMSIS_Atmel - %24(ToolchainDir)\..\..\CMSIS_Atmel\CMSIS\Include - %24(ToolchainDir)\..\..\CMSIS_Atmel\Device\ATMEL - %24(ToolchainDir)\..\..\CMSIS_Atmel\Device\ATMEL\sam4l\include + ../src/ASF/sam/drivers/eic Default (-g) @@ -403,6 +363,7 @@ %24(ToolchainDir)\..\..\CMSIS_Atmel\CMSIS\Include %24(ToolchainDir)\..\..\CMSIS_Atmel\Device\ATMEL %24(ToolchainDir)\..\..\CMSIS_Atmel\Device\ATMEL\sam4l\include + ../src/ASF/sam/drivers/eic Default (-Wa,-g) @@ -429,6 +390,7 @@ + @@ -819,6 +781,12 @@ compile src\Common-Demo-Source\semtest.c + + compile + + + compile + compile diff --git a/FreeRTOS/Demo/CORTEX_M4_ATSAM4L_Atmel_Studio/src/SAM4L_low_power_tick_management.c b/FreeRTOS/Demo/CORTEX_M4_ATSAM4L_Atmel_Studio/src/SAM4L_low_power_tick_management.c index 90521d5c3..42a921282 100644 --- a/FreeRTOS/Demo/CORTEX_M4_ATSAM4L_Atmel_Studio/src/SAM4L_low_power_tick_management.c +++ b/FreeRTOS/Demo/CORTEX_M4_ATSAM4L_Atmel_Studio/src/SAM4L_low_power_tick_management.c @@ -377,6 +377,7 @@ enum sleepmgr_mode xSleepMode; ulAlarmValue = ulAlarmValueForOneTick; ulCompleteTickPeriods++; } + ast_write_counter_value( AST, 0 ); ast_write_alarm0_value( AST, ulAlarmValue ); } diff --git a/FreeRTOS/Demo/CORTEX_M4_ATSAM4L_Atmel_Studio/src/asf.h b/FreeRTOS/Demo/CORTEX_M4_ATSAM4L_Atmel_Studio/src/asf.h index 5af623354..7ad1867d2 100644 --- a/FreeRTOS/Demo/CORTEX_M4_ATSAM4L_Atmel_Studio/src/asf.h +++ b/FreeRTOS/Demo/CORTEX_M4_ATSAM4L_Atmel_Studio/src/asf.h @@ -59,6 +59,9 @@ #include #include +// From module: EIC - External Interrupt Controller +#include + // From module: FLASHCALW Controller Software Driver #include @@ -68,7 +71,7 @@ // From module: IOPORT - General purpose I/O service #include -// From module: Interrupt management - SAM3 implementation +// From module: Interrupt management - SAM implementation #include // From module: Part identification macros diff --git a/FreeRTOS/Demo/CORTEX_M4_ATSAM4L_Atmel_Studio/src/asf/sam/drivers/eic/eic.c b/FreeRTOS/Demo/CORTEX_M4_ATSAM4L_Atmel_Studio/src/asf/sam/drivers/eic/eic.c new file mode 100644 index 000000000..409e8ae60 --- /dev/null +++ b/FreeRTOS/Demo/CORTEX_M4_ATSAM4L_Atmel_Studio/src/asf/sam/drivers/eic/eic.c @@ -0,0 +1,244 @@ +/** + * \file + * + * \brief EIC driver for SAM + * + * Copyright (c) 2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ + +#include "eic.h" +#include "sysclk.h" +#include "sleepmgr.h" + +/// @cond 0 +/**INDENT-OFF**/ +#ifdef __cplusplus +extern "C" { +#endif +/**INDENT-ON**/ +/// @endcond + +/** + * \defgroup sam_drivers_eic_group External Interrupt Controller(EIC) + * + * See \ref sam_eic_quickstart. + * + * EIC allows pins to be configured as external interrupts. + * + * @{ + */ + + +/** + * \internal + * \brief EIC callback function pointer array + */ +eic_callback_t eic_callback_pointer[EIC_NUMBER_OF_LINES]; + +/** + * \brief Write the EIC hardware with specified configuration value. + * + * \param eic Base address of the EIC module + * \param eic_line_conf Configuration parameters of the EIC module + * (see \ref eic_line_config) + * \param line_number Number of line to config + */ +void eic_line_set_config(Eic *eic, uint8_t line_number, + struct eic_line_config *eic_line_conf) +{ + /* Set up mode level */ + eic->EIC_MODE = (eic_line_conf->eic_mode == EIC_MODE_LEVEL_TRIGGERED) + ? (eic->EIC_MODE | (1 << line_number)) + : (eic->EIC_MODE & ~(1 << line_number)); + /* Set up edge type */ + eic->EIC_EDGE = (eic_line_conf->eic_edge == EIC_EDGE_RISING_EDGE) + ? (eic->EIC_EDGE | (1 << line_number)) + : (eic->EIC_EDGE & ~(1 << line_number)); + /* Set up level */ + eic->EIC_LEVEL = (eic_line_conf->eic_level == EIC_LEVEL_HIGH_LEVEL) + ? (eic->EIC_LEVEL | (1 << line_number)) + : (eic->EIC_LEVEL & ~(1 << line_number)); + /* Set up if filter is used */ + eic->EIC_FILTER = (eic_line_conf->eic_filter == EIC_FILTER_ENABLED) + ? (eic->EIC_FILTER | (1 << line_number)) + : (eic->EIC_FILTER & ~(1 << line_number)); + /* Set up which mode is used : asynchronous mode/ synchronous mode */ + eic->EIC_ASYNC = (eic_line_conf->eic_async == EIC_ASYNCH_MODE) + ? (eic->EIC_ASYNC | (1 << line_number)) + : (eic->EIC_ASYNC & ~(1 << line_number)); + +} + +/** + * \brief Disable the EIC module + * + * \param eic Base address of the EIC module + */ +void eic_disable(Eic *eic) +{ + sysclk_disable_peripheral_clock(eic); + sleepmgr_unlock_mode(SLEEPMGR_BACKUP); +} + +/** + * \brief Enable the EIC module + * + * \param eic Base address of the EIC module + */ +void eic_enable(Eic *eic) +{ + sysclk_enable_peripheral_clock(eic); + sleepmgr_lock_mode(SLEEPMGR_BACKUP); +} + +/** + * \brief Set callback for given EIC line + * + * \param eic Base address of the EIC module + * \param line_number Number of line. + * \param callback callback function pointer. + * \param irq_line interrupt line. + * \param irq_level interrupt level. + */ +void eic_line_set_callback(Eic *eic, uint8_t line_number, + eic_callback_t callback, uint8_t irq_line, uint8_t irq_level) +{ + eic_callback_pointer[line_number] = callback; + irq_register_handler((IRQn_Type)irq_line, irq_level); + eic_line_enable_interrupt(eic, line_number); +} + +/** + * \internal + * \brief Common EIC line interrupt handler + * + * The optional callback used by the interrupt handler is set by the + * eic_line_set_callback() function. + * + * \param line_number EIC linel number to handle interrupt for + */ +static void eic_line_interrupt(uint8_t line_number) +{ + if (eic_callback_pointer[line_number]) { + eic_callback_pointer[line_number](); + } else { + Assert(false); /* Catch unexpected interrupt */ + } +} + +/** + * \brief Interrupt handler for EIC NMI. + */ +void NMI_Handler(void) +{ + eic_line_interrupt(0); +} + +/** + * \brief Interrupt handler for EIC line 1. + */ +void EIC_1_Handler(void) +{ + eic_line_interrupt(1); +} + +/** + * \brief Interrupt handler for EIC line 2. + */ +void EIC_2_Handler(void) +{ + eic_line_interrupt(2); +} + +/** + * \brief Interrupt handler for EIC line 3. + */ +void EIC_3_Handler(void) +{ + eic_line_interrupt(3); +} + +/** + * \brief Interrupt handler for EIC line 4. + */ +void EIC_4_Handler(void) +{ + eic_line_interrupt(4); +} + +/** + * \brief Interrupt handler for EIC line 5. + */ +void EIC_5_Handler(void) +{ + eic_line_interrupt(5); +} + +/** + * \brief Interrupt handler for EIC line 6. + */ +void EIC_6_Handler(void) +{ + eic_line_interrupt(6); +} + +/** + * \brief Interrupt handler for EIC line 7. + */ +void EIC_7_Handler(void) +{ + eic_line_interrupt(7); +} + +/** + * \brief Interrupt handler for EIC line 8. + */ +void EIC_8_Handler(void) +{ + eic_line_interrupt(8); +} + +//@} + +/// @cond 0 +/**INDENT-OFF**/ +#ifdef __cplusplus +} +#endif +/**INDENT-ON**/ +/// @endcond diff --git a/FreeRTOS/Demo/CORTEX_M4_ATSAM4L_Atmel_Studio/src/asf/sam/drivers/eic/eic.h b/FreeRTOS/Demo/CORTEX_M4_ATSAM4L_Atmel_Studio/src/asf/sam/drivers/eic/eic.h new file mode 100644 index 000000000..09923f20d --- /dev/null +++ b/FreeRTOS/Demo/CORTEX_M4_ATSAM4L_Atmel_Studio/src/asf/sam/drivers/eic/eic.h @@ -0,0 +1,310 @@ +/** + * \file + * + * \brief EIC driver for SAM + * + * Copyright (c) 2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ + +#ifndef EIC_H_INCLUDED +#define EIC_H_INCLUDED + +#include "compiler.h" + +/// @cond 0 +/**INDENT-OFF**/ +#ifdef __cplusplus +extern "C" { +#endif +/**INDENT-ON**/ +/// @endcond + +/** Number of available EIC lines, device dependent. */ +#if SAM4L +#define EIC_NUMBER_OF_LINES 9 +#else +#error 'This device does not support EIC driver' +#endif + +/** \name External Interrupt lines */ +/* @{ */ +#define EXT_NMI 0 +#define EXT_INT1 1 +#define EXT_INT2 2 +#define EXT_INT3 3 +#define EXT_INT4 4 +#define EXT_INT5 5 +#define EXT_INT6 6 +#define EXT_INT7 7 +#define EXT_INT8 8 +/* @} */ + +/** \name Mode Trigger Options */ +/* @{ */ +#define EIC_MODE_EDGE_TRIGGERED 0 +#define EIC_MODE_LEVEL_TRIGGERED 1 +/* @{ */ + +/** \name Edge level Options */ +/* @{ */ +#define EIC_EDGE_FALLING_EDGE 0 +#define EIC_EDGE_RISING_EDGE 1 +/* @{ */ + +/** \name Level Options */ +/* @{ */ +#define EIC_LEVEL_LOW_LEVEL 0 +#define EIC_LEVEL_HIGH_LEVEL 1 +/* @{ */ + +/** \name Filter Options */ +/* @{ */ +#define EIC_FILTER_ENABLED 1 +#define EIC_FILTER_DISABLED 0 +/* @{ */ + +/** \name Synch Mode Options */ +/* @{ */ +#define EIC_SYNCH_MODE 0 +#define EIC_ASYNCH_MODE 1 +/* @{ */ + +/** Configuration parameters of the EIC module. */ +struct eic_line_config { + /** Mode : \ref EIC_MODE_EDGE_TRIGGERED or \ref EIC_MODE_LEVEL_TRIGGERED */ + uint8_t eic_mode; + /** Edge : \ref EIC_EDGE_FALLING_EDGE or \ref EIC_EDGE_RISING_EDGE */ + uint8_t eic_edge; + /** Level : \ref EIC_LEVEL_LOW_LEVEL or \ref EIC_LEVEL_HIGH_LEVEL */ + uint8_t eic_level; + /** Filter: \ref EIC_FILTER_DISABLED or \ref EIC_FILTER_ENABLED */ + uint8_t eic_filter; + /** Async: \ref EIC_ASYNCH_MODEmode or \ref EIC_SYNCH_MODE */ + uint8_t eic_async; +}; + +typedef void (*eic_callback_t)(void); + +void eic_disable(Eic *eic); +void eic_enable(Eic *eic); + +void eic_line_set_config(Eic *eic, uint8_t line_number, + struct eic_line_config *eic_line_conf); + +void eic_line_set_callback(Eic *eic, uint8_t line_number, + eic_callback_t callback, uint8_t irq_line, uint8_t irq_level); + +/** + * \brief Enable the external interrupt on specified line. + * + * \param eic Base address of the EIC module + * \param line_number The number of enabled line + */ +static inline void eic_line_enable(Eic *eic, uint8_t line_number) +{ + eic->EIC_EN = 1 << line_number; +} + +/** + * \brief Disable the external interrupt on specified line. + * + * \param eic Base address of the EIC module + * \param line_number The number of disabled line + */ +static inline void eic_line_disable(Eic *eic, uint8_t line_number) +{ + eic->EIC_DIS = 1 << line_number; +} + +/** + * \brief Tells whether an EIC line is enabled. + * + * \param eic Base address of the EIC module + * \param line_number Line number to test + * + * \return Whether an EIC line is enabled. + */ +static inline bool eic_line_is_enabled(Eic *eic, uint8_t line_number) +{ + return (eic->EIC_CTRL & (1 << line_number)) != 0; +} + +/** + * \brief Enables the external interrupt from specified pin propagate from + * EIC to interrupt controller. + * + * \param eic Base address of the EIC (i.e. EIC). + * \param line_number Line number to test + */ +static inline void eic_line_enable_interrupt(Eic *eic, + uint8_t line_number) +{ + eic->EIC_IER = 1 << line_number; +} + +/** + * \brief Disables the external interrupt from specified pin propagate from + * EIC to interrupt controller. + * + * \param eic Base address of the EIC (i.e. EIC). + * \param line_number Line number to test + */ +static inline void eic_line_disable_interrupt(Eic *eic, + uint8_t line_number) +{ + eic->EIC_IDR = 1 << line_number; + eic->EIC_IMR; +} + +/** + * \brief Tells whether an EIC interrupt line is enabled. + * + * \param eic Base address of the EIC module + * \param line_number Line number to test + * + * \return Whether an EIC interrupt line is enabled. + */ +static inline bool eic_line_interrupt_is_enabled(Eic *eic, + uint8_t line_number) +{ + return (eic->EIC_IMR & (1 << line_number)) != 0; +} + +/** + * \brief Clear the interrupt flag of specified pin. + * Call this function once you've handled the interrupt. + * + * \param eic Base address of the EIC (i.e. EIC). + * \param line_number Line number to test + */ +static inline void eic_line_clear_interrupt(Eic *eic, + uint8_t line_number) +{ + eic->EIC_ICR = 1 << line_number; + eic->EIC_ISR; +} + +/** + * \brief Tells whether an EIC interrupt line is pending. + * + * \param eic Base address of the EIC module + * \param line_number Line number to test + * + * \return Whether an EIC interrupt line is pending. + */ +static inline bool eic_line_interrupt_is_pending(Eic *eic, + uint8_t line_number) +{ + return (eic->EIC_ISR & (1 << line_number)) != 0; +} + +/// @cond 0 +/**INDENT-OFF**/ +#ifdef __cplusplus +} +#endif +/**INDENT-ON**/ +/// @endcond + +/** + * \page sam_eic_quickstart Quickstart guide for SAM EIC driver + * + * This is the quickstart guide for the \ref eic_group "SAM EIC driver", + * with step-by-step instructions on how to configure and use the driver in a + * selection of use cases. + * + * The use cases contain several code fragments. The code fragments in the + * steps for setup can be copied into a custom initialization function, while + * the steps for usage can be copied into, e.g., the main application function. + * + * \section eic_basic_use_case Basic use case + * In this basic use case, the EIC module and single line are configured for: + * - Falling edge trigger and async mode + * - Interrupt-based handling + * - EIC_LINE_5 as input + * + * \subsection sam_eic_quickstart_prereq Prerequisites + * -# \ref sysclk_group "System Clock Management (Sysclock)" + * + * \section eic_basic_use_case_setup Setup steps + * \subsection eic_basic_use_case_setup_code Example code + * Add to application C-file: + * \code + * void eic_callback(void) + * { + * // Check if EIC push button line interrupt line is pending + * if (eic_line_interrupt_is_pending(EIC, GPIO_PUSH_BUTTON_EIC_LINE)) { + * eic_line_clear_interrupt(EIC, GPIO_PUSH_BUTTON_EIC_LINE); + * bToggle = 1; + * } + * } + * void eic_setup(void) + * { + * eic_enable(EIC); + * + * eic_line_set_config(EIC, GPIO_PUSH_BUTTON_EIC_LINE, &eic_line_conf); + * + * eic_line_set_callback(EIC, GPIO_PUSH_BUTTON_EIC_LINE, set_toggle_flag, EIC_5_IRQn, 1); + * + * eic_line_enable(EIC, GPIO_PUSH_BUTTON_EIC_LINE); + * } + * \endcode + * + * \subsection eic_basic_use_case_setup_flow Workflow + * -# Define the interrupt callback function in the application: + * - \code +* void eic_callback(void) + * { + * // Check if EIC push button line interrupt line is pending + * if (eic_line_interrupt_is_pending(EIC, GPIO_PUSH_BUTTON_EIC_LINE)) { + * eic_line_clear_interrupt(EIC, GPIO_PUSH_BUTTON_EIC_LINE); + * bToggle = 1; + * } + * } + * \endcode + * -# Enable EIC module: + * - \code eic_enable(EIC); \endcode + * - \note Including enable module clock and lock sleep mode. + * -# Configure EIC line with specified mode: + * - \code aeic_line_set_config(EIC, GPIO_PUSH_BUTTON_EIC_LINE, &eic_line_conf); \endcode + * -# Set the EIC callback function and enable EIC interrupt. + * - \code eic_line_set_callback(EIC, GPIO_PUSH_BUTTON_EIC_LINE, set_toggle_flag, EIC_5_IRQn, 1); \endcode + * -# Enable EIC line: + * - \code eic_line_enable(EIC, GPIO_PUSH_BUTTON_EIC_LINE); \endcode + */ +#endif // EIC_H_INCLUDED diff --git a/FreeRTOS/Demo/CORTEX_M4_ATSAM4L_Atmel_Studio/src/config/conf_board.h b/FreeRTOS/Demo/CORTEX_M4_ATSAM4L_Atmel_Studio/src/config/conf_board.h index 96e099f05..fe0a502ea 100644 --- a/FreeRTOS/Demo/CORTEX_M4_ATSAM4L_Atmel_Studio/src/config/conf_board.h +++ b/FreeRTOS/Demo/CORTEX_M4_ATSAM4L_Atmel_Studio/src/config/conf_board.h @@ -50,4 +50,6 @@ /** Enable LCD backlight */ #define CONF_BOARD_BL +#define CONF_BOARD_EIC + #endif /* CONF_BOARD_H_INCLUDED */ diff --git a/FreeRTOS/Demo/CORTEX_M4_ATSAM4L_Atmel_Studio/src/main.c b/FreeRTOS/Demo/CORTEX_M4_ATSAM4L_Atmel_Studio/src/main.c index 8ca936e51..3445ceff5 100644 --- a/FreeRTOS/Demo/CORTEX_M4_ATSAM4L_Atmel_Studio/src/main.c +++ b/FreeRTOS/Demo/CORTEX_M4_ATSAM4L_Atmel_Studio/src/main.c @@ -112,6 +112,10 @@ void vApplicationIdleHook( void ); void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName ); void vApplicationTickHook( void ); +/* A handler for a button interrupt. The button's only purpose is to bring the +CPU out of sleep mode early. */ +static void prvButtonISR( void ); + /*-----------------------------------------------------------*/ /* See the documentation page for this demo on the FreeRTOS.org web site for @@ -137,9 +141,33 @@ int main( void ) } /*-----------------------------------------------------------*/ +static void prvButtonISR( void ) +{ + /* The button doesn't do anything other than providing a means for brining + the MCU out of sleep mode early. */ + if( eic_line_interrupt_is_pending( EIC, GPIO_PUSH_BUTTON_EIC_LINE ) ) + { + eic_line_clear_interrupt( EIC, GPIO_PUSH_BUTTON_EIC_LINE ); + } +} +/*-----------------------------------------------------------*/ + static void prvSetupHardware( void ) { extern void SystemCoreClockUpdate( void ); +struct eic_line_config xEICLineConfiguration; + + /* Configure the external interrupt controller so button pushes can + generate interrupts. */ + xEICLineConfiguration.eic_mode = EIC_MODE_EDGE_TRIGGERED; + xEICLineConfiguration.eic_edge = EIC_EDGE_FALLING_EDGE; + xEICLineConfiguration.eic_level = EIC_LEVEL_LOW_LEVEL; + xEICLineConfiguration.eic_filter = EIC_FILTER_DISABLED; + xEICLineConfiguration.eic_async = EIC_ASYNCH_MODE; + eic_enable( EIC ); + eic_line_set_config( EIC, GPIO_PUSH_BUTTON_EIC_LINE, &xEICLineConfiguration ); + eic_line_set_callback( EIC, GPIO_PUSH_BUTTON_EIC_LINE, prvButtonISR, EIC_5_IRQn, 0 ); + eic_line_enable( EIC, GPIO_PUSH_BUTTON_EIC_LINE ); /* ASF function to setup clocking. */ sysclk_init(); -- 2.39.2