diff --git a/boards/arm/nrf52/nrf52840-dk/Kconfig b/boards/arm/nrf52/nrf52840-dk/Kconfig index 52b4e6b2eb..12fe14e155 100644 --- a/boards/arm/nrf52/nrf52840-dk/Kconfig +++ b/boards/arm/nrf52/nrf52840-dk/Kconfig @@ -5,4 +5,8 @@ if ARCH_BOARD_NRF52840_DK +config NRF52840DK_HIGHPRI + bool "High priority interrupt test" + default n + endif diff --git a/boards/arm/nrf52/nrf52840-dk/configs/highpri/defconfig b/boards/arm/nrf52/nrf52840-dk/configs/highpri/defconfig new file mode 100644 index 0000000000..9c35757486 --- /dev/null +++ b/boards/arm/nrf52/nrf52840-dk/configs/highpri/defconfig @@ -0,0 +1,48 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_ARCH_FPU is not set +CONFIG_ARCH="arm" +CONFIG_ARCH_BOARD="nrf52840-dk" +CONFIG_ARCH_BOARD_NRF52840_DK=y +CONFIG_ARCH_CHIP="nrf52" +CONFIG_ARCH_CHIP_NRF52840=y +CONFIG_ARCH_CHIP_NRF52=y +CONFIG_ARCH_HIPRI_INTERRUPT=y +CONFIG_ARCH_RAMVECTORS=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_ARCH_STDARG_H=y +CONFIG_BOARDCTL_MKRD=y +CONFIG_BOARD_LOOPSPERMSEC=5500 +CONFIG_FAT_LCNAMES=y +CONFIG_FAT_LFN=y +CONFIG_FS_FAT=y +CONFIG_LIB_BOARDCTL=y +CONFIG_MAX_TASKS=16 +CONFIG_MAX_WDOGPARMS=2 +CONFIG_MM_REGIONS=2 +CONFIG_NFILE_DESCRIPTORS=8 +CONFIG_NFILE_STREAMS=8 +CONFIG_NRF52840DK_HIGHPRI=y +CONFIG_NRF52_TIMER0=y +CONFIG_NRF52_UART0=y +CONFIG_PREALLOC_MQ_MSGS=4 +CONFIG_PREALLOC_TIMERS=4 +CONFIG_PREALLOC_WDOGS=4 +CONFIG_RAM_SIZE=65535 +CONFIG_RAM_START=0x20000000 +CONFIG_RAW_BINARY=y +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_WAITPID=y +CONFIG_SDCLONE_DISABLE=y +CONFIG_START_DAY=26 +CONFIG_START_MONTH=3 +CONFIG_SYMTAB_ORDEREDBYNAME=y +CONFIG_TASK_NAME_SIZE=0 +CONFIG_UART0_SERIAL_CONSOLE=y +CONFIG_USER_ENTRYPOINT="highpri_main" +CONFIG_WDOG_INTRESERVE=0 diff --git a/boards/arm/nrf52/nrf52840-dk/scripts/flash_config.ld b/boards/arm/nrf52/nrf52840-dk/scripts/flash_config.ld index 23acb1c685..ac347f0b0d 100644 --- a/boards/arm/nrf52/nrf52840-dk/scripts/flash_config.ld +++ b/boards/arm/nrf52/nrf52840-dk/scripts/flash_config.ld @@ -82,6 +82,12 @@ SECTIONS _eronly = ABSOLUTE(.); + /* The RAM vector table (if present) should lie at the beginning of SRAM */ + + .ram_vectors : { + *(.ram_vectors) + } > datamem + .data : { _sdata = ABSOLUTE(.); diff --git a/boards/arm/nrf52/nrf52840-dk/src/Makefile b/boards/arm/nrf52/nrf52840-dk/src/Makefile index 06f3004ffb..08441a6104 100644 --- a/boards/arm/nrf52/nrf52840-dk/src/Makefile +++ b/boards/arm/nrf52/nrf52840-dk/src/Makefile @@ -71,4 +71,8 @@ ifeq ($(CONFIG_LPWAN_SX127X),y) CSRCS += nrf52_sx127x.c endif +ifeq ($(CONFIG_NRF52840DK_HIGHPRI),y) +CSRCS += nrf52_highpri.c +endif + include $(TOPDIR)/boards/Board.mk diff --git a/boards/arm/nrf52/nrf52840-dk/src/nrf52_highpri.c b/boards/arm/nrf52/nrf52840-dk/src/nrf52_highpri.c new file mode 100644 index 0000000000..5420939498 --- /dev/null +++ b/boards/arm/nrf52/nrf52840-dk/src/nrf52_highpri.c @@ -0,0 +1,303 @@ +/**************************************************************************** + * boards/arm/nrf52/nrf52840-dk/src/nrf52_highpri.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include "arm_internal.h" +#include "ram_vectors.h" + +#include "nrf52_tim.h" + +#include + +#ifdef CONFIG_NRF52840DK_HIGHPRI + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ + +#ifndef CONFIG_ARCH_HIPRI_INTERRUPT +# error CONFIG_ARCH_HIPRI_INTERRUPT is required +#endif + +#ifndef CONFIG_ARCH_RAMVECTORS +# error CONFIG_ARCH_RAMVECTORS is required +#endif + +#ifndef CONFIG_ARCH_IRQPRIO +# error CONFIG_ARCH_IRQPRIO is required +#endif + +#ifndef CONFIG_NRF52_TIMER0 +# error CONFIG_NRF52_TIMER0 is required +#endif + +/* Timer configuration */ + +#define NRF52_HIGHPRI_TIMER (0) +#define NRF52_HIGHPRI_TIMER_IRQ (NRF52_IRQ_TIMER0) +#define NRF52_TIMER_PRESCALER (NRF52_TIM_PRE_16000000) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct highpri_s +{ + FAR struct nrf52_tim_dev_s *dev; + volatile uint64_t basepri[16]; + volatile uint64_t handler; + volatile uint64_t thread; +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct highpri_s g_highpri; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: timer_handler + * + * Description: + * This is the handler for the high speed TIMER0 interrupt. + * + ****************************************************************************/ + +void timer_handler(void) +{ + uint8_t basepri; + int index; + int ret; + + /* Verify interrupt source */ + + ret = NRF52_TIM_CHECKINT(g_highpri.dev, NRF52_TIM_CC0); + if (ret != 1) + { + DEBUGASSERT(0); + } + + /* Increment the count associated with the current basepri */ + + basepri = getbasepri(); + index = ((basepri >> 4) & 15); + g_highpri.basepri[index]++; + + /* Check if we are in an interrupt handle */ + + if (up_interrupt_context()) + { + g_highpri.handler++; + } + else + { + g_highpri.thread++; + } + + /* Clear event */ + + NRF52_TIM_ACKINT(g_highpri.dev, NRF52_TIM_CC0); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: highpri_main + * + * Description: + * Main entry point in into the high priority interrupt test. + * + ****************************************************************************/ + +int highpri_main(int argc, char *argv[]) +{ + FAR struct nrf52_tim_dev_s *tim = NULL; + uint64_t basepri[16]; + uint64_t handler; + uint64_t thread; + uint64_t total; + uint32_t seconds; + int ret; + int i; + + /* Initialzie TIMER */ + + tim = nrf52_tim_init(NRF52_HIGHPRI_TIMER); + if (tim == NULL) + { + printf("ERROR: failed to initialize TIMER%d instance\n", + NRF52_HIGHPRI_TIMER); + ret = EXIT_FAILURE; + goto errout; + } + + g_highpri.dev = tim; + + /* Configure TIMER mode and width */ + + ret = NRF52_TIM_CONFIGURE(tim, NRF52_TIM_MODE_TIMER, NRF52_TIM_WIDTH_16B); + if (ret < 0) + { + printf("ERROR: failed to configure timer %d\n", ret); + ret = EXIT_FAILURE; + goto errout; + } + + /* Configure TIMER prescaler */ + + ret = NRF52_TIM_SETPRE(tim, NRF52_TIMER_PRESCALER); + if (ret < 0) + { + printf("ERROR: failed to set timer prescaler %d\n", ret); + ret = EXIT_FAILURE; + goto errout; + } + + /* Set TIMER CC0 */ + + ret = NRF52_TIM_SETCC(tim, NRF52_TIM_CC0, 0x01); + if (ret < 0) + { + printf("ERROR: failed to set TIMER CC %d\n", ret); + ret = EXIT_FAILURE; + goto errout; + } + + /* Enable IRQ for TIMER CC0 */ + + ret = NRF52_TIM_ENABLEINT(tim, NRF52_TIM_INT_COMPARE0); + if (ret < 0) + { + printf("ERROR: failed to enable TIMER0 CC IRQ %d\n", ret); + ret = EXIT_FAILURE; + goto errout; + } + + /* Attach TIMER ram vector */ + + ret = arm_ramvec_attach(NRF52_HIGHPRI_TIMER_IRQ, timer_handler); + if (ret < 0) + { + fprintf(stderr, "highpri_main: ERROR: arm_ramvec_attach failed: %d\n", + ret); + ret = EXIT_FAILURE; + goto errout; + } + + /* Set the priority of the TIM6 interrupt vector */ + + ret = up_prioritize_irq(NRF52_HIGHPRI_TIMER_IRQ, NVIC_SYSH_HIGH_PRIORITY); + if (ret < 0) + { + fprintf(stderr, "highpri_main: ERROR: up_prioritize_irq failed: %d\n", + ret); + ret = EXIT_FAILURE; + goto errout; + } + + /* Enable the timer interrupt at the NVIC and at TIMER */ + + up_enable_irq(NRF52_HIGHPRI_TIMER_IRQ); + NRF52_TIM_START(tim); + + seconds = 0; + + while (1) + { + /* Flush stdout and wait a bit */ + + fflush(stdout); + nxsig_sleep(1); + seconds++; + + /* Sample counts so that they are not volatile. Missing a count now + * and then is a normal consequence of this design. + */ + + for (i = 0; i < 16; i++) + { + basepri[i] = g_highpri.basepri[i]; + } + + handler = g_highpri.handler; + thread = g_highpri.thread; + + /* Then print out what is happening */ + + printf("Elapsed time: %d seconds\n\n", seconds); + for (i = 0, total = 0; i < 16; i++) + { + total += basepri[i]; + } + + if (total > 0) + { + for (i = 0; i < 16; i++) + { + if (basepri[i] > 0) + { + printf(" basepri[%02x]: %lld (%d%%)\n", + i << 4, basepri[i], + (int)((100 * basepri[i] + (total / 2)) / total)); + } + } + } + + total = handler + thread; + if (total > 0) + { + printf(" Handler: %lld (%d%%)\n", + handler, (int)((100*handler + (total / 2)) / total)); + printf(" Thread: %lld (%d%%)\n\n", + thread, (int)((100*thread + (total / 2)) / total)); + } + } + + ret = EXIT_SUCCESS; + +errout: + return ret; +} + +#endif /* CONFIG_NRF52840DK_HIGHPRI */