diff --git a/Kconfig b/Kconfig index c524fcb5e5..f4067ad39e 100644 --- a/Kconfig +++ b/Kconfig @@ -68,7 +68,7 @@ config ALLOW_MIT_COMPONENTS config ALLOW_BSDNORDIC_COMPONENTS bool "Use components that have 5-Clause Nordic licenses" - depends on ARCH_CHIP_NRF52 || ARCH_CHIP_NRF53 + depends on ARCH_CHIP_NRF52 || ARCH_CHIP_NRF53 || ARCH_CHIP_NRF91 default n ---help--- When this option is enabled the project will allow the use diff --git a/LICENSE b/LICENSE index df19b7ccc7..9be43fa5b3 100644 --- a/LICENSE +++ b/LICENSE @@ -6715,6 +6715,8 @@ drivers/wireless/spirit/ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. arch/arm/src/nrf52/sdk-nrfxlib +arch/arm/src/nrf53/sdk-nrfxlib +arch/arm/src/nrf91/sdk-nrfxlib =============================== Nordic SoftDevice Controller is based on the 3-Clause BSD License: diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 480c9bbc05..559fdfb81d 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -295,6 +295,17 @@ config ARCH_CHIP_NRF53 ---help--- Nordic NRF53 architectures (ARM dual Cortex-M33). +config ARCH_CHIP_NRF91 + bool "Nordic NRF91" + select ARCH_CORTEXM33 + select ARCH_HAVE_PWM_MULTICHAN + select ARCH_HAVE_TRUSTZONE + select ARCH_HAVE_TICKLESS + depends on EXPERIMENTAL + ---help--- + Nordic NRF91 architectures (ARM Cortex-M33 with integrated + LTE-M/NB-IoT modem and GNSS). + config ARCH_CHIP_NUC1XX bool "Nuvoton NUC100/120" select ARCH_CORTEXM0 @@ -991,6 +1002,7 @@ config ARCH_CHIP default "moxart" if ARCH_CHIP_MOXART default "nrf52" if ARCH_CHIP_NRF52 default "nrf53" if ARCH_CHIP_NRF53 + default "nrf91" if ARCH_CHIP_NRF91 default "nuc1xx" if ARCH_CHIP_NUC1XX default "rp2040" if ARCH_CHIP_RP2040 default "s32k1xx" if ARCH_CHIP_S32K1XX @@ -1428,6 +1440,9 @@ endif if ARCH_CHIP_NRF53 source "arch/arm/src/nrf53/Kconfig" endif +if ARCH_CHIP_NRF91 +source "arch/arm/src/nrf91/Kconfig" +endif if ARCH_CHIP_NUC1XX source "arch/arm/src/nuc1xx/Kconfig" endif diff --git a/arch/arm/include/nrf91/chip.h b/arch/arm/include/nrf91/chip.h new file mode 100644 index 0000000000..d577040e68 --- /dev/null +++ b/arch/arm/include/nrf91/chip.h @@ -0,0 +1,53 @@ +/**************************************************************************** + * arch/arm/include/nrf91/chip.h + * + * 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. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_INCLUDE_NRF91_CHIP_H +#define __ARCH_ARM_INCLUDE_NRF91_CHIP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Prototypes + ****************************************************************************/ + +/* NVIC priority levels *****************************************************/ + +#define NVIC_SYSH_PRIORITY_MIN 0xe0 /* All bits[7:5] set is minimum priority */ +#define NVIC_SYSH_PRIORITY_DEFAULT 0x80 /* Midpoint is the default */ +#define NVIC_SYSH_PRIORITY_MAX 0x00 /* Zero is maximum priority */ +#define NVIC_SYSH_PRIORITY_STEP 0x20 /* Steps between priorities */ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions Prototypes + ****************************************************************************/ + +#endif /* __ARCH_ARM_INCLUDE_NRF91_CHIP_H */ diff --git a/arch/arm/include/nrf91/irq.h b/arch/arm/include/nrf91/irq.h new file mode 100644 index 0000000000..571cb27fd5 --- /dev/null +++ b/arch/arm/include/nrf91/irq.h @@ -0,0 +1,101 @@ +/**************************************************************************** + * arch/arm/include/nrf91/irq.h + * + * 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. + * + ****************************************************************************/ + +/* This file should never be included directly but, rather, + * only indirectly through nuttx/irq.h + */ + +#ifndef __ARCH_ARM_INCLUDE_NRF91_IRQ_H +#define __ARCH_ARM_INCLUDE_NRF91_IRQ_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#ifndef __ASSEMBLY__ +# include +#endif + +/**************************************************************************** + * Pre-processor Prototypes + ****************************************************************************/ + +/* IRQ numbers. + * The IRQ number corresponds vector number and hence map directly to bits in + * the NVIC. This does, however, waste several words of memory in the IRQ to + * handle mapping tables. + */ + +/* Processor Exceptions (vectors 0-15) */ + +#define NRF91_IRQ_RESERVED (0) /* Reserved vector (only used with CONFIG_DEBUG_FEATURES) */ + /* Vector 0: Reset stack pointer value */ + /* Vector 1: Reset (not handler as an IRQ) */ +#define NRF91_IRQ_NMI (2) /* Vector 2: Non-Maskable Interrupt (NMI) */ +#define NRF91_IRQ_HARDFAULT (3) /* Vector 3: Hard fault */ +#define NRF91_IRQ_MEMFAULT (4) /* Vector 4: Memory management (MPU) */ +#define NRF91_IRQ_BUSFAULT (5) /* Vector 5: Bus fault */ +#define NRF91_IRQ_USAGEFAULT (6) /* Vector 6: Usage fault */ + /* Vectors 7-10: Reserved */ +#define NRF91_IRQ_SVCALL (11) /* Vector 11: SVC call */ +#define NRF91_IRQ_DBGMONITOR (12) /* Vector 12: Debug Monitor */ + /* Vector 13: Reserved */ +#define NRF91_IRQ_PENDSV (14) /* Vector 14: Pendable system service request */ +#define NRF91_IRQ_SYSTICK (15) /* Vector 15: System tick */ +#define NRF91_IRQ_EXTINT (16) /* Vector 16: Vector number of the first external interrupt */ + +/* Cortex-M4 External interrupts (vectors >= 16) */ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#if defined(CONFIG_ARCH_CHIP_NRF9160) +# include +#else +# error "Unsupported NRF91XX MCU" +#endif + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +#ifndef __ASSEMBLY__ +typedef void (*vic_vector_t)(uint32_t *regs); + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +#undef EXTERN +#ifdef __cplusplus +} +#endif +#endif + +#endif /* __ARCH_ARM_INCLUDE_NRF91_IRQ_H */ diff --git a/arch/arm/include/nrf91/nrf9160_irq.h b/arch/arm/include/nrf91/nrf9160_irq.h new file mode 100644 index 0000000000..b91a8d7ddd --- /dev/null +++ b/arch/arm/include/nrf91/nrf9160_irq.h @@ -0,0 +1,76 @@ +/**************************************************************************** + * arch/arm/include/nrf91/nrf9160_irq.h + * + * 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. + * + ****************************************************************************/ + +/* This file should never be included directly but, rather, + * only indirectly through nuttx/irq.h + */ + +#ifndef __ARCH_ARM_INCLUDE_NRF9160_IRQ_H +#define __ARCH_ARM_INCLUDE_NRF9160_IRQ_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/* Cortex-M33 External interrupts (vectors >= 16) */ + +/* Application core */ + +#define NRF91_IRQ_SPU (NRF91_IRQ_EXTINT+3) /* SPU interrupt */ +#define NRF91_IRQ_REGULATORS (NRF91_IRQ_EXTINT+4) /* Regulators */ +#define NRF91_IRQ_POWER_CLOCK (NRF91_IRQ_EXTINT+5) /* Power, Clock */ +#define NRF91_IRQ_SERIAL0 (NRF91_IRQ_EXTINT+8) /* UART/SPI/TWI 0 */ +#define NRF91_IRQ_SERIAL1 (NRF91_IRQ_EXTINT+9) /* UART/SPI/TWI 1 */ +#define NRF91_IRQ_SERIAL2 (NRF91_IRQ_EXTINT+10) /* UART/SPI/TWI 2 */ +#define NRF91_IRQ_SERIAL3 (NRF91_IRQ_EXTINT+11) /* UART/SPI/TWI 3 */ +#define NRF91_IRQ_GPIOTE0 (NRF91_IRQ_EXTINT+13) /* GPIO Task & Event 0 */ +#define NRF91_IRQ_SAADC (NRF91_IRQ_EXTINT+14) /* Analog to Digital Converter */ +#define NRF91_IRQ_TIMER0 (NRF91_IRQ_EXTINT+15) /* Timer 0 */ +#define NRF91_IRQ_TIMER1 (NRF91_IRQ_EXTINT+16) /* Timer 1 */ +#define NRF91_IRQ_TIMER2 (NRF91_IRQ_EXTINT+17) /* Timer 2 */ +#define NRF91_IRQ_RTC0 (NRF91_IRQ_EXTINT+20) /* Real-time counter 0 */ +#define NRF91_IRQ_RTC1 (NRF91_IRQ_EXTINT+21) /* Real-time counter 1 */ +#define NRF91_IRQ_WDT0 (NRF91_IRQ_EXTINT+24) /* Watchdog Timer 0 */ +#define NRF91_IRQ_EGU0 (NRF91_IRQ_EXTINT+27) /* Event Gen. Unit 0 */ +#define NRF91_IRQ_EGU1 (NRF91_IRQ_EXTINT+28) /* Event Gen. Unit 1 */ +#define NRF91_IRQ_EGU2 (NRF91_IRQ_EXTINT+29) /* Event Gen. Unit 2 */ +#define NRF91_IRQ_EGU3 (NRF91_IRQ_EXTINT+30) /* Event Gen. Unit 3 */ +#define NRF91_IRQ_EGU4 (NRF91_IRQ_EXTINT+31) /* Event Gen. Unit 4 */ +#define NRF91_IRQ_EGU5 (NRF91_IRQ_EXTINT+32) /* Event Gen. Unit 5 */ +#define NRF91_IRQ_PWM0 (NRF91_IRQ_EXTINT+33) /* Pulse Width Modulation Unit 0 */ +#define NRF91_IRQ_PWM1 (NRF91_IRQ_EXTINT+34) /* Pulse Width Modulation Unit 1 */ +#define NRF91_IRQ_PWM2 (NRF91_IRQ_EXTINT+35) /* Pulse Width Modulation Unit 2 */ +#define NRF91_IRQ_PWM3 (NRF91_IRQ_EXTINT+36) /* Pulse Width Modulation Unit 3 */ +#define NRF91_IRQ_PDM (NRF91_IRQ_EXTINT+38) /* Pulse Density Modulation (Digital Mic) Interface */ +#define NRF91_IRQ_I2S (NRF91_IRQ_EXTINT+40) /* Inter-IC Sound interface */ +#define NRF91_IRQ_IPC (NRF91_IRQ_EXTINT+42) /* IPC */ +#define NRF91_IRQ_GPIOTE1 (NRF91_IRQ_EXTINT+49) /* GPIO Task & Event 1 */ +#define NRF91_IRQ_KMU (NRF91_IRQ_EXTINT+57) /* KMU */ +#define NRF91_IRQ_CRYPTOCELL (NRF91_IRQ_EXTINT+64) /* CRYPTOCELL */ + +#define NRF91_IRQ_NEXTINT (66) + +#define NRF91_IRQ_NIRQS (NRF91_IRQ_EXTINT+NRF91_IRQ_NEXTINT) + +/* Total number of IRQ numbers */ + +#define NR_IRQS NRF91_IRQ_NIRQS + +#endif /* __ARCH_ARM_INCLUDE_NRF9160_IRQ_H */ diff --git a/arch/arm/src/nrf91/.gitignore b/arch/arm/src/nrf91/.gitignore new file mode 100644 index 0000000000..05b391e827 --- /dev/null +++ b/arch/arm/src/nrf91/.gitignore @@ -0,0 +1,2 @@ +sdk-nrfxlib* +*.tar.gz diff --git a/arch/arm/src/nrf91/Kconfig b/arch/arm/src/nrf91/Kconfig new file mode 100644 index 0000000000..7e22300e96 --- /dev/null +++ b/arch/arm/src/nrf91/Kconfig @@ -0,0 +1,689 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +comment "NRF91 Configuration Options" + +# NRF91 Families + +choice + prompt "NRF91 Chip Selection" + default ARCH_CHIP_NRF9160 + depends on ARCH_CHIP_NRF91 + +config ARCH_CHIP_NRF9160 + bool "NRF9160" + +endchoice # NRF91 Chip Selection + +config NRF91_ENABLE_APPROTECT + bool "NRF91 enable APPROTECT" + default n + +# Peripheral Selection + +config NRF91_I2C_MASTER + bool + default n + +config NRF91_SPI_MASTER + bool + default n + +config NRF91_IPC + bool + +config NRF91_UART + bool + default n + +config NRF91_TIMER + bool + default n + +config NRF91_PWM + bool + default n + +config NRF91_RTC + bool + default n + +config NRF91_SERIAL0 + bool + default n + +config NRF91_SERIAL2 + bool + default n + +config NRF91_SERIAL3 + bool + default n + +config NRF91_SERIAL4 + bool + default n + +menu "NRF91 Peripheral Selection" + +config NRF91_GPIOTE + bool "GPIOTE (GPIO interrupts)" + default n + +config NRF91_I2C0_MASTER + bool "I2C0 Master" + default n + select NRF91_I2C_MASTER + select NRF91_SERIAL0 + +config NRF91_I2C1_MASTER + bool "I2C1 Master" + default n + select NRF91_I2C_MASTER + select NRF91_SERIAL1 + +config NRF91_I2C2_MASTER + bool "I2C2 Master" + default n + select NRF91_I2C_MASTER + select NRF91_SERIAL2 + +config NRF91_I2C3_MASTER + bool "I2C3 Master" + default n + select NRF91_I2C_MASTER + select NRF91_SERIAL3 + +config NRF91_SPI0_MASTER + bool "SPI0 Master" + default n + select NRF91_SPI_MASTER + select NRF91_SERIAL0 + +config NRF91_SPI1_MASTER + bool "SPI1 Master" + default n + select NRF91_SPI_MASTER + select NRF91_SERIAL1 + +config NRF91_SPI2_MASTER + bool "SPI2 Master" + default n + select NRF91_SPI_MASTER + select NRF91_SERIAL2 + +config NRF91_SPI3_MASTER + bool "SPI3 Master" + default n + select NRF91_SPI_MASTER + select NRF91_SERIAL3 + +config NRF91_UART0 + bool "UART0" + default n + select UART0_SERIALDRIVER + select NRF91_UART + select NRF91_SERIAL0 + +config NRF91_UART1 + bool "UART1" + default n + select UART1_SERIALDRIVER + select NRF91_UART + select NRF91_SERIAL1 + +config NRF91_TIMER0 + bool "TIMER0" + select NRF91_TIMER + default n + +config NRF91_TIMER1 + bool "TIMER1" + select NRF91_TIMER + default n + +config NRF91_TIMER2 + bool "TIMER2" + select NRF91_TIMER + +config NRF91_PWM0 + bool "PWM0" + select NRF91_PWM + default n + +config NRF91_PWM1 + bool "PWM1" + select NRF91_PWM + default n + +config NRF91_PWM2 + bool "PWM2" + select NRF91_PWM + default n + +config NRF91_SAADC + bool "SAADC" + default n + +config NRF91_RTC0 + bool "RTC0" + select NRF91_RTC + default n + +config NRF91_RTC1 + bool "RTC1" + select NRF91_RTC + default n + +endmenu # NRF91 Peripheral Selection + +menu "SPU configuration" + +choice + prompt "SPU configuration" + default NRF91_SPU_NONE + depends on ARCH_TRUSTZONE_SECURE + +config NRF91_SPU_CUSTOM + bool "Custom SPU configuration" + ---help--- + Enables board-specific NRF91 SPU configuration. + +config NRF91_SPU_NONSECURE + bool "Non-secure SPU configuration" + +config NRF91_SPU_NONE + bool "No SPU configuration" + +endchoice # SPU configuration + +if NRF91_SPU_NONSECURE + +config NRF91_POWERCLOCK_NS + bool "IPC POWER/CLOCK non-secure" + default n + +config NRF91_GPIO0_NS + bool "IPC GPIO0 non-secure" + default n + +config NRF91_NVMC_NS + bool "IPC NVMC non-secure" + default n + +config NRF91_SERIAL0_NS + bool "IPC SERIAL0 non-secure" + default n + +config NRF91_SERIAL1_NS + bool "IPC SERIAL1 non-secure" + default n + +config NRF91_SERIAL2_NS + bool "IPC SERIAL2 non-secure" + default n + +config NRF91_SERIAL3_NS + bool "IPC SERIAL3 non-secure" + default n + +config NRF91_SERIAL4_NS + bool "IPC SERIAL4 non-secure" + default n + +config NRF91_TIMER0_NS + bool "IPC TIMER0 non-secure" + default n + +config NRF91_TIMER1_NS + bool "IPC TIMER1 non-secure" + default n + +config NRF91_TIMER2_NS + bool "IPC TIMER2 non-secure" + default n + +config NRF91_RTC0_NS + bool "IPC RTC0 non-secure" + default n + +config NRF91_WDT0_NS + bool "IPC WDT0 non-secure" + default n + +config NRF91_WDT1_NS + bool "IPC WDT1 non-secure" + default n + +config NRF91_RTC0_NS + bool "IPC RTC0 non-secure" + default n + +config NRF91_RTC1_NS + bool "IPC RTC1 non-secure" + default n + +config NRF91_PWM0_NS + bool "IPC PWM0 non-secure" + default n + +config NRF91_PWM1_NS + bool "IPC PWM1 non-secure" + default n + +config NRF91_PWM2_NS + bool "IPC PWM2 non-secure" + default n + +config NRF91_PWM3_NS + bool "IPC PWM3 non-secure" + default n + +config NRF91_IPC_NS + bool "IPC non-secure" + default n + +config NRF91_FLASH_NS_START + int "FLASH non-secure region start" + range 0 32 + default 0 + +config NRF91_RAM_NS_START + int "RAM non-secure region start" + range 0 32 + default 0 + +endif # NRF91_CONFIG_NONSECURE + +endmenu # "SPU configuration" + +menu "Clock Configuration" + +config NRF91_HFCLK_XTAL + bool "Enable HFCLK from external crystal" + default n + ---help--- + If the board includes an external high-frequency crystal, enable this + option to supply the HFCLK. If this option is disabled, the internal + oscillator will be used. + +config NRF91_USE_LFCLK + bool "Enable LFCLK" + default n + ---help--- + Enable low-frequency clock. + +if NRF91_USE_LFCLK + +choice + prompt "LFCLK source" + default NRF91_LFCLK_XTAL + +config NRF91_LFCLK_XTAL + bool "External 32.768Khz crystal" + +config NRF91_LFCLK_RC + bool "Internal RC oscillator" + +config NRF91_LFCLK_SYNTH + bool "Synthesized from HFCLK" + +endchoice + +endif # NRF91_USE_LFCLK + +endmenu # Clock Configuration + +menu "System Timer" + +config NRF91_SYSTIMER + bool + default y + +choice + prompt "System Timer Source" + default NRF91_SYSTIMER_SYSTICK + ---help--- + Choose which hardware resource will drive NuttX + system time + +config NRF91_SYSTIMER_SYSTICK + bool "SysTick" + select TIMER_ARCH + select TIMER + select ARMV8M_SYSTICK + ---help--- + Use ARM SysTick. It can be used for tickless and + non-tickless mode. + + NOTE: nrf91 implementation of WFE/WFI involves is + incompatible with SysTick. This means that if + you choose this option, WFE/WFI will not be used + in idle loop. + +config NRF91_SYSTIMER_RTC + bool "RTC" + select NRF91_RTC + select SCHED_TICKLESS + select SCHED_TICKLESS_ALARM + select NRF91_USE_LFCLK + ---help--- + Use RTC timer in tickless mode. + +endchoice + +if NRF91_SYSTIMER_RTC + +config NRF91_SYSTIMER_RTC_INSTANCE + int "RTC timer instance" + default 0 + range 0 1 + ---help--- + Which RTC instance to use to drive the system timer + +endif + +endmenu # System Timer + +config NRF91_FLASH_PREFETCH + bool "Enable FLASH Pre-fetch" + default y + ---help--- + Enable FLASH prefetch + +config NRF91_PROGMEM + bool "FLASH program memory" + default n + select ARCH_HAVE_PROGMEM + ---help--- + Enable support FLASH interfaces as defined in include/nuttx/progmem.h + +menu "GPIO Interrupt Configuration" + +config NRF91_PER_PIN_INTERRUPTS + bool "Per-pin interrupt callbacks" + default !DEFAULT_SMALL + depends on NRF91_GPIOTE + ---help--- + The GPIOTE peripheral supports a limited number of channels which can + be set to EVENT mode and thus generate interrupts on pin state changes. + Another mechanism offered by the GPIO/GPIOTE peripherals is the PORT + event. This event is generated from a signal shared by all pins in + the GPIO port. + + This option enables the ability to set per-pin callbacks that will + be invoked from the main GPIOTE ISR when a PORT event is generated. + As this involves extra storage to store each callback, this option can + be disabled to save space. In such case, it is possible to set a callback + for the whole PORT event directly. + +endmenu # GPIO Interrupt Configuration + +menu "PWM configuration" + +if NRF91_PWM + +config NRF91_PWM_MULTICHAN + bool "PWM Multiple Output Channels" + default n + +if NRF91_PWM_MULTICHAN + +if NRF91_PWM0 + +config NRF91_PWM0_CH0 + bool "PWM0 Channel 0 Output" + default n + ---help--- + Enables channel 0 output. + +config NRF91_PWM0_CH1 + bool "PWM0 Channel 1 Output" + default n + ---help--- + Enables channel 1 output. + +config NRF91_PWM0_CH2 + bool "PWM0 Channel 2 Output" + default n + ---help--- + Enables channel 2 output. + +config NRF91_PWM0_CH3 + bool "PWM0 Channel 3 Output" + default n + ---help--- + Enables channel 3 output. + +endif # NRF91_PWM0 + +if NRF91_PWM1 + +config NRF91_PWM1_CH0 + bool "PWM1 Channel 0 Output" + default n + ---help--- + Enables channel 0 output. + +config NRF91_PWM1_CH1 + bool "PWM1 Channel 1 Output" + default n + ---help--- + Enables channel 1 output. + +config NRF91_PWM1_CH2 + bool "PWM1 Channel 2 Output" + default n + ---help--- + Enables channel 2 output. + +config NRF91_PWM1_CH3 + bool "PWM1 Channel 3 Output" + default n + ---help--- + Enables channel 3 output. + +endif # NRF91_PWM1 + +if NRF91_PWM2 + +config NRF91_PWM2_CH0 + bool "PWM2 Channel 0 Output" + default n + ---help--- + Enables channel 0 output. + +config NRF91_PWM2_CH1 + bool "PWM2 Channel 1 Output" + default n + ---help--- + Enables channel 1 output. + +config NRF91_PWM2_CH2 + bool "PWM2 Channel 2 Output" + default n + ---help--- + Enables channel 2 output. + +config NRF91_PWM2_CH3 + bool "PWM2 Channel 3 Output" + default n + ---help--- + Enables channel 3 output. + +endif # NRF91_PWM2 + +endif # !NRF91_PWM_MULTICHAN + +if !NRF91_PWM_MULTICHAN + +config NRF91_PWM0_CHANNEL + int "PWM0 Output Channel" + depends on NRF91_PWM0 + default 0 + range 0 3 + +config NRF91_PWM1_CHANNEL + int "PWM1 Output Channel" + depends on NRF91_PWM1 + default 0 + range 0 3 + +config NRF91_PWM2_CHANNEL + int "PWM2 Output Channel" + depends on NRF91_PWM2 + default 0 + range 0 3 + +endif # !NRF91_PWM_MULTICHAN + +endif # NRF91_PWM + +endmenu # PWM configuration + +menu "SAADC Configuration" + +if NRF91_SAADC + +choice + prompt "SAADC trigger selection" + default NRF91_SAADC_TASK + ---help--- + Choose mode for sample rate control + +config NRF91_SAADC_TASK + bool "SAADC Task trigger" + +config NRF91_SAADC_TIMER + bool "SAADC Timer trigger" + +endchoice # SAADC trigger selection + +if NRF91_SAADC_TIMER + +config NRF91_SAADC_TIMER_CC + int "SAADC Timer CC" + default 0 + range 80 2047 + +endif #NRF91_SAADC_TIMER + +config NRF91_SAADC_OVERSAMPLE + int "SAADC oversample" + default 0 + range 0 8 + ---help--- + SAADC oversample control + +config NRF91_SAADC_RESOLUTION + int "SAADC resolution" + default 0 + range 0 3 + ---help--- + SAADC resolution 0 - 8 bits, 1 - 10 bits, 2 - 12 bits, 3 - 14 bits + +config NRF91_SAADC_CHANNELS + int "SAADC channels" + default 8 + range 0 8 + ---help--- + SAADC channels + +config NRF91_SAADC_LIMITS + bool "SAADC limits enable" + default n + ---help--- + SAADC limist enable + +endif # NRF91_SAADC + +endmenu # SAADC Configuration + +menu "SPI Configuration" + +if NRF91_SPI_MASTER + +config NRF91_SPI_MASTER_INTERRUPTS + bool "SPI Master interrupts support" + default n + +endif # NRF91_SPI_MASTER + +endmenu + +menu "I2C Master Configuration" + +if NRF91_I2C_MASTER + +config NRF91_I2C_MASTER_DISABLE_NOSTART + bool "Disable the I2C Master NOSTART flag support" + default n + ---help--- + To combine two i2c messages that are part of a + single transaction (NO_STOP-NO_START) the nrf91 + hardware requires these be joined into a single + transfer. This can be expensive and some devices + can get away with multi-part transfers as separate + transfers. Enable this at your own risk! + +config NRF91_I2C_MASTER_COPY_BUF_SIZE + int "Static buffer size for NOSTART flag support" + depends on !NRF91_I2C_MASTER_DISABLE_NOSTART + default 4 + ---help--- + To combine two i2c messages that are part of a + single transaction (NO_STOP-NO_START) the nrf91 + hardware requires these be joined into a single + transfer. This static buffer will be used if the + transaction will fit otherwise it will fall back + on malloc. + +endif # NRF91_I2C_MASTER + +endmenu + +config NRF91_MODEM + bool "NRF91 modem" + depends on ALLOW_BSDNORDIC_COMPONENTS && ARCH_TRUSTZONE_NONSECURE + select ARCH_IRQPRIO + select NRF91_IPC + default n + +if NRF91_MODEM + +config NRF91_MODEM_SHMEM_TX_SIZE + hex "NRF91 modem shmem RX size" + default 0x2000 + +config NRF91_MODEM_SHMEM_RX_SIZE + hex "NRF91 modem shmem RX size" + default 0x2000 + +config NRF91_MODEM_SHMEM_TRACE_SIZE + hex "NRF91 modem shmem TRACE size" + default 0 + +config NRF91_MODEM_SHMEM_SIZE + hex "NRF91 modem shmem size" + default 0x44e8 + ---help--- + Shared memory size for the modem library must be calculated by user: + CONFIG_NRF91_MODEM_SHMEM_SIZE = NRF_MODEM_SHMEM_CTRL_SIZE + + CONFIG_NRF91_MODEM_SHMEM_TX_SIZE + CONFIG_NRF91_MODEM_SHMEM_TX_SIZE + + CONFIG_NRF91_MODEM_SHMEM_TRACE_SIZE + + where: + NRF_MODEM_SHMEM_CTRL_SIZE is a constant for a given library build + and can be found in nrf_modem/include/nrf_modem.h file. + +config NRF91_MODEM_LOG + bool "NRF91 modem with logs" + default n + +config NRF91_MODEM_AT + bool "NRF91 modem AT interface support" + default y + +endif # NRF91_MODEM diff --git a/arch/arm/src/nrf91/Make.defs b/arch/arm/src/nrf91/Make.defs new file mode 100644 index 0000000000..224c2f7efa --- /dev/null +++ b/arch/arm/src/nrf91/Make.defs @@ -0,0 +1,134 @@ +############################################################################ +# arch/arm/src/nrf91/Make.defs +# +# 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. +# +############################################################################ + +include armv8-m/Make.defs + +ifeq ($(CONFIG_NRF91_SYSTIMER_SYSTICK),y) +CHIP_CSRCS += nrf91_systick.c +else +ifeq ($(CONFIG_NRF91_SYSTIMER_RTC),y) +CHIP_CSRCS += nrf91_tickless_rtc.c +endif +endif + +CHIP_CSRCS += nrf91_start.c nrf91_clockconfig.c nrf91_irq.c nrf91_utils.c +CHIP_CSRCS += nrf91_allocateheap.c nrf91_lowputc.c nrf91_gpio.c +CHIP_CSRCS += nrf91_uid.c nrf91_spu.c + +ifeq ($(CONFIG_NRF91_PROGMEM),y) +CHIP_CSRCS += nrf91_flash.c +endif + +ifneq ($(CONFIG_ARCH_IDLE_CUSTOM),y) +CHIP_CSRCS += nrf91_idle.c +endif + +ifeq ($(CONFIG_NRF91_GPIOTE),y) +CHIP_CSRCS += nrf91_gpiote.c +endif + +ifeq ($(CONFIG_NRF91_UART),y) +CHIP_CSRCS += nrf91_serial.c +endif + +ifeq ($(CONFIG_NRF91_TIMER),y) +CHIP_CSRCS += nrf91_tim.c +ifeq ($(CONFIG_TIMER),y) +CHIP_CSRCS += nrf91_tim_lowerhalf.c +endif +endif + +ifeq ($(CONFIG_NRF91_PWM),y) +CHIP_CSRCS += nrf91_pwm.c +endif + +ifeq ($(CONFIG_NRF91_SAADC),y) +CHIP_CSRCS += nrf91_adc.c +endif + +ifeq ($(CONFIG_NRF91_RTC),y) +CHIP_CSRCS += nrf91_rtc.c +endif + +ifeq ($(CONFIG_NRF91_SPI_MASTER),y) +CHIP_CSRCS += nrf91_spi.c +endif + +ifeq ($(CONFIG_PM),y) +CHIP_CSRCS += nrf91_pminitialize.c +endif + +ifeq ($(CONFIG_NRF91_I2C_MASTER),y) +CHIP_CSRCS += nrf91_i2c.c +endif + +ifeq ($(CONFIG_NRF91_MODEM),y) + +NRFXLIB_UNPACK := sdk-nrfxlib +NRFXLIB_VER := 2.4.0 +NRFXLIB_REF := v$(NRFXLIB_VER) +NRFXLIB_TGZ := $(NRFXLIB_REF).tar.gz +NRFXLIB_URL := https://github.com/nrfconnect/sdk-nrfxlib/archive + +$(NRFXLIB_TGZ): + $(call DOWNLOAD,$(NRFXLIB_URL),$(NRFXLIB_TGZ),chip/$(NRFXLIB_TGZ)) + +chip/$(NRFXLIB_UNPACK): $(NRFXLIB_TGZ) + $(Q) echo "Unpacking: NRXFLIB" + $(Q) cd chip && tar zxf $(NRFXLIB_TGZ) + $(Q) mv chip/$(NRFXLIB_UNPACK)-$(NRFXLIB_VER)* chip/$(NRFXLIB_UNPACK) + $(Q) touch chip/$(NRFXLIB_UNPACK) + +ifeq ($(wildcard chip/$(NRFXLIB_UNPACK)/.git),) +context:: chip/$(NRFXLIB_UNPACK) + +distclean:: + $(call DELFILE, chip/$(NRFXLIB_TGZ)) + $(call DELDIR, chip/$(NRFXLIB_UNPACK)) +endif + +CHIP_CSRCS += nrf91_modem.c nrf91_modem_os.c nrf91_nrfx_ipc.c + +ifeq ($(CONFIG_NRF91_MODEM_AT),y) +CHIP_CSRCS += nrf91_modem_at.c +endif + +NRFXLIB_DIR = $(ARCH_SRCDIR)$(DELIM)chip$(DELIM)sdk-nrfxlib + +INCLUDES += \ + ${INCDIR_PREFIX}$(NRFXLIB_DIR)$(DELIM)nrf_modem$(DELIM)include + +ifeq ($(CONFIG_ARCH_FPU),y) + LIB_VARIANT=hard-float +else + LIB_VARIANT=soft-float +endif + +EXTRA_LIBPATHS += \ + -L $(NRFXLIB_DIR)$(DELIM)nrf_modem$(DELIM)lib$(DELIM)cortex-m33$(DELIM)$(LIB_VARIANT) + +ifeq ($(CONFIG_NRF91_MODEM_LOG),y) + EXTRA_LIBS += -lmodem_log +else + EXTRA_LIBS += -lmodem +endif + + +endif diff --git a/arch/arm/src/nrf91/chip.h b/arch/arm/src/nrf91/chip.h new file mode 100644 index 0000000000..28a9f3ff0a --- /dev/null +++ b/arch/arm/src/nrf91/chip.h @@ -0,0 +1,47 @@ +/**************************************************************************** + * arch/arm/src/nrf91/chip.h + * + * 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. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_NRF91_CHIP_H +#define __ARCH_ARM_SRC_NRF91_CHIP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/* Include the memory map and the chip definitions file. + * Other chip hardware files should then include this file for the proper + * setup. + */ + +#include +#include +#include "hardware/nrf91_memorymap.h" + +/* If the common ARMv7-M vector handling logic is used, then it expects the + * following definition in this file that provides the number of supported + * external interrupts which, for this architecture, is provided in the + * arch/nrf91/chip.h header file. + */ + +#define ARMV8M_PERIPHERAL_INTERRUPTS NRF91_IRQ_NEXTINT + +#endif /* __ARCH_ARM_SRC_NRF91_CHIP_H */ diff --git a/arch/arm/src/nrf91/hardware/nrf91_clock.h b/arch/arm/src/nrf91/hardware/nrf91_clock.h new file mode 100644 index 0000000000..fbe2046e10 --- /dev/null +++ b/arch/arm/src/nrf91/hardware/nrf91_clock.h @@ -0,0 +1,109 @@ +/**************************************************************************** + * arch/arm/src/nrf91/hardware/nrf91_clock.h + * + * 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. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_NRF91_HARDWARE_NRF91_CLOCK_H +#define __ARCH_ARM_SRC_NRF91_HARDWARE_NRF91_CLOCK_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include "nrf91_memorymap.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Register offsets *********************************************************/ + +#define NRF91_CLOCK_TASKS_HFCLKSTART_OFFSET 0x0000 /* Start HFCLK crystal oscillator */ +#define NRF91_CLOCK_TASKS_HFCLKSTOP_OFFSET 0x0004 /* Stop HFCLK crystal oscillator */ +#define NRF91_CLOCK_TASKS_LFCLKSTART_OFFSET 0x0008 /* Start LFCLK source */ +#define NRF91_CLOCK_TASKS_LFCLKSTOP_OFFSET 0x000c /* Stop LFCLK source */ + /* TODO: */ +#define NRF91_CLOCK_EVENTS_HFCLKSTARTED_OFFSET 0x0100 /* HFCLK oscillator started */ +#define NRF91_CLOCK_EVENTS_LFCLKSTARTED_OFFSET 0x0104 /* LFCLK started */ + /* TODO: */ +#define NRF91_CLOCK_INTENSET_OFFSET 0x0304 /* Enable interrupt */ +#define NRF91_CLOCK_INTENCLR_OFFSET 0x0308 /* Disable interrupt */ + /* TODO: */ +#define NRF91_CLOCK_HFCLKRUN_OFFSET 0x0408 /* Status indicating that HFCLKSTART task has been triggered */ +#define NRF91_CLOCK_HFCLKSTAT_OFFSET 0x040c /* HFCLK status */ +#define NRF91_CLOCK_LFCLKRUN_OFFSET 0x0414 /* Status indicating that LFCLKSTART task has been triggered */ +#define NRF91_CLOCK_LFCLKSTAT_OFFSET 0x0418 /* LFCLK status */ +#define NRF91_CLOCK_LFCLKSRCCOPY_OFFSET 0x041c /* Copy of LFCLKSRC register, set when LFCLKSTART task was triggered */ +#define NRF91_CLOCK_LFCLKSRC_OFFSET 0x0518 /* Clock source for the LFCLK */ + +/* Register definitions *****************************************************/ + +#define NRF91_CLOCK_TASKS_HFCLKSTART (NRF91_CLOCK_BASE + NRF91_CLOCK_TASKS_HFCLKSTART_OFFSET) +#define NRF91_CLOCK_TASKS_HFCLKSTOP (NRF91_CLOCK_BASE + NRF91_CLOCK_TASKS_HFCLKSTOP_OFFSET) +#define NRF91_CLOCK_TASKS_LFCLKSTART (NRF91_CLOCK_BASE + NRF91_CLOCK_TASKS_LFCLKSTART_OFFSET) +#define NRF91_CLOCK_TASKS_LFCLKSTOP (NRF91_CLOCK_BASE + NRF91_CLOCK_TASKS_LFCLKSTOP_OFFSET) +/* TODO */ +#define NRF91_CLOCK_EVENTS_HFCLKSTARTED (NRF91_CLOCK_BASE + NRF91_CLOCK_EVENTS_HFCLKSTARTED_OFFSET) +#define NRF91_CLOCK_EVENTS_LFCLKSTARTED (NRF91_CLOCK_BASE + NRF91_CLOCK_EVENTS_LFCLKSTARTED_OFFSET) +/* TODO */ +#define NRF91_CLOCK_INTENSET (NRF91_CLOCK_BASE + NRF91_CLOCK_INTENSET_OFFSET) +#define NRF91_CLOCK_INTENCLR (NRF91_CLOCK_BASE + NRF91_CLOCK_INTENCLR_OFFSET) +/* TODO */ +#define NRF91_CLOCK_HFCLKRUN (NRF91_CLOCK_BASE + NRF91_CLOCK_HFCLKRUN_OFFSET) +#define NRF91_CLOCK_HFCLKSTAT (NRF91_CLOCK_BASE + NRF91_CLOCK_HFCLKSTAT_OFFSET) +#define NRF91_CLOCK_LFCLKRUN (NRF91_CLOCK_BASE + NRF91_CLOCK_LFCLKRUN_OFFSET) +#define NRF91_CLOCK_LFCLKSTAT (NRF91_CLOCK_BASE + NRF91_CLOCK_LFCLKSTAT_OFFSET) +#define NRF91_CLOCK_LFCLKSRCCOPY (NRF91_CLOCK_BASE + NRF91_CLOCK_LFCLKSRCCOPY_OFFSET) +#define NRF91_CLOCK_LFCLKSRC (NRF91_CLOCK_BASE + NRF91_CLOCK_LFCLKSRC_OFFSET) + +/* Register bit definitions *************************************************/ + +/* HFCLKRUN Register */ + +#define CLOCK_HFCLKRUN_STATUS (1 << 0) /* Bit 0: HFCLSTART task triggered status */ + +/* HFCLKSTAT Register */ + +#define CLOCK_HFCLKSTAT_SRC_SHIFT (0) /* Bit 0: Source of HFCLK */ +#define CLOCK_HFCLKSTAT_SRC_MASK (1 << CLOCK_HFCLKSTAT_SRC_SHIFT) +# define CLOCK_HFCLKSTAT_SRC_HFINT (0 << CLOCK_HFCLKSTAT_SRC_SHIFT) /* 0b0: 128 MHz internal oscillator (HFINT) */ +# define CLOCK_HFCLKSTAT_SRC_HFXO (1 << CLOCK_HFCLKSTAT_SRC_SHIFT) /* 0b1: 128 MHz crystal oscilator (HFXO) */ +#define CLOCK_HFCLKSTAT_STATE (1 << 16) /* Bit 16: HFCLK state */ + +/* LFCLKRUN Register */ + +#define CLOCK_LFCLKRUN_STATUS (1 << 0) /* Bit 0: LFCLKSTART task triggered status */ + +/* LFCLKSTAT Register */ + +#define CLOCK_LFCLKSTAT_SRC_SHIFT (0) /* Bits 0-1: Source of LFCLK */ +#define CLOCK_LFCLKSTAT_SRC_MASK (3 << CLOCK_LFCLKSTAT_SRC_SHIFT) +# define CLOCK_LFCLKSTAT_SRC_LFRC (1 << CLOCK_LFCLKSTAT_SRC_SHIFT) /* 0b0: 32.768 kHz RC oscillator (LFRC) */ +# define CLOCK_LFCLKSTAT_SRC_LFXO (2 << CLOCK_LFCLKSTAT_SRC_SHIFT) /* 0b1: 32.768 kHz crystal oscillator (LFXO) */ +#define CLOCK_LFCLKSTAT_STATE (1 << 16) /* Bit 16: LFCLKSTAT state */ + +/* LFCLKSRC Register */ + +#define CLOCK_LFCLKSRC_SRC_SHIFT (0) /* Bits 0-1: LFRC clock source */ +#define CLOCK_LFCLKSRC_SRC_MASK (3 << CLOCK_LFCLKSRC_SRC_SHIFT) +# define CLOCK_LFCLKSRC_SRC_RFU (1 << CLOCK_LFCLKSTAT_SRC_SHIFT) +# define CLOCK_LFCLKSRC_SRC_LFRC (2 << CLOCK_LFCLKSTAT_SRC_SHIFT) +# define CLOCK_LFCLKSRC_SRC_LFXO (3 << CLOCK_LFCLKSTAT_SRC_SHIFT) + +#endif /* __ARCH_ARM_SRC_NRF91_HARDWARE_NRF91_CLOCK_H */ diff --git a/arch/arm/src/nrf91/hardware/nrf91_ficr.h b/arch/arm/src/nrf91/hardware/nrf91_ficr.h new file mode 100644 index 0000000000..97bd79a14d --- /dev/null +++ b/arch/arm/src/nrf91/hardware/nrf91_ficr.h @@ -0,0 +1,59 @@ +/*************************************************************************** + * arch/arm/src/nrf91/hardware/nrf91_ficr.h + * + * 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. + * + ***************************************************************************/ + +#ifndef __ARCH_ARM_SRC_NRF91_HARDWARE_NRF91_FICR_H +#define __ARCH_ARM_SRC_NRF91_HARDWARE_NRF91_FICR_H + +/*************************************************************************** + * Included Files + ***************************************************************************/ + +#include +#include "hardware/nrf91_memorymap.h" + +/*************************************************************************** + * Pre-processor Definitions + ***************************************************************************/ + +/* FICR Register Offsets ***************************************************/ + + /* TODO: SIPINFO */ +#define NRF91_FICR_INFO_DEVICEID0_OFFSET 0x204 /* Device identifier */ +#define NRF91_FICR_INFO_DEVICEID1_OFFSET 0x208 /* Device identifier */ +#define NRF91_FICR_INFO_RAM_OFFSET 0x218 /* RAM variant */ +#define NRF91_FICR_INFO_FLASH_OFFSET 0x21c /* Flash variant */ +#define NRF91_FICR_INFO_CODEPAGESIZE_OFFSET 0x220 /* Code memory page size in bytes */ +#define NRF91_FICR_INFO_CODESIZE_OFFSET 0x224 /* Code memory size */ +#define NRF91_FICR_INFO_DEVICETYPE_OFFSET 0x228 /* Device type */ + /* TODO */ + +/* FICR Register Addresses *************************************************/ + +#define NRF91_FICR_INFO_DEVICEID0 (NRF91_FICR_BASE + NRF91_FICR_INFO_DEVICEID0_OFFSET) +#define NRF91_FICR_INFO_DEVICEID1 (NRF91_FICR_BASE + NRF91_FICR_INFO_DEVICEID1_OFFSET) +#define NRF91_FICR_INFO_RAM (NRF91_FICR_BASE + NRF91_FICR_INFO_RAM_OFFSET) +#define NRF91_FICR_INFO_FLASH (NRF91_FICR_BASE + NRF91_FICR_INFO_FLASH_OFFSET) +#define NRF91_FICR_INFO_CODEPAGESIZE (NRF91_FICR_BASE + NRF91_FICR_INFO_CODEPAGESIZE_OFFSET) +#define NRF91_FICR_INFO_CODESIZE (NRF91_FICR_BASE + NRF91_FICR_INFO_CODESIZE_OFFSET) +#define NRF91_FICR_INFO_DEVICETYPE (NRF91_FICR_BASE + NRF91_FICR_INFO_DEVICETYPE_OFFSET) + +/* TODO */ + +#endif /* __ARCH_ARM_SRC_NRF91_HARDWARE_NRF91_FICR_H */ diff --git a/arch/arm/src/nrf91/hardware/nrf91_gpio.h b/arch/arm/src/nrf91/hardware/nrf91_gpio.h new file mode 100644 index 0000000000..2df82c7da2 --- /dev/null +++ b/arch/arm/src/nrf91/hardware/nrf91_gpio.h @@ -0,0 +1,95 @@ +/**************************************************************************** + * arch/arm/src/nrf91/hardware/nrf91_gpio.h + * + * 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. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_NRF91_HARDWARE_NRF91_GPIO_H +#define __ARCH_ARM_SRC_NRF91_HARDWARE_NRF91_GPIO_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include "hardware/nrf91_memorymap.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define NRF91_GPIO_NPORTS 2 +#define NRF91_GPIO_PORT0 0 + +#define NRF91_GPIO_NPINS 32 + +/* Register offsets *********************************************************/ + +#define NRF91_GPIO_OUT_OFFSET 0x0004 /* Write GPIO port */ +#define NRF91_GPIO_OUTSET_OFFSET 0x0008 /* Set individual bits in GPIO port */ +#define NRF91_GPIO_OUTCLR_OFFSET 0x000c /* Clear individual bits in GPIO port */ +#define NRF91_GPIO_IN_OFFSET 0x0010 /* Read GPIO port */ +#define NRF91_GPIO_DIR_OFFSET 0x0014 /* Direction of GPIO pins */ +#define NRF91_GPIO_DIRSET_OFFSET 0x0018 /* DIR set register */ +#define NRF91_GPIO_DIRCLR_OFFSET 0x001c /* DIR clear register */ +#define NRF91_GPIO_LATCH_OFFSET 0x0020 /* Latch register */ +#define NRF91_GPIO_DETECTMODE_OFFSET 0x0024 /* Select between default DETECT signal behaviour and LDETECT mode (non-secure) */ +#define NRF91_GPIO_DETECTMODESEC_OFFSET 0x0024 /* Select between default DETECT signal behaviour and LDETECT mode (secure) */ + +#define NRF91_GPIO_PIN_CNF_OFFSET(n) (0x0200 + (n << 2)) + +/* Register addresses *******************************************************/ + +#define NRF91_GPIO0_OUT (NRF91_GPIO_P0_BASE + NRF91_GPIO_OUT_OFFSET) +#define NRF91_GPIO0_OUTSET (NRF91_GPIO_P0_BASE + NRF91_GPIO_OUTSET_OFFSET) +#define NRF91_GPIO0_OUTCLR (NRF91_GPIO_P0_BASE + NRF91_GPIO_OUTCLR_OFFSET) +#define NRF91_GPIO0_IN (NRF91_GPIO_P0_BASE + NRF91_GPIO_IN_OFFSET) +#define NRF91_GPIO0_DIR (NRF91_GPIO_P0_BASE + NRF91_GPIO_DIR_OFFSET) +#define NRF91_GPIO0_DIRSET (NRF91_GPIO_P0_BASE + NRF91_GPIO_DIRSET_OFFSET) +#define NRF91_GPIO0_DIRCLR (NRF91_GPIO_P0_BASE + NRF91_GPIO_DIRCLR_OFFSET) +#define NRF91_GPIO0_CNF(n) (NRF91_GPIO_P0_BASE + NRF91_GPIO_PIN_CNF_OFFSET(n)) + +/* Register bit definitions *************************************************/ + +#define GPIO_DETECTMODE_DEFAULT (0) +#define GPIO_DETECTMODE_LDETECT (1) + +#define GPIO_CNF_DIR (1 << 0) /* Bit 0: Pin direction */ +#define GPIO_CNF_INPUT (1 << 1) /* Bit 1: Input buffer disconnect */ +#define GPIO_CNF_PULL_SHIFT (2) +#define GPIO_CNF_PULL_MASK (0x3 << GPIO_CNF_PULL_SHIFT) +# define GPIO_CNF_PULL_DISABLED (0 << GPIO_CNF_PULL_SHIFT) +# define GPIO_CNF_PULL_DOWN (1 << GPIO_CNF_PULL_SHIFT) +# define GPIO_CNF_PULL_UP (3 << GPIO_CNF_PULL_SHIFT) +#define GPIO_CNF_DRIVE_SHIFT (8) +#define GPIO_CNF_DRIVE_MASK (0xf << GPIO_CNF_DRIVE_SHIFT) +# define GPIO_CNF_DRIVE_S0S1 (0 << GPIO_CNF_DRIVE_SHIFT) +# define GPIO_CNF_DRIVE_H0S1 (1 << GPIO_CNF_DRIVE_SHIFT) +# define GPIO_CNF_DRIVE_S0H1 (2 << GPIO_CNF_DRIVE_SHIFT) +# define GPIO_CNF_DRIVE_H0H1 (3 << GPIO_CNF_DRIVE_SHIFT) +# define GPIO_CNF_DRIVE_D0S1 (4 << GPIO_CNF_DRIVE_SHIFT) +# define GPIO_CNF_DRIVE_D0H1 (5 << GPIO_CNF_DRIVE_SHIFT) +# define GPIO_CNF_DRIVE_S0D1 (6 << GPIO_CNF_DRIVE_SHIFT) +# define GPIO_CNF_DRIVE_H0D1 (7 << GPIO_CNF_DRIVE_SHIFT) +#define GPIO_CNF_SENSE_SHIFT (16) +#define GPIO_CNF_SENSE_MASK (0x3 << GPIO_CNF_SENSE_SHIFT) +# define GPIO_CNF_SENSE_DISABLED (0 << GPIO_CNF_SENSE_SHIFT) +# define GPIO_CNF_SENSE_HIGH (2 << GPIO_CNF_SENSE_SHIFT) +# define GPIO_CNF_SENSE_LOW (3 << GPIO_CNF_SENSE_SHIFT) + +#endif /* __ARCH_ARM_SRC_NRF91_HARDWARE_NRF91_GPIO_H */ diff --git a/arch/arm/src/nrf91/hardware/nrf91_ipc.h b/arch/arm/src/nrf91/hardware/nrf91_ipc.h new file mode 100644 index 0000000000..a9a70ad7ab --- /dev/null +++ b/arch/arm/src/nrf91/hardware/nrf91_ipc.h @@ -0,0 +1,68 @@ +/**************************************************************************** + * arch/arm/src/nrf91/hardware/nrf91_ipc.h + * + * 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. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_NRF91_HARDWARE_NRF91_IPC_H +#define __ARCH_ARM_SRC_NRF91_HARDWARE_NRF91_IPC_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include "nrf91_memorymap.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define NRF91_IPC_CHANS 8 + +/* Register offsets *********************************************************/ + +#define NRF91_IPC_TASKS_SEND_OFFSET(n) (0x000 + (0x4 * n)) /* Trigger events on IPC channel enabled in SEND_CNF[n] */ +#define NRF91_IPC_SUBSCRIBE_SEND_OFFSET(n) (0x080 + (0x4 * n)) /* Subscribe configuration for task SEND[n] */ +#define NRF91_IPC_EVENTS_RECEIVE_OFFSET(n) (0x100 + (0x4 * n)) /* Event received on one or more of the enabled IPC channels in RECEIVE_CNF[n] */ +#define NRF91_IPC_PUBLISH_RECEIVE_OFFSET(n) (0x180 + (0x4 * n)) /* Publish configuration for event RECEIVE[n] */ +#define NRF91_IPC_INTEN_OFFSET (0x300) /* Enable or disable interrupt */ +#define NRF91_IPC_INTENSET_OFFSET (0x304) /* Enable interrupt */ +#define NRF91_IPC_INTENCLR_OFFSET (0x308) /* Disable interrupt */ +#define NRF91_IPC_INTPEND_OFFSET (0x30C) /* Pending interrupts */ +#define NRF91_IPC_SEND_CNF_OFFSET(n) (0x510 + (0x4 * n)) /* Send event configuration for TASKS_SEND[n] */ +#define NRF91_IPC_RECEIVE_CNF_OFFSET(n) (0x590 + (0x4 * n)) /* Receive event configuration for EVENTS_RECEIVE[n] */ +#define NRF91_IPC_GPMEM_OFFSET(n) (0x610 + (0x4 * n)) /* General purpose memory */ + +/* Register definitions *****************************************************/ + +#define NRF91_IPC_TASKS_SEND(n) (NRF91_IPC_BASE + NRF91_IPC_TASKS_SEND_OFFSET(n)) +#define NRF91_IPC_SUBSCRIBE_SEND(n) (NRF91_IPC_BASE + NRF91_IPC_SUBSCRIBE_SEND_OFFSET(n)) +#define NRF91_IPC_EVENTS_RECEIVE(n) (NRF91_IPC_BASE + NRF91_IPC_EVENTS_RECEIVE_OFFSET(n)) +#define NRF91_IPC_INTEN (NRF91_IPC_BASE + NRF91_IPC_INTEN_OFFSET) +#define NRF91_IPC_INTENSET (NRF91_IPC_BASE + NRF91_IPC_INTENSET_OFFSET) +#define NRF91_IPC_INTENCLR (NRF91_IPC_BASE + NRF91_IPC_INTENCLR_OFFSET) +#define NRF91_IPC_INTPEND (NRF91_IPC_BASE + NRF91_IPC_INTPEND_OFFSET) +#define NRF91_IPC_SEND_CNF(n) (NRF91_IPC_BASE + NRF91_IPC_SEND_CNF_OFFSET(n)) +#define NRF91_IPC_RECEIVE_CNF(n) (NRF91_IPC_BASE + NRF91_IPC_RECEIVE_CNF_OFFSET(n)) +#define NRF91_IPC_GPMEM(n) (NRF91_IPC_BASE + NRF91_IPC_GPMEM_OFFSET(n)) + +/* Register bit definitions *************************************************/ + +#define IPC_CHAN_ID(x) (1 << x) /* Channel ID */ + +#endif /* __ARCH_ARM_SRC_NRF91_HARDWARE_NRF91_IPC_H */ diff --git a/arch/arm/src/nrf91/hardware/nrf91_memorymap.h b/arch/arm/src/nrf91/hardware/nrf91_memorymap.h new file mode 100644 index 0000000000..3671f20616 --- /dev/null +++ b/arch/arm/src/nrf91/hardware/nrf91_memorymap.h @@ -0,0 +1,158 @@ +/**************************************************************************** + * arch/arm/src/nrf91/hardware/nrf91_memorymap.h + * + * 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. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_NRF91_HARDWARE_NRF91_MEMORYMAP_H +#define __ARCH_ARM_SRC_NRF91_HARDWARE_NRF91_MEMORYMAP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Memory Map */ + +#define NRF91_FLASH_BASE 0x00000000 /* Flash memory Start Address */ +#define NRF91_SRAM_BASE 0x20000000 /* SRAM Start Address */ + +#define NRF91_CORTEXM33_BASE 0xe0000000 /* Cortex-M33 Private Peripheral Bus */ + +/* Non-secure access address */ + +#ifdef CONFIG_ARCH_TRUSTZONE_NONSECURE +# define NRF91_NS(x) (x - 0x10000000) +#else +# define NRF91_NS(x) (x) +#endif + +/* APB Peripherals */ + +#ifndef CONFIG_ARCH_TRUSTZONE_NONSECURE +# define NRF91_SPU_BASE 0x50003000 +#endif +#define NRF91_REGULATORS_BASE NRF91_NS(0x50004000) +#define NRF91_CLOCK_BASE NRF91_NS(0x50005000) +#define NRF91_POWER_BASE NRF91_NS(0x50005000) +#define NRF91_CTRLAPPERI_BASE NRF91_NS(0x50006000) +#define NRF91_SPIM0_BASE NRF91_NS(0x50008000) +#define NRF91_SPIS0_BASE NRF91_NS(0x50008000) +#define NRF91_TWIM0_BASE NRF91_NS(0x50008000) +#define NRF91_TWIS0_BASE NRF91_NS(0x50008000) +#define NRF91_UART0_BASE NRF91_NS(0x50008000) +#define NRF91_SPIM1_BASE NRF91_NS(0x50009000) +#define NRF91_SPIS1_BASE NRF91_NS(0x50009000) +#define NRF91_TWIM1_BASE NRF91_NS(0x50009000) +#define NRF91_TWIS1_BASE NRF91_NS(0x50009000) +#define NRF91_UART1_BASE NRF91_NS(0x50009000) +#define NRF91_SPIM2_BASE NRF91_NS(0x5000A000) +#define NRF91_SPIS2_BASE NRF91_NS(0x5000A000) +#define NRF91_TWIM2_BASE NRF91_NS(0x5000A000) +#define NRF91_TWIS2_BASE NRF91_NS(0x5000A000) +#define NRF91_UART2_BASE NRF91_NS(0x5000A000) +#define NRF91_SPIM3_BASE NRF91_NS(0x5000C000) +#define NRF91_SPIS3_BASE NRF91_NS(0x5000C000) +#define NRF91_TWIM3_BASE NRF91_NS(0x5000C000) +#define NRF91_TWIS3_BASE NRF91_NS(0x5000C000) +#define NRF91_UART3_BASE NRF91_NS(0x5000C000) +#ifndef CONFIG_ARCH_TRUSTZONE_NONSECURE +# define NRF91_GPIOTE0_BASE 0x5000D000 +#endif +#define NRF91_SAADC_BASE NRF91_NS(0x5000E000) +#define NRF91_TIMER0_BASE NRF91_NS(0x5000F000) +#define NRF91_TIMER1_BASE NRF91_NS(0x50010000) +#define NRF91_TIMER2_BASE NRF91_NS(0x50011000) +#define NRF91_RTC0_BASE NRF91_NS(0x50014000) +#define NRF91_RTC1_BASE NRF91_NS(0x50015000) +#define NRF91_DPPIC_BASE NRF91_NS(0x50017000) +#define NRF91_WDT0_BASE NRF91_NS(0x50018000) +#define NRF91_WDT1_BASE NRF91_NS(0x50019000) +#define NRF91_EGU0_BASE NRF91_NS(0x5001B000) +#define NRF91_EGU1_BASE NRF91_NS(0x5001C000) +#define NRF91_EGU2_BASE NRF91_NS(0x5001D000) +#define NRF91_EGU3_BASE NRF91_NS(0x5001E000) +#define NRF91_EGU4_BASE NRF91_NS(0x5001F000) +#define NRF91_EGU5_BASE NRF91_NS(0x50020000) +#define NRF91_PWM0_BASE NRF91_NS(0x50021000) +#define NRF91_PWM1_BASE NRF91_NS(0x50022000) +#define NRF91_PWM2_BASE NRF91_NS(0x50023000) +#define NRF91_PWM3_BASE NRF91_NS(0x50024000) +#define NRF91_PDM0_BASE NRF91_NS(0x50026000) +#define NRF91_I2S0_BASE NRF91_NS(0x50028000) +#define NRF91_IPC_BASE NRF91_NS(0x5002A000) +#define NRF91_FPU_BASE NRF91_NS(0x5002C000) +#ifdef CONFIG_ARCH_TRUSTZONE_NONSECURE +# define NRF91_GPIOTE1_BASE 0x40031000 +#endif +#define NRF91_KMU_BASE NRF91_NS(0x50039000) +#define NRF91_NVMC_BASE NRF91_NS(0x50039000) +#define NRF91_VMC_BASE NRF91_NS(0x5003A000) +#ifndef CONFIG_ARCH_TRUSTZONE_NONSECURE +# define NRF91_CCHOSTRGF_BASE 0x50840000 +# define NRF91_CRYPTOCELL_BASE 0x50840000 +#endif +#define NRF91_GPIO_P0_BASE NRF91_NS(0x50842500) +#define NRF91_FICR_BASE 0x00FF0000 +#define NRF91_UICR_BASE 0x00FF8000 +#define NRF91_TAD_BASE 0xE0080000 + +/* Peripherals IDs */ + +#define NRF91_SPU_ID 3 +#define NRF91_REGULATORS_ID 4 +#define NRF91_POWER_CLOCK_ID 5 +#define NRF91_CTRLAPPERI_ID 6 +#define NRF91_SERIAL0_ID 8 +#define NRF91_SERIAL1_ID 9 +#define NRF91_SERIAL2_ID 10 +#define NRF91_SERIAL3_ID 11 +#define NRF91_GPIOTE0_ID 13 +#define NRF91_SAADC_ID 14 +#define NRF91_TIMER0_ID 15 +#define NRF91_TIMER1_ID 16 +#define NRF91_TIMER2_ID 17 +#define NRF91_RTC0_ID 20 +#define NRF91_RTC1_ID 21 +#define NRF91_DPPIC_ID 23 +#define NRF91_WDT0_ID 24 +#define NRF91_EGU0_ID 27 +#define NRF91_EGU1_ID 28 +#define NRF91_EGU2_ID 29 +#define NRF91_EGU3_ID 30 +#define NRF91_EGU4_ID 31 +#define NRF91_EGU5_ID 32 +#define NRF91_PWM0_ID 33 +#define NRF91_PWM1_ID 34 +#define NRF91_PWM2_ID 35 +#define NRF91_PWM3_ID 36 +#define NRF91_PDM_ID 38 +#define NRF91_I2S_ID 40 +#define NRF91_IPC_ID 42 +#define NRF91_GPIOTE1_ID 49 +#define NRF91_KMU_ID 57 +#define NRF91_NVMC_ID 57 +#define NRF91_VMC_ID 58 +#define NRF91_CRUPTOCELL_ID 64 +#define NRF91_GPIO0_ID 66 + +#endif /* __ARCH_ARM_SRC_NRF91_HARDWARE_NRF91_MEMORYMAP_H */ diff --git a/arch/arm/src/nrf91/hardware/nrf91_nvmc.h b/arch/arm/src/nrf91/hardware/nrf91_nvmc.h new file mode 100644 index 0000000000..dacdb6fc1a --- /dev/null +++ b/arch/arm/src/nrf91/hardware/nrf91_nvmc.h @@ -0,0 +1,88 @@ +/**************************************************************************** + * arch/arm/src/nrf91/hardware/nrf91_nvmc.h + * + * 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. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_NRF91_HARDWARE_NRF91_NVMC_H +#define __ARCH_ARM_SRC_NRF91_HARDWARE_NRF91_NVMC_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include "hardware/nrf91_memorymap.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* NVMC Register Offsets ****************************************************/ + +/* Registers for the NVMC */ + +#define NRF91_NVMC_READY_OFFSET 0x400 /* Ready flag */ +#define NRF91_NVMC_READYNEXT_OFFSET 0x408 /* Ready flag */ +#define NRF91_NVMC_CONFIG_OFFSET 0x504 /* Configuration register */ +#define NRF91_NVMC_ERASEALL_OFFSET 0x50c /* Register for erasing all non-volatile user memory */ +#define NRF91_NVMC_ERASEPAGEPARTIALCFG_OFFSET 0x51c /* Register for partial erase configuration */ +#define NRF91_NVMC_ICACHECNF_OFFSET 0x540 /* I-Code cache configuration register */ +#define NRF91_NVMC_IHIT_OFFSET 0x548 /* I-Code cache hit counter. */ +#define NRF91_NVMC_IMISS_OFFSET 0x54c /* I-Code cache miss counter */ +#define NRF91_NVMC_CONFIGNS_OFFSET 0x584 /* Non-secure configuration register */ +#define NRF91_NVMC_WRITEUICRNS_OFFSET 0x588 /* Non-secure APPROTECT enable register */ + +/* NVMC Register Addresses **************************************************/ + +#define NRF91_NVMC_READY (NRF91_NVMC_BASE + NRF91_NVMC_READY_OFFSET) +#define NRF91_NVMC_READYNEXT (NRF91_NVMC_BASE + NRF91_NVMC_READYNEXT_OFFSET) +#define NRF91_NVMC_CONFIG (NRF91_NVMC_BASE + NRF91_NVMC_CONFIG_OFFSET) +#define NRF91_NVMC_ERASEALL (NRF91_NVMC_BASE + NRF91_NVMC_ERASEALL_OFFSET) +#define NRF91_NVMC_ERASEPAGEPARTIALCFG (NRF91_NVMC_BASE + NRF91_NVMC_ERASEPAGEPARTIALCFG_OFFSET) +#define NRF91_NVMC_ICACHECNF (NRF91_NVMC_BASE + NRF91_NVMC_ICACHECNF_OFFSET) +#define NRF91_NVMC_IHIT (NRF91_NVMC_BASE + NRF91_NVMC_IHIT_OFFSET) +#define NRF91_NVMC_IMISS (NRF91_NVMC_BASE + NRF91_NVMC_IMISS_OFFSET) +#define NRF91_NVMC_CONFIGNS (NRF91_NVMC_BASE + NRF91_NVMC_CONFIGNS_OFFSET) +#define NRF91_NVMC_WRITEUICRNS (NRF91_NVMC_BASE + NRF91_NVMC_WRITEUICRNS_OFFSET) + +/* NVMC Register Bitfield Definitions ***************************************/ + +/* READY Register */ + +#define NVMC_READY_READY (1 << 0) /* NVMC is ready */ + +/* CONFIG Register */ + +#define NVMC_CONFIG_SHIFT (0) +#define NVMC_CONFIG_MASK (3 << NVMC_CONFIG_SHIFT) +#define NVMC_CONFIG_REN (0 << NVMC_CONFIG_SHIFT) /* Read-only access */ +#define NVMC_CONFIG_WEN (1 << NVMC_CONFIG_SHIFT) /* Write Enabled */ +#define NVMC_CONFIG_EEN (2 << NVMC_CONFIG_SHIFT) /* Erase Enabled */ +#define NVMC_CONFIG_PEEN (4 << NVMC_CONFIG_SHIFT) /* Partial erase enabled */ + +/* ICACHECNF Register */ + +#define NVMC_ICACHECNF_CACHEEN (1 << 0) /* Cache enable */ +#define NVMC_ICACHECNF_CACHEPROFEN (1 << 8) /* Cache profiling enable */ + +/* WRITEUICRNS Register */ + +#define NVMC_WRITEUICRNS_SET (1 << 0) /* Allow non-secure code to set APPROTECT */ +#define NVMC_WRITEUICRNS_KEY (0xAFBE5A7 << 4) + +#endif /* __ARCH_ARM_SRC_NRF91_HARDWARE_NRF91_NVMC_H */ diff --git a/arch/arm/src/nrf91/hardware/nrf91_power.h b/arch/arm/src/nrf91/hardware/nrf91_power.h new file mode 100644 index 0000000000..e69de29bb2 diff --git a/arch/arm/src/nrf91/hardware/nrf91_rtc.h b/arch/arm/src/nrf91/hardware/nrf91_rtc.h new file mode 100644 index 0000000000..4240846c7c --- /dev/null +++ b/arch/arm/src/nrf91/hardware/nrf91_rtc.h @@ -0,0 +1,110 @@ +/**************************************************************************** + * arch/arm/src/nrf91/hardware/nrf91_rtc.h + * + * 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. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_NRF91_HARDWARE_NRF91_RTC_H +#define __ARCH_ARM_SRC_NRF91_HARDWARE_NRF91_RTC_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include "hardware/nrf91_memorymap.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Register offsets for RTC *************************************************/ + +#define NRF91_RTC_TASKS_START_OFFSET 0x0000 /* Start RTC counter */ +#define NRF91_RTC_TASKS_STOP_OFFSET 0x0004 /* Stop RTC counter */ +#define NRF91_RTC_TASKS_CLEAR_OFFSET 0x0008 /* Clear RTC counter */ +#define NRF91_RTC_TASKS_TRIGOVRFLW_OFFSET 0x000c /* Clear Set counter to 0xfffff0 */ + /* TODO: 0x040 - 0x0c */ +#define NRF91_RTC_EVENTS_TICK_OFFSET 0x0100 /* Event on counter increment */ +#define NRF91_RTC_EVENTS_OVRFLW_OFFSET 0x0104 /* Event on counter overflow */ +#define NRF91_RTC_EVENTS_COMPARE_OFFSET(x) (0x0140 + ((x) * 0x04)) /* Compare event on CC[x] match */ + /* TODO: 0x180 - 0x200 */ +#define NRF91_RTC_INTENSET_OFFSET 0x0304 /* Enable interrupt */ +#define NRF91_RTC_INTENCLR_OFFSET 0x0308 /* Disable interrupt */ +#define NRF91_RTC_EVTEN_OFFSET 0x0340 /* Enable or disable event routing */ +#define NRF91_RTC_EVTENSET_OFFSET 0x0344 /* Enable event routing */ +#define NRF91_RTC_EVTENCLR_OFFSET 0x0348 /* Disable event routing */ +#define NRF91_RTC_COUNTER_OFFSET 0x0504 /* Current counter value */ +#define NRF91_RTC_PRESCALER_OFFSET 0x0508 /* 12 bit prescaler for counter frequency */ +#define NRF91_RTC_CC_OFFSET(x) (0x0540 + ((x) * 0x04)) /* Compare register x */ + +/* Register offsets for RTC *************************************************/ + +/* TASKS_START Register */ + +#define RTC_TASKS_START (1 << 0) /* Bit 0: Start RTC counter */ + +/* TASKS_STOP Register */ + +#define RTC_TASKS_STOP (1 << 0) /* Bit 0: Stop RTC counter */ + +/* TASKS_CLEAR Register */ + +#define RTC_TASKS_CLEAR (1 << 0) /* Bit 0: Clear RTC counter */ + +/* TASKS_TRIGOVRFLW Register */ + +#define RTC_TASKS_TRIGOVRFLW (1 << 0) /* Bit 0: Set counter to 0xfffff0 */ + +/* EVENTS_TICK Register */ + +#define RTC_EVENTS_TICK (1 << 0) /* Bit 0: Event on counter increment */ + +/* EVENTS_OVRFLW Register */ + +#define RTC_EVENTS_OVRFLW (1 << 0) /* Bit 0: Event on counter overflow */ + +/* EVENTS_COMPARE Register */ + +#define RTC_EVENTS_COMPARE (1 << 0) /* Bit 0: Eompare event on CC[x] match */ + +/* INTENSET/INTENCLR Register */ + +#define RTC_INT_TICK (1 << 0) /* Bit 0: TICK interrupt*/ +#define RTC_INT_OVRFLW (1 << 1) /* Bit 1: OVRFLW interrupt */ +#define RTC_INT_COMPARE(x) (1 << (16 + (x))) /* Bit 16-19: COMPARE[x] interrupt */ + +/* EVTEN/EVTENSET/EVTSENCLR Register */ + +#define RTC_EVTEN_TICK (1 << 0) /* Bit 0: TICK event */ +#define RTC_EVTEN_OVRFLW (1 << 1) /* Bit 1: OVRFLW event */ +#define RTC_EVTEN_COMPARE(x) (1 << (16 + (x))) /* Bit 16-19: COMPARE[x] event */ + +/* COUNTER Register */ + +#define RTC_COUNTER_MASK (0x00ffffff) /* Bits 0-23: Counter value */ + +/* PRESCALER Register */ + +#define RTC_PRESCALER_MASK (0x00000fff) /* Bits 0-11: Prescaler value */ +#define RTC_PRESCALER_MAX (0x00000fff) + +/* CC Register */ + +#define RTC_CC_MASK (0x00ffffff) /* Bits 0-23: Compare register */ + +#endif /* __ARCH_ARM_SRC_NRF91_HARDWARE_NRF91_RTC_H */ diff --git a/arch/arm/src/nrf91/hardware/nrf91_spi.h b/arch/arm/src/nrf91/hardware/nrf91_spi.h new file mode 100644 index 0000000000..5763e353f5 --- /dev/null +++ b/arch/arm/src/nrf91/hardware/nrf91_spi.h @@ -0,0 +1,216 @@ +/**************************************************************************** + * arch/arm/src/nrf91/hardware/nrf91_spi.h + * + * 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. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_NRF91_HARDWARE_NRF91_SPI_H +#define __ARCH_ARM_SRC_NRF91_HARDWARE_NRF91_SPI_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include "hardware/nrf91_memorymap.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Register offsets for SPI master (SPIM) ***********************************/ + +#define NRF91_SPIM_TASK_START_OFFSET (0x0010) /* Start SPI transaction */ +#define NRF91_SPIM_TASK_STOP_OFFSET (0x0014) /* Stop SPI transaction */ +#define NRF91_SPIM_TASK_SUSPEND_OFFSET (0x001c) /* Suspend SPI transaction */ +#define NRF91_SPIM_TASK_RESUME_OFFSET (0x0020) /* Resume SPI transaction */ + /* TODO: 0x090 - 0x0a0 */ +#define NRF91_SPIM_EVENTS_STOPPED_OFFSET (0x0104) /* SPI transaction has stopped */ +#define NRF91_SPIM_EVENTS_ENDRX_OFFSET (0x0110) /* End of RXD buffer reached */ +#define NRF91_SPIM_EVENTS_END_OFFSET (0x0118) /* End of RXD buffer and TXD buffer reached */ +#define NRF91_SPIM_EVENTS_ENDTX_OFFSET (0x0120) /* End of TXD buffer reached */ +#define NRF91_SPIM_EVENTS_STARTED_OFFSET (0x014c) /* Transaction started */ + /* TODO: 0x184 - 0x1cc */ +#define NRF91_SPIM_SHORTS_OFFSET (0x0200) /* Shortcuts between local events and tasks */ +#define NRF91_SPIM_INTENSET_OFFSET (0x0304) /* Enable interrupt */ +#define NRF91_SPIM_INTENCLR_OFFSET (0x0308) /* Disable interrupt */ +#define NRF91_SPIM_STALLSTAT_OFFSET (0x0400) /* Stall status for EasyDMA RAM accesses */ +#define NRF91_SPIM_ENABLE_OFFSET (0x0500) /* Enable SPIM */ +#define NRF91_SPIM_PSELSCK_OFFSET (0x0508) /* Pin select for SCK */ +#define NRF91_SPIM_PSELMOSI_OFFSET (0x050c) /* Pin select for MOSI */ +#define NRF91_SPIM_PSELMISO_OFFSET (0x0510) /* Pin select for MISO */ +#define NRF91_SPIM_PSELCSN_OFFSET (0x0514) /* Pin select for CSN */ +#define NRF91_SPIM_FREQUENCY_OFFSET (0x0524) /* SPI frequency. */ +#define NRF91_SPIM_RXDPTR_OFFSET (0x0534) /* Data pointer */ +#define NRF91_SPIM_RXDMAXCNT_OFFSET (0x0538) /* Maximum number of bytes in receive buffer */ +#define NRF91_SPIM_RXDMAMOUNT_OFFSET (0x053c) /* Number of bytes transferred in the last transaction */ +#define NRF91_SPIM_RXDLIST_OFFSET (0x0540) /* RXD EasyDMA list type */ +#define NRF91_SPIM_TXDPTR_OFFSET (0x0544) /* Data pointer */ +#define NRF91_SPIM_TXDMAXCNT_OFFSET (0x0548) /* Number of bytes in transmit buffer */ +#define NRF91_SPIM_TXDAMOUNT_OFFSET (0x054c) /* Number of bytes transferred in the last transaction */ +#define NRF91_SPIM_TXDLIST_OFFSET (0x0550) /* TXD EasyDMA list type */ +#define NRF91_SPIM_CONFIG_OFFSET (0x0554) /* Configuration register */ +#define NRF91_SPIM_RXDELAY_OFFSET (0x0560) /* Sample delay for input serial data on MISO */ +#define NRF91_SPIM_CSNDUR_OFFSET (0x0564) /* IFTIMING.CSNDUR */ +#define NRF91_SPIM_CSNPOL_OFFSET (0x0568) /* Polarity of CSN output */ +#define NRF91_SPIM_PSELDCX_OFFSET (0x056c) /* Pin select for DCX signal */ +#define NRF91_SPIM_DCXCNT_OFFSET (0x0570) /* DCX configuration */ +#define NRF91_SPIM_ORC_OFFSET (0x05c0) /* ORC */ + +/* Register offsets for SPI slave (SPIS) ************************************/ + + /* TODO: 0x024 - 0x1a8 */ +#define NRF91_SPIS_SHORTS_OFFSET (0x0200) /* Shortcuts between local events and tasks */ +#define NRF91_SPIS_INTENSET_OFFSET (0x0304) /* Enable interrupt */ +#define NRF91_SPIS_INTENCLR_OFFSET (0x0308) /* Disable interrupt */ +#define NRF91_SPIS_SEMSTAT_OFFSET (0x0400) /* Semaphore status register */ +#define NRF91_SPIS_STATUS_OFFSET (0x0440) /* Status from last transaction */ +#define NRF91_SPIS_ENABLE_OFFSET (0x0500) /* Enable SPIS */ +#define NRF91_SPIS_PSELSCK_OFFSET (0x0508) /* Pin select for SCK */ +#define NRF91_SPIS_PSELMOSI_OFFSET (0x050c) /* Pin select for MOSI signal */ +#define NRF91_SPIS_PSELMISO_OFFSET (0x0510) /* Pin select for MISO signal */ +#define NRF91_SPIS_PSELCSN_OFFSET (0x0514) /* Pin select for CSN */ +#define NRF91_SPIS_RXDPTR_OFFSET (0x0534) /* Data pointer */ +#define NRF91_SPIS_RXDMAXCNT_OFFSET (0x0538) /* Maximum number of bytes in receive buffer */ +#define NRF91_SPIS_RXDMAMOUNT_OFFSET (0x053c) /* Number of bytes transferred in the last transaction */ +#define NRF91_SPIS_RXDLIST_OFFSET (0x0540) /* RXD EasyDMA list type */ +#define NRF91_SPIS_TXDPTR_OFFSET (0x0544) /* Data pointer */ +#define NRF91_SPIS_TXDMAXCNT_OFFSET (0x0548) /* Number of bytes in transmit buffer */ +#define NRF91_SPIS_TXDAMOUNT_OFFSET (0x054c) /* Number of bytes transferred in the last transaction */ +#define NRF91_SPIS_TXDLIST_OFFSET (0x0550) /* TXD EasyDMA list type */ +#define NRF91_SPIS_CONFIG_OFFSET (0x0554) /* Configuration register */ +#define NRF91_SPIS_DEF_OFFSET (0x055c) /* Default character */ +#define NRF91_SPIS_ORC_OFFSET (0x05c0) /* Over-read character */ + +/* Register Bitfield Definitions for SPIM ***********************************/ + +/* TASKS_START Register */ + +#define SPIM_TASKS_START (1 << 0) /* Bit 0: Start SPI transaction */ + +/* TASKS_STOP Register */ + +#define SPIM_TASKS_STOP (1 << 0) /* Bit 0: Stop SPI transaction */ + +/* TASKS_SUSPEND Register */ + +#define SPIM_TASKS_SUSPEND (1 << 0) /* Bit 0: Suspend SPI transaction */ + +/* TASKS_RESUME Register */ + +#define SPIM_TASKS_RESUME (1 << 0) /* Bit 0: Resume SPI transaction */ + +/* EVENTS_STOPPED Register */ + +#define SPIM_EVENTS_STOPPED (1 << 0) /* Bit 0: SPI transaction has stopped */ + +/* EVENTS_ENDRX Register */ + +#define SPIM_EVENTS_ENDRX (1 << 0) /* Bit 0: End of RXD buffer reached */ + +/* EVENTS_END Register */ + +#define SPIM_EVENTS_END (1 << 0) /* Bit 0: End of RXD buffer and TXD buffer reached */ + +/* EVENTS_ENDTX Register */ + +#define SPIM_EVENTS_ENDTX (1 << 0) /* Bit 0: End of TXD buffer reached */ + +/* EVENTS_STARTED Register */ + +#define SPIM_EVENTS_STARTED (1 << 0) /* Bit 0: Transaction started */ + +/* SHORTS Register */ + +#define SPIM_SHORTS_ENDSTART (1 << 0) /* Bit 0: Shortcut between event END and task START */ + +/* INTENSET/INTENCLR Register */ + +#define SPIM_INT_STOPPED (1 << 1) /* Bit 1: Enable interrupt for STOPPED */ +#define SPIM_INT_ENDRX (1 << 4) /* Bit 4: Enable interrupt for ENDRX */ +#define SPIM_INT_END (1 << 6) /* Bit 6: Enable interrupt for END */ +#define SPIM_INT_ENDTX (1 << 8) /* Bit 8: Enable interrupt for ENDTX */ +#define SPIM_INT_STARTED (1 << 19) /* Bit 19: Enable interrupt for STARTED */ + +/* STALLLSTAT Register */ + +#define SPIM_STALLSTAT_RX (1 << 0) /* Bit 0: Stall status for EasyDMA RAM reads */ +#define SPIM_STALLSTAT_TX (1 << 1) /* Bit 1: Stall status for EasyDMA RAM writes */ + +/* ENABLE Register */ + +#define SPIM_ENABLE_DIS (0) /* Disable SPIM */ +#define SPIM_ENABLE_EN (0x7 << 0) /* Enable SPIM */ + +/* PSEL* Registers */ + +#define SPIM_PSEL_PIN_SHIFT (0) /* Bits 0-4: SCK pin number */ +#define SPIM_PSEL_PIN_MASK (0x1f << SPIM_PSELSCK_PIN_SHIFT) +#define SPIM_PSEL_PORT_SHIFT (5) /* Bit 5: SCK port number */ +#define SPIM_PSEL_PORT_MASK (0x1 << SPIM_PSELSCK_PORT_SHIFT) +#define SPIM_PSEL_CONNECTED (1 << 31) /* Bit 31: Connection */ +#define SPIM_PSEL_RESET (0xffffffff) + +/* FREQUENCY Register */ + +#define SPIM_FREQUENCY_125KBPS (0x02000000) /* 125 kbps */ +#define SPIM_FREQUENCY_250KBPS (0x04000000) /* 250 kbps */ +#define SPIM_FREQUENCY_500KBPS (0x08000000) /* 500 kbps */ +#define SPIM_FREQUENCY_1MBPS (0x10000000) /* 1 Mbps */ +#define SPIM_FREQUENCY_2MBPS (0x20000000) /* 2 Mbps */ +#define SPIM_FREQUENCY_4MBPS (0x40000000) /* 4 Mbps */ +#define SPIM_FREQUENCY_8MBPS (0x80000000) /* 8 Mbps */ + +/* RXDMAXCNT Register */ + +#define SPIM_RXDMAXCNT_SHIFT (0) /* Bits 0-15: Maximum number of bytes in receive buffer */ +#define SPIM_RXDMAXCNT_MASK (0xffff << SPIM_RXDMAXCNT_SHIFT) + +/* RXDAMOUNT Register */ + +#define SPIM_RXDAMOUNT_SHIFT (0) /* Bits 0-15: Number of bytes transferred in the last transaction */ +#define SPIM_RXDAMOUNT_MASK (0xffff << SPIM_RXDAMOUNT_SHIFT) + +/* TXDMAXCNT Register */ + +#define SPIM_TXDMAXCNT_SHIFT (0) /* Bits 0-15: Maximum number of bytes in transmit buffer */ +#define SPIM_TXDMAXCNT_MASK (0xffff << SPIM_TXDMAXCNT_MASK) + +/* TXDAMOUNT Register */ + +#define SPIM_TXDAMOUNT_SHIFT (0) /* Bits 0-15: Number of bytes transferred in the last transaction */ +#define SPIM_TXDAMOUNT_MASK (0xffff << SPIM_TXDAMOUNT_SHIFT) + +/* CONFIG Register */ + +#define SPIM_CONFIG_ORDER (1 << 0) /* Bit 0: Bit order */ +#define SPIM_CONFIG_CPHA (1 << 1) /* Bit 1: Serial clock phase */ +#define SPIM_CONFIG_CPOL (1 << 2) /* Bit 2: Serial clock polarity */ + +/* PSELDCX Register */ + +#define SPIM_PSELDCX_PIN_SHIFT (0) /* Bits 0-4: DCX pin number */ +#define SPIM_PSELDCX_PIN_MASK (0x1f << SPIM_PSELDCX_PIN_SHIFT) +#define SPIM_PSELDCX_PORT_SHIFT (5) /* Bit 5: SCK port number */ +#define SPIM_PSELDCX_PORT_MASK (0x1 << SPIM_PSELDCX_PORT_SHIFT) +#define SPIM_PSELDCX_CONNECTED (1 << 31) /* Bit 31: Connection */ + +/* Register Bitfield Definitions for SPIS ***********************************/ + +/* TODO */ + +#endif /* __ARCH_ARM_SRC_NRF91_HARDWARE_NRF91_SPI_H */ diff --git a/arch/arm/src/nrf91/hardware/nrf91_spu.h b/arch/arm/src/nrf91/hardware/nrf91_spu.h new file mode 100644 index 0000000000..a7771169c2 --- /dev/null +++ b/arch/arm/src/nrf91/hardware/nrf91_spu.h @@ -0,0 +1,114 @@ +/**************************************************************************** + * arch/arm/src/nrf91/hardware/nrf91_spu.h + * + * 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. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_NRF91_HARDWARE_NRF91_SPU_H +#define __ARCH_ARM_SRC_NRF91_HARDWARE_NRF91_SPU_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include "nrf91_memorymap.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Register offsets *********************************************************/ + +#define NRF91_SPU_EVENTS_RAMACCERR_OFFSET 0x100 /* A security violation has been detected for the RAM memory space */ +#define NRF91_SPU_EVENTS_FLASHACCERR_OFFSET 0x104 /* A security violation has been detected for the FLASH memory space */ +#define NRF91_SPU_EVENTS_PERIPHACCERR_OFFSET 0x108 /* A security violation has been detected on one or several peripherals */ +#define NRF91_SPU_PUBLISH_RAMACCERR_OFFSET 0x180 /* Publish configuration for event RAMACCERR */ +#define NRF91_SPU_PUBLISH_FLASHACCERR_OFFSET 0x184 /* Publish configuration for event FLASHACCERR */ +#define NRF91_SPU_PUBLISH_PERIPHACCERR_OFFSET 0x188 /* Publish configuration for event PERIPHACCERR */ +#define NRF91_SPU_INTEN_OFFSET 0x300 /* Enable or disable interrupt */ +#define NRF91_SPU_INTSEL_OFFSET 0x304 /* Enable interrupt */ +#define NRF91_SPU_INTCLR_OFFSET 0x308 /* Disable interrupt */ +#define NRF91_SPU_CAP_OFFSET 0x400 /* Show implemented features for the current device */ +#define NRF91_SPU_CPULOCK_OFFSET 0x404 /* Configure bits to lock down CPU features at runtime */ +#define NRF91_SPU_EXTDOMAIN_OFFSET(n) (0x440 + (0x4 * n)) /* Access for bus access generated from the external domain n */ +#define NRF91_SPU_DPPIPERM_OFFSET(n) (0x480 + (0x8 * n)) /* Select between secure and non-secure attribute for the DPPI channels. */ +#define NRF91_SPU_DPPILOCK_OFFSET(n) (0x484 + (0x8 * n)) /* Prevent further modification of the corresponding PERM register */ +#define NRF91_SPU_GPIOPORTPERM_OFFSET(n) (0x4C0 + (0x8 * n)) /* Select between secure and non-secure attribute for pins 0 to 31 of port n. */ +#define NRF91_SPU_GPIOPORTLOCK_OFFSET(n) (0x4C4 + (0x8 * n)) /* Prevent further modification of the corresponding PERM register */ +#define NRF91_SPU_FLASHNSCREGION_OFFSET(n) (0x500 + (0x8 * n)) /* Define which flash region can contain the non-secure callable (NSC) region n */ +#define NRF91_SPU_FLASHNSCSIZE_OFFSET(n) (0x504 + (0x8 * n)) /* Define the size of the non-secure callable (NSC) region n */ +#define NRF91_SPU_RAMNSCREGION_OFFSET(n) (0x540 + (0x8 * n)) /* Define which RAM region can contain the non-secure callable (NSC) region n */ +#define NRF91_SPU_RAMNSCSIZE_OFFSET(n) (0x544 + (0x8 * n)) /* Define the size of the non-secure callable (NSC) region n */ +#define NRF91_SPU_FLASHREGIONPERM_OFFSET(n) (0x600 + (0x4 * n)) /* Access permissions for flash region n */ +#define NRF91_SPU_RAMREGIONPERM_OFFSET(n) (0x700 + (0x4 * n)) /* Access permissions for RAM region n */ +#define NRF91_SPU_PERIPHIDPERM_OFFSET(n) (0x800 + (0x4 * n)) /* List capabilities and access permissions for the peripheral with ID n */ + +/* Register definitions *****************************************************/ + +#define NRF91_SPU_EVENTS_RAMACCERR (NRF91_SPU_BASE + NRF91_SPU_EVENTS_RAMACCERR_OFFSET) +#define NRF91_SPU_EVENTS_FLASHACCERR (NRF91_SPU_BASE + NRF91_SPU_EVENTS_FLASHACCERR_OFFSET) +#define NRF91_SPU_EVENTS_PERIPHACCERR (NRF91_SPU_BASE + NRF91_SPU_EVENTS_PERIPHACCERR_OFFSET) +#define NRF91_SPU_PUBLISH_RAMACCERR (NRF91_SPU_BASE + NRF91_SPU_PUBLISH_RAMACCERR_OFFSET) +#define NRF91_SPU_PUBLISH_FLASHACCERR (NRF91_SPU_BASE + NRF91_SPU_PUBLISH_FLASHACCERR_OFFSET) +#define NRF91_SPU_PUBLISH_PERIPHACCERR (NRF91_SPU_BASE + NRF91_SPU_PUBLISH_PERIPHACCERR_OFFSET) +#define NRF91_SPU_INTEN (NRF91_SPU_BASE + NRF91_SPU_INTEN_OFFSET) +#define NRF91_SPU_INTSEL (NRF91_SPU_BASE + NRF91_SPU_INTSEL_OFFSET) +#define NRF91_SPU_INTCLR (NRF91_SPU_BASE + NRF91_SPU_INTCLR_OFFSET) +#define NRF91_SPU_CAP (NRF91_SPU_BASE + NRF91_SPU_CAP_OFFSET) +#define NRF91_SPU_CPULOCK (NRF91_SPU_BASE + NRF91_SPU_CPULOCK_OFFSET) +#define NRF91_SPU_EXTDOMAIN(n) (NRF91_SPU_BASE + NRF91_SPU_EXTDOMAIN_OFFSET(n)) +#define NRF91_SPU_DPPIPERM(n) (NRF91_SPU_BASE + NRF91_SPU_DPPIPERM_OFFSET(n)) +#define NRF91_SPU_DPPILOCK(n) (NRF91_SPU_BASE + NRF91_SPU_DPPILOCK_OFFSET(n)) +#define NRF91_SPU_GPIOPORTPERM(n) (NRF91_SPU_BASE + NRF91_SPU_GPIOPORTPERM_OFFSET(n)) +#define NRF91_SPU_GPIOPORTLOCK(n) (NRF91_SPU_BASE + NRF91_SPU_GPIOPORTLOCK_OFFSET(n)) +#define NRF91_SPU_FLASHNSCREGION(n) (NRF91_SPU_BASE + NRF91_SPU_FLASHNSCREGION_OFFSET(n)) +#define NRF91_SPU_FLASHNSCSIZE(n) (NRF91_SPU_BASE + NRF91_SPU_FLASHNSCSIZE_OFFSET(n)) +#define NRF91_SPU_RAMNSCREGION(n) (NRF91_SPU_BASE + NRF91_SPU_RAMNSCREGION_OFFSET(n)) +#define NRF91_SPU_RAMNSCSIZE(n) (NRF91_SPU_BASE + NRF91_SPU_RAMNSCSIZE_OFFSET(n)) +#define NRF91_SPU_FLASHREGIONPERM(n) (NRF91_SPU_BASE + NRF91_SPU_FLASHREGIONPERM_OFFSET(n)) +#define NRF91_SPU_RAMREGIONPERM(n) (NRF91_SPU_BASE + NRF91_SPU_RAMREGIONPERM_OFFSET(n)) +#define NRF91_SPU_PERIPHIDPERM(n) (NRF91_SPU_BASE + NRF91_SPU_PERIPHIDPERM_OFFSET(n)) + +/* Register bit definitions *************************************************/ + +#define SPU_RAM_REGIONS (32) +#define SPU_FLASH_REGIONS (32) + +#define SPU_EXTDOMAIN_SECUREMAPPING_SHIFT (0) +#define SPU_EXTDOMAIN_SECUREMAPPING_MASK (3 << SPU_EXTDOMAIN_SECUREMAPPING_SHIFT) +# define SPU_EXTDOMAIN_SECUREMAPPING_NONSEC (0 << SPU_EXTDOMAIN_SECUREMAPPING_SHIFT) +# define SPU_EXTDOMAIN_SECUREMAPPING_SEC (1 << SPU_EXTDOMAIN_SECUREMAPPING_SHIFT) +# define SPU_EXTDOMAIN_SECUREMAPPING_USER (2 << SPU_EXTDOMAIN_SECUREMAPPING_SHIFT) +#define SPU_EXTDOMAIN_SECUREMAPPING_SECATTR (1 << 4) +#define SPU_EXTDOMAIN_SECUREMAPPING_LOCK (1 << 8) + +#define SPU_FLASHREGION_PERM_EXEC (1 << 0) +#define SPU_FLASHREGION_PERM_WRITE (1 << 1) +#define SPU_FLASHREGION_PERM_READ (1 << 2) +#define SPU_FLASHREGION_PERM_SECATTR (1 << 4) +#define SPU_FLASHREGION_PERM_LOCK (1 << 8) + +#define SPU_RAMREGION_PERM_EXEC (1 << 0) +#define SPU_RAMREGION_PERM_WRITE (1 << 1) +#define SPU_RAMREGION_PERM_READ (1 << 2) +#define SPU_RAMREGION_PERM_SECATTR (1 << 4) +#define SPU_RAMREGION_PERM_LOCK (1 << 8) + +#define SPU_PERM_SECATTR (1 << 4) + +#endif /* __ARCH_ARM_SRC_NRF91_HARDWARE_NRF91_SPU_H */ diff --git a/arch/arm/src/nrf91/hardware/nrf91_tim.h b/arch/arm/src/nrf91/hardware/nrf91_tim.h new file mode 100644 index 0000000000..10617b8a2e --- /dev/null +++ b/arch/arm/src/nrf91/hardware/nrf91_tim.h @@ -0,0 +1,113 @@ +/**************************************************************************** + * arch/arm/src/nrf91/hardware/nrf91_tim.h + * + * 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. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_NRF91_HARDWARE_NRF91_TIM_H +#define __ARCH_ARM_SRC_NRF91_HARDWARE_NRF91_TIM_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include "hardware/nrf91_memorymap.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* TIMER constants **********************************************************/ + +#define TIMER_BASE_FERQUENCY (16000000) + +/* Register offsets for TIM *************************************************/ + +#define NRF91_TIM_TASKS_START_OFFSET 0x0000 /* Start Timer */ +#define NRF91_TIM_TASKS_STOP_OFFSET 0x0004 /* Stop Timer */ +#define NRF91_TIM_TASKS_COUNT_OFFSET 0x0008 /* Increment Timer */ +#define NRF91_TIM_TASKS_CLEAR_OFFSET 0x000c /* Clear time */ +#define NRF91_TIM_TASKS_SHUTDOWN_OFFSET 0x0010 /* Shutdown Timer */ +#define NRF91_TIM_TASKS_CAPTURE_OFFSET(x) (0x0040 + ((x) * 4)) /* Capture Timer value to CC[x] */ +#define NRF91_TIM_EVENTS_COMPARE_OFFSET(x) (0x0140 + ((x) * 4)) /* Compare event on CC[x] */ + /* TODO: 0x080-0x1c0 */ +#define NRF91_TIM_SHORTS_OFFSET 0x0200 /* Shortcuts between local events and tasks */ +#define NRF91_TIM_INTEN_OFFSET 0x0300 /* Enable or disable interrupt */ +#define NRF91_TIM_INTENSET_OFFSET 0x0304 /* Enable interrupt */ +#define NRF91_TIM_INTCLR_OFFSET 0x0308 /* Disable interrupt */ +#define NRF91_TIM_MODE_OFFSET 0x0504 /* Timer mode selection */ +#define NRF91_TIM_BITMODE_OFFSET 0x0508 /* Configure the number of bits used by the Timer */ +#define NRF91_TIM_PRESCALER_OFFSET 0x0510 /* Timer prescaler register */ +#define NRF91_TIM_CC_OFFSET(x) (0x0540 + ((x) * 4)) /* Capture/Compare register x */ +#define NRF91_TIM_ONESHOT_OFFSET(x) (0x0580 + ((x) * 4)) /* Enable one-shot operation for Capture/Compare channel x */ + +/* Register offsets for TIM *************************************************/ + +/* TASKS_START Register */ + +#define TIM_TASKS_START (1 << 0) /* Bit 0: Start Timer */ + +/* TASKS_STOP Register */ + +#define TIM_TASKS_STOP (1 << 0) /* Bit 0: Stop Timer */ + +/* TASKS_COUNT Register */ + +#define TIM_TASKS_COUNT (1 << 0) /* Bit 0: Increment Timer */ + +/* TASKS_CLEAR Register */ + +#define TIM_TASKS_CLEAR (1 << 0) /* Bit 0: Clear Timer */ + +/* SHORTS Register */ + +#define TIM_SHORTS_COMPARE_CLEAR(x) (1 << (x)) /* Bits 0-5: */ +#define TIM_SHORTS_COMPARE_STOP(x) (1 << (x + 8)) /* Bits 8-13 */ + +/* INTENSET/INTENCLR Register */ + +#define TIM_INT_COMPARE(x) (1 << (x + 16)) /* Bits 16-21 */ + +/* MODE Register */ + +#define TIM_MODE_SHIFT (0) /* Bits 0-1: Timer mode */ +#define TIM_MODE_MASK (0x3 << TIM_MODE_SHIFT) +# define TIM_MODE_TIMER (0x0 << TIM_MODE_SHIFT) /* 0: Timer mode */ +# define TIM_MODE_COUNTER (0x1 << TIM_MODE_SHIFT) /* 1: Counter mode */ +# define TIM_MODE_LPCOUNTER (0x2 << TIM_MODE_SHIFT) /* 2: Low Power Counter mode */ + +/* BITMODE Register */ + +#define TIM_BITMODE_SHIFT (0) /* Bits 0-1: Timer bit width */ +#define TIM_BITMODE_MASK (0x3 << TIM_BITMODE_SHIFT) +# define TIM_BITMODE_16B (0x0 << TIM_BITMODE_SHIFT) /* 0: 16 bit */ +# define TIM_BITMODE_8B (0x1 << TIM_BITMODE_SHIFT) /* 1: 8 bit */ +# define TIM_BITMODE_24B (0x2 << TIM_BITMODE_SHIFT) /* 2: 24 bit */ +# define TIM_BITMODE_32B (0x3 << TIM_BITMODE_SHIFT) /* 3: 32 bit */ + +/* PRESCALER Register */ + +#define TIM_PRESCALER_SHIFT (0) /* Bits 0-3: Prescaler value */ +#define TIM_PRESCALER_MAX (9) +#define TIM_PRESCALER_MASK (TIM_PRESCALER_MAX << TIM_PRESCALER_SHIFT) + +/* ONESHOT Register */ + +#define TIM_ONESHOT_EN (1 << 0) /* Bit 0: Enable one-shot operation */ + +#endif /* __ARCH_ARM_SRC_NRF91_HARDWARE_NRF91_TIM_H */ diff --git a/arch/arm/src/nrf91/hardware/nrf91_twi.h b/arch/arm/src/nrf91/hardware/nrf91_twi.h new file mode 100644 index 0000000000..8697fabea1 --- /dev/null +++ b/arch/arm/src/nrf91/hardware/nrf91_twi.h @@ -0,0 +1,190 @@ +/**************************************************************************** + * arch/arm/src/nrf91/hardware/nrf91_twi.h + * + * 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. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_NRF91_HARDWARE_NRF91_TWI_H +#define __ARCH_ARM_SRC_NRF91_HARDWARE_NRF91_TWI_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include "hardware/nrf91_memorymap.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Register offsets for TWI master (TWIM) ***********************************/ + +#define NRF91_TWIM_TASKS_STARTRX_OFFSET 0x0000 /* Start TWIM receive sequence */ +#define NRF91_TWIM_TASKS_STARTTX_OFFSET 0x0008 /* Start TWIM transmit sequence */ +#define NRF91_TWIM_TASKS_STOP_OFFSET 0x0014 /* Stop TWIM transaction */ +#define NRF91_TWIM_TASKS_SUSPEND_OFFSET 0x001c /* Suspend TWIM transaction */ +#define NRF91_TWIM_TASKS_RESUME_OFFSET 0x0020 /* Resume TWIM transaction */ + /* TODO: 0x080 - 0x0a0 */ +#define NRF91_TWIM_EVENTS_STOPPED_OFFSET 0x0104 /* TWIM stopped */ +#define NRF91_TWIM_EVENTS_ERROR_OFFSET 0x0124 /* TWIM error */ +#define NRF91_TWIM_EVENTS_SUSPENDED_OFFSET 0x0148 /* Last byte has been sent out after the SUSPEND task has been issued */ +#define NRF91_TWIM_EVENTS_RXSTARTED_OFFSET 0x014c /* Receive sequence started */ +#define NRF91_TWIM_EVENTS_TXSTARTED_OFFSET 0x0150 /* Transmit sequence started */ +#define NRF91_TWIM_EVENTS_LASTRX_OFFSET 0x015c /* Byte boundary, starting to receive the last byte */ +#define NRF91_TWIM_EVENTS_LASTTX_OFFSET 0x0160 /* Byte boundary, starting to transmit the last byte */ + /* TODO: 0x184 - 0x1e0 */ +#define NRF91_TWIM_SHORTS_OFFSET 0x0200 /* Shortcuts between local events and tasks */ +#define NRF91_TWIM_INTEN_OFFSET 0x0300 /* Enable or disable interrupt */ +#define NRF91_TWIM_INTENSET_OFFSET 0x0304 /* Enable interrupt */ +#define NRF91_TWIM_INTENCLR_OFFSET 0x0308 /* Disable interrupt */ +#define NRF91_TWIM_ERRORSRC_OFFSET 0x04c4 /* Error source */ +#define NRF91_TWIM_ENABLE_OFFSET 0x0500 /* Enable TWIMS */ +#define NRF91_TWIM_PSELSCL_OFFSET 0x0508 /* Pin select for SCL signal */ +#define NRF91_TWIM_PSELSDA_OFFSET 0x050c /* Pin select for SDA signal */ +#define NRF91_TWIM_FREQUENCY_OFFSET 0x0524 /* TWIM frequency */ +#define NRF91_TWIM_RXDPTR_OFFSET 0x0534 /* RXD Data pointer */ +#define NRF91_TWIM_RXDMAXCNT_OFFSET 0x0538 /* Maximum number of bytes in RXD buffer */ +#define NRF91_TWIM_RXDAMOUNT_OFFSET 0x053c /* Number of bytes transferred in the last RXD transaction */ +#define NRF91_TWIM_RXDLIST_OFFSET 0x0540 /* RX EasyDMA list type */ +#define NRF91_TWIM_TXDPTR_OFFSET 0x0544 /* TXD Data pointer */ +#define NRF91_TWIM_TXMAXCNT_OFFSET 0x0548 /* Maximum number of bytes in TXD buffer */ +#define NRF91_TWIM_TXAMOUNT_OFFSET 0x054c /* Number of bytes transferred in the last TXD transaction */ +#define NRF91_TWIM_TXLIST_OFFSET 0x0550 /* TX EasyDMA list type */ +#define NRF91_TWIM_ADDRESS_OFFSET 0x0588 /* TWIM address */ + +/* Register offsets for TWI slave (TWIS) ************************************/ + +#define NRF91_TWIS_TASKS_STOP_OFFSET 0x0014 /* Stop TWIS transaction */ +#define NRF91_TWIS_TASKS_SUSPEND_OFFSET 0x001c /* Suspend TWIS transaction */ +#define NRF91_TWIS_TASKS_RESUME_OFFSET 0x0020 /* Resume TWIS transaction */ +#define NRF91_TWIS_TASKS_PREPARERX_OFFSET 0x0030 /* Prepare the TWIS slave to respond to a write command */ +#define NRF91_TWIS_TASKS_PREPARETX_OFFSET 0x0034 /* Prepare the TWIS slave to respond to a read command */ +#define NRF91_TWIS_EVENTS_STOPPED_OFFSET 0x0104 /* TWIS stopped */ +#define NRF91_TWIS_EVENTS_ERROR_OFFSET 0x0124 /* TWIS error */ +#define NRF91_TWIS_EVENTS_RXSTARTED_OFFSET 0x014c /* Receive sequence started */ +#define NRF91_TWIS_EVENTS_TXSTARTED_OFFSET 0x0150 /* Transmit sequence started */ +#define NRF91_TWIS_EVENTS_WRITE_OFFSET 0x0164 /* Write command received */ +#define NRF91_TWIS_EVENTS_READ_OFFSET 0x0168 /* Read command received */ +#define NRF91_TWIS_SHORTS_OFFSET 0x0200 /* Shortcuts between local events and tasks */ +#define NRF91_TWIS_INTEN_OFFSET 0x0300 /* Enable or disable interrupt */ +#define NRF91_TWIS_INTENSET_OFFSET 0x0304 /* Enable interrupt */ +#define NRF91_TWIS_INTENCLR_OFFSET 0x0308 /* Disable interrupt */ +#define NRF91_TWIS_ERRORSRC_OFFSET 0x04d0 /* Error source */ +#define NRF91_TWIS_MATCH_OFFSET 0x04d4 /* Status register indicating which address had a match */ +#define NRF91_TWIS_ENABLE_OFFSET 0x0500 /* Enable TWISS */ +#define NRF91_TWIS_PSELSCL_OFFSET 0x0508 /* Pin select for SCL signal */ +#define NRF91_TWIS_PSELSDA_OFFSET 0x050c /* Pin select for SDA signal */ +#define NRF91_TWIS_RXDPTR_OFFSET 0x0534 /* RXD Data pointer */ +#define NRF91_TWIS_RXDMAXCNT_OFFSET 0x0538 /* Maximum number of bytes in RXD buffer */ +#define NRF91_TWIS_RXDAMOUNT_OFFSET 0x053c /* Number of bytes transferred in the last RXD transaction */ +#define NRF91_TWIS_RXDLIST_OFFSET 0x0540 /* RX EasyDMA list type */ +#define NRF91_TWIS_TXDPTR_OFFSET 0x0544 /* TXD Data pointer */ +#define NRF91_TWIS_TXMAXCNT_OFFSET 0x0548 /* Maximum number of bytes in TXD buffer */ +#define NRF91_TWIS_TXAMOUNT_OFFSET 0x054c /* Number of bytes transferred in the last TXD transaction */ +#define NRF91_TWIS_TXLIST_OFFSET 0x0550 /* TX EasyDMA list type */ +#define NRF91_TWIS_ADDRESS0_OFFSET 0x0588 /* TWIS address 0 */ +#define NRF91_TWIS_ADDRESS1_OFFSET 0x058c /* TWIS address 1 */ +#define NRF91_TWIS_CONFIG_OFFSET 0x0594 /* Configuration register for the address match mechanism */ +#define NRF91_TWIS_ORC_OFFSET 0x05c0 /* Over-read character */ + +/* Register Bitfield Definitions for TWIM ***********************************/ + +/* SHORTS Register */ + +#define TWIM_SHORTS_LASTTX_STARTRX (1 << 7) /* Bit 7: Shortcut between event LASTTX and task STARTRX */ +#define TWIM_SHORTS_LASTTX_SUSPEND (1 << 8) /* Bit 8: Shortcut between event LASTTX and task SUSPEND */ +#define TWIM_SHORTS_LASTTX_STOP (1 << 9) /* Bit 9: Shortcut between event LASTTX and task STOP */ +#define TWIM_SHORTS_LASTRX_STARTTX (1 << 10) /* Bit 10: Shortcut between event LASTRX and task STARTTX */ +#define TWIM_SHORTS_LASTRX_SUSPEND (1 << 11) /* Bit 11: Shortcut between event LASTRX and task SUSPEND */ +#define TWIM_SHORTS_LASTRX_STOP (1 << 12) /* Bit 12: Shortcut between event LASTRX and task STOP */ + +/* INTEN/INTENSET/INTENCLR Register */ + +#define TWIM_INT_STOPPED (1 << 1) /* Bit 1: Interrupt for event STOPPED */ +#define TWIM_INT_ERROR (1 << 9) /* Bit 9: Interrupt for event ERROR */ +#define TWIM_INT_SUSPENDED (1 << 18) /* Bit 18: Interrupt for event SUSPENDED */ +#define TWIM_INT_RXSTARTED (1 << 19) /* Bit 19: Interrupt for event RXSTARTED */ +#define TWIM_INT_TXSTARTED (1 << 20) /* Bit 20: Interrupt for event TXSTARTED */ +#define TWIM_INT_LASTRX (1 << 23) /* Bit 23: Interrupt for event LASTRX */ +#define TWIM_INT_LASTTX (1 << 24) /* Bit 24: Interrupt for event LASTTX */ + +/* ERRORSRC Register */ + +#define TWIM_ERRORSRC_OVERRUN (1 << 0) /* Bit 0: Overrun error */ +#define TWIM_ERRORSRC_ANACK (1 << 1) /* Bit 1: NACK received after sending the address */ +#define TWIM_ERRORSRC_DNACK (1 << 2) /* Bit 2: NACK received after sending a data byte */ + +/* ENABLE Register */ + +#define TWIM_ENABLE_DIS (0) /* Disable TWIM */ +#define TWIM_ENABLE_EN (0x6 << 0) /* Disable TWIM */ + +/* PSELSCL Register */ + +#define TWIM_PSELSCL_PIN_SHIFT (0) /* Bits 0-4: SCL pin number */ +#define TWIM_PSELSCL_PIN_MASK (0x1f << TWIM_PSELSCL_PIN_SHIFT) +#define TWIM_PSELSCL_PORT_SHIFT (5) /* Bit 5: SCL port number */ +#define TWIM_PSELSCL_PORT_MASK (0x1 << TWIM_PSELSCL_PORT_SHIFT) +#define TWIM_PSELSCL_CONNECTED (1 << 31) /* Bit 31: Connection */ +#define TWIM_PSELSCL_RESET (0xffffffff) + +/* PSELSDA Register */ + +#define TWIM_PSELSDA_PIN_SHIFT (0) /* Bits 0-4: SDA pin number */ +#define TWIM_PSELSDA_PIN_MASK (0x1f << TWIM_PSELSDA_PIN_SHIFT) +#define TWIM_PSELSDA_PORT_SHIFT (5) /* Bit 5: SDA port number */ +#define TWIM_PSELSDA_PORT_MASK (0x1 << TWIM_PSELSDA_PORT_SHIFT) +#define TWIM_PSELSDA_CONNECTED (1 << 31) /* Bit 31: Connection */ +#define TWIM_PSELSDA_RESET (0xffffffff) + +/* FREQUENCY Register */ + +#define TWIM_FREQUENCY_100KBPS (0x01980000) /* 100 kbps */ +#define TWIM_FREQUENCY_250KBPS (0x04000000) /* 250 kbps */ +#define TWIM_FREQUENCY_400KBPS (0x06400000) /* 400 kbps */ + +/* RXDMAXCNT Register */ + +#define TWIM_RXDMAXCNT_SHIFT (0) /* Bits 0-15: Maximum number of bytes in receive buffer */ +#define TWIM_RXDMAXCNT_MASK (0xffff << TWIM_RXDMAXCNT_SHIFT) + +/* RXDAMOUNT Register */ + +#define TWIM_RXDAMOUNT_SHIFT (0) /* Bits 0-15: Number of bytes transferred in the last transaction */ +#define TWIM_RXDAMOUNT_MASK (0xffff << TWIM_RXDAMOUNT_SHIFT) + +/* TXDMAXCNT Register */ + +#define TWIM_TXDMAXCNT_SHIFT (0) /* Bits 0-15: Maximum number of bytes in transmit buffer */ +#define TWIM_TXDMAXCNT_MASK (0xffff << TWIM_TXDMAXCNT_SHIFT) + +/* TXDAMOUNT Register */ + +#define TWIM_TXDAMOUNT_SHIFT (0) /* Bits 0-15: Number of bytes transferred in the last transaction */ +#define TWIM_TXDAMOUNT_MASK (0xffff << TWIM_TXDAMOUNT_SHIFT) + +/* ADDRESS Register */ + +#define TWIM_ADDRESS_SHIFT (0) /* Bits 0-6: Address used in the TWI transfer */ +#define TWIM_ADDRESS_MASK (0x7f << TWIM_ADDRESS_SHIFT) + +/* Register Bitfield Definitions for TWIS ***********************************/ + +/* TODO */ + +#endif /* __ARCH_ARM_SRC_NRF91_HARDWARE_NRF91_TWI_H */ diff --git a/arch/arm/src/nrf91/hardware/nrf91_uarte.h b/arch/arm/src/nrf91/hardware/nrf91_uarte.h new file mode 100644 index 0000000000..3b19c0e0f5 --- /dev/null +++ b/arch/arm/src/nrf91/hardware/nrf91_uarte.h @@ -0,0 +1,306 @@ +/*************************************************************************** + * arch/arm/src/nrf91/hardware/nrf91_uarte.h + * + * 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. + * + ***************************************************************************/ + +#ifndef __ARCH_ARM_SRC_NRF91_HARDWARE_NRF91_UARTE_H +#define __ARCH_ARM_SRC_NRF91_HARDWARE_NRF91_UARTE_H + +/*************************************************************************** + * Included Files + ***************************************************************************/ + +#include +#include "hardware/nrf91_memorymap.h" + +/*************************************************************************** + * Pre-processor Definitions + ***************************************************************************/ + +/* UART/UARTE Register Offsets *********************************************/ + +#define NRF91_UARTE_TASKS_STARTRX_OFFSET 0x0000 /* Start UART receiver */ +#define NRF91_UARTE_TASKS_STOPRX_OFFSET 0x0004 /* Stop UART receiver */ +#define NRF91_UARTE_TASKS_STARTTX_OFFSET 0x0008 /* Start UART transmitter */ +#define NRF91_UARTE_TASKS_STOPTX_OFFSET 0x000c /* Stop UART transmitter */ +#define NRF91_UARTE_TASKS_FLUSHRX_OFFSET 0x002c /* Flush RX FIFO into RX buffer */ +#define NRF91_UARTE_EVENTS_CTS_OFFSET 0x0100 /* CTS is activated (set low). Clear To Send. */ +#define NRF91_UARTE_EVENTS_NCTS_OFFSET 0x0104 /* CTS is deactivated (set high). Not Clear To Send. */ +#define NRF91_UARTE_EVENTS_RXDRDY_OFFSET 0x0108 /* Data received in RXD (but potentially not yet transferred to Data RAM) */ +#define NRF91_UARTE_EVENTS_ENDRX_OFFSET 0x0110 /* Receive buffer is filled up */ +#define NRF91_UARTE_EVENTS_TXDRDY_OFFSET 0x011c /* Data sent from TXD */ +#define NRF91_UARTE_EVENTS_ENDTX_OFFSET 0x0120 /* Last TX byte transmitted */ +#define NRF91_UARTE_EVENTS_ERROR_OFFSET 0x0124 /* Error detected */ +#define NRF91_UARTE_EVENTS_RXTO_OFFSET 0x0144 /* Receiver timeout */ +#define NRF91_UARTE_EVENTS_RXSTARTED_OFFSET 0x014c /* UART receiver has started */ +#define NRF91_UARTE_EVENTS_TXSTARTED_OFFSET 0x0150 /* UART transmitter has started */ +#define NRF91_UARTE_EVENTS_TXSTOPPED_OFFSET 0x0158 /* Transmitter stopped */ +#define NRF91_UARTE_SHORTS_OFFSET 0x0200 /* Shortcut register */ +#define NRF91_UARTE_INTEN_OFFSET 0x0300 /* Enable or disable interrupt */ +#define NRF91_UARTE_INTENSET_OFFSET 0x0304 /* Enable interrupt */ +#define NRF91_UARTE_INTENCLR_OFFSET 0x0308 /* Disable interrupt */ +#define NRF91_UARTE_ERRORSRC_OFFSET 0x0480 /* Error source */ +#define NRF91_UARTE_ENABLE_OFFSET 0x0500 /* Enable UART */ +#define NRF91_UARTE_PSEL_RTS_OFFSET 0x0508 /* Pin select for RTS signal */ +#define NRF91_UARTE_PSEL_TXD_OFFSET 0x050c /* Pin select for TXD signal */ +#define NRF91_UARTE_PSEL_CTS_OFFSET 0x0510 /* Pin select for CTS signal */ +#define NRF91_UARTE_PSEL_RXD_OFFSET 0x0514 /* Pin select for RXD signal */ +#define NRF91_UARTE_BAUDRATE_OFFSET 0x0524 /* Baud rate. Accuracy depends on the HFCLK source selected. */ +#define NRF91_UARTE_RXD_PTR_OFFSET 0x0534 /* Data pointer */ +#define NRF91_UARTE_RXD_MAXCNT_OFFSET 0x0538 /* Maximum number of bytes in receive buffer */ +#define NRF91_UARTE_RXD_AMOUNT_OFFSET 0x053c /* Number of bytes transferred in the last transaction */ +#define NRF91_UARTE_TXD_PTR_OFFSET 0x0544 /* Data pointer */ +#define NRF91_UARTE_TXD_MAXCNT_OFFSET 0x0548 /* Maximum number of bytes in transmit buffer */ +#define NRF91_UARTE_TXD_AMOUNT_OFFSET 0x054c /* Number of bytes transferred in the last transaction */ +#define NRF91_UARTE_CONFIG_OFFSET 0x056c /* Configuration of parity and hardware flow control */ + +#define NRF91_UART_TASKS_STARTRX_OFFSET 0x0000 /* Start UART receiver */ +#define NRF91_UART_TASKS_STOPRX_OFFSET 0x0004 /* Stop UART receiver */ +#define NRF91_UART_TASKS_STARTTX_OFFSET 0x0008 /* Start UART transmitter */ +#define NRF91_UART_TASKS_STOPTX_OFFSET 0x000c /* Stop UART transmitter */ +#define NRF91_UART_TASKS_SUSPEND_OFFSET 0x001c /* Suspend UART */ +#define NRF91_UART_EVENTS_CTS_OFFSET 0x0100 /* CTS is activated (set low). Clear To Send. */ +#define NRF91_UART_EVENTS_NCTS_OFFSET 0x0104 /* CTS is deactivated (set high). Not Clear To Send. */ +#define NRF91_UART_EVENTS_RXDRDY_OFFSET 0x0108 /* Data received in RXD */ +#define NRF91_UART_EVENTS_TXDRDY_OFFSET 0x011c /* Data sent from TXD */ +#define NRF91_UART_EVENTS_ERROR_OFFSET 0x0124 /* Error detected */ +#define NRF91_UART_EVENTS_RXTO_OFFSET 0x0144 /* Receiver timeout */ +#define NRF91_UART_SHORTS_OFFSET 0x0200 /* Shortcut register */ +#define NRF91_UART_INTENSET_OFFSET 0x0304 /* Enable interrupt */ +#define NRF91_UART_INTENCLR_OFFSET 0x0308 /* Disable interrupt */ +#define NRF91_UART_ERRORSRC_OFFSET 0x0480 /* Error source */ +#define NRF91_UART_ENABLE_OFFSET 0x0500 /* Enable UART */ +#define NRF91_UART_PSELRTS_OFFSET 0x0508 /* Pin select for RTS */ +#define NRF91_UART_PSELTXD_OFFSET 0x050c /* Pin select for TXD */ +#define NRF91_UART_PSELCTS_OFFSET 0x0510 /* Pin select for CTS */ +#define NRF91_UART_PSELRXD_OFFSET 0x0514 /* Pin select for RXD */ +#define NRF91_UART_RXD_OFFSET 0x0518 /* RXD register */ +#define NRF91_UART_TXD_OFFSET 0x051c /* TXD register */ +#define NRF91_UART_BAUDRATE_OFFSET 0x0524 /* Baud rate */ +#define NRF91_UART_CONFIG_OFFSET 0x056c /* Configuration of parity and hardware flow control */ + +/* UART/UARTE Register Addresses *******************************************/ + +#define NRF91_UARTE0_TASKS_STARTRX (NRF91_UARTE0_BASE + NRF91_UARTE_TASKS_STARTRX_OFFSET) +#define NRF91_UARTE0_TASKS_STOPRX (NRF91_UARTE0_BASE + NRF91_UARTE_TASKS_STOPRX_OFFSET) +#define NRF91_UARTE0_TASKS_STARTTX (NRF91_UARTE0_BASE + NRF91_UARTE_TASKS_STARTTX_OFFSET) +#define NRF91_UARTE0_TASKS_STOPTX (NRF91_UARTE0_BASE + NRF91_UARTE_TASKS_STOPTX_OFFSET) +#define NRF91_UARTE0_TASKS_FLUSHRX (NRF91_UARTE0_BASE + NRF91_UARTE_TASKS_FLUSHRX_OFFSET) +#define NRF91_UARTE0_EVENTS_CTS (NRF91_UARTE0_BASE + NRF91_UARTE_EVENTS_CTS_OFFSET) +#define NRF91_UARTE0_EVENTS_NCTS (NRF91_UARTE0_BASE + NRF91_UARTE_EVENTS_NCTS_OFFSET) +#define NRF91_UARTE0_EVENTS_RXDRDY (NRF91_UARTE0_BASE + NRF91_UARTE_EVENTS_RXDRDY_OFFSET) +#define NRF91_UARTE0_EVENTS_ENDRX (NRF91_UARTE0_BASE + NRF91_UARTE_EVENTS_ENDRX_OFFSET) +#define NRF91_UARTE0_EVENTS_TXDRDY (NRF91_UARTE0_BASE + NRF91_UARTE_EVENTS_TXDRDY_OFFSET) +#define NRF91_UARTE0_EVENTS_ENDTX (NRF91_UARTE0_BASE + NRF91_UARTE_EVENTS_ENDTX_OFFSET) +#define NRF91_UARTE0_EVENTS_ERROR (NRF91_UARTE0_BASE + NRF91_UARTE_EVENTS_ERROR_OFFSET) +#define NRF91_UARTE0_EVENTS_RXTO (NRF91_UARTE0_BASE + NRF91_UARTE_EVENTS_RXTO_OFFSET) +#define NRF91_UARTE0_EVENTS_RXSTARTED (NRF91_UARTE0_BASE + NRF91_UARTE_EVENTS_RXSTARTED_OFFSET) +#define NRF91_UARTE0_EVENTS_TXSTARTED (NRF91_UARTE0_BASE + NRF91_UARTE_EVENTS_TXSTARTED_OFFSET) +#define NRF91_UARTE0_EVENTS_TXSTOPPED (NRF91_UARTE0_BASE + NRF91_UARTE_EVENTS_TXSTOPPED_OFFSET) +#define NRF91_UARTE0_SHORTS (NRF91_UARTE0_BASE + NRF91_UARTE_SHORTS_OFFSET) +#define NRF91_UARTE0_INTEN (NRF91_UARTE0_BASE + NRF91_UARTE_INTEN_OFFSET) +#define NRF91_UARTE0_INTENSET (NRF91_UARTE0_BASE + NRF91_UARTE_INTENSET_OFFSET) +#define NRF91_UARTE0_INTENCLR (NRF91_UARTE0_BASE + NRF91_UARTE_INTENCLR_OFFSET) +#define NRF91_UARTE0_ERRORSRC (NRF91_UARTE0_BASE + NRF91_UARTE_ERRORSRC_OFFSET) +#define NRF91_UARTE0_ENABLE (NRF91_UARTE0_BASE + NRF91_UARTE_ENABLE_OFFSET) +#define NRF91_UARTE0_PSEL_RTS (NRF91_UARTE0_BASE + NRF91_UARTE_PSEL_RTS_OFFSET) +#define NRF91_UARTE0_PSEL_TXD (NRF91_UARTE0_BASE + NRF91_UARTE_PSEL_TXD_OFFSET) +#define NRF91_UARTE0_PSEL_CTS (NRF91_UARTE0_BASE + NRF91_UARTE_PSEL_CTS_OFFSET) +#define NRF91_UARTE0_PSEL_RXD (NRF91_UARTE0_BASE + NRF91_UARTE_PSEL_RXD_OFFSET) +#define NRF91_UARTE0_BAUDRATE (NRF91_UARTE0_BASE + NRF91_UARTE_BAUDRATE_OFFSET) +#define NRF91_UARTE0_RXD_PTR (NRF91_UARTE0_BASE + NRF91_UARTE_RXD_PTR_OFFSET) +#define NRF91_UARTE0_RXD_MAXCNT (NRF91_UARTE0_BASE + NRF91_UARTE_RXD_MAXCNT_OFFSET) +#define NRF91_UARTE0_RXD_AMOUNT (NRF91_UARTE0_BASE + NRF91_UARTE_RXD_AMOUNT_OFFSET) +#define NRF91_UARTE0_TXD_PTR (NRF91_UARTE0_BASE + NRF91_UARTE_TXD_PTR_OFFSET) +#define NRF91_UARTE0_TXD_MAXCNT (NRF91_UARTE0_BASE + NRF91_UARTE_TXD_MAXCNT_OFFSET) +#define NRF91_UARTE0_TXD_AMOUNT (NRF91_UARTE0_BASE + NRF91_UARTE_TXD_AMOUNT_OFFSET) +#define NRF91_UARTE0_CONFIG (NRF91_UARTE0_BASE + NRF91_UARTE_CONFIG_OFFSET) + +#define NRF91_UART0_TASKS_STARTRX (NRF91_UART0_BASE + NRF91_UART_TASKS_STARTRX_OFFSET) +#define NRF91_UART0_TASKS_STOPRX (NRF91_UART0_BASE + NRF91_UART_TASKS_STOPRX_OFFSET) +#define NRF91_UART0_TASKS_STARTTX (NRF91_UART0_BASE + NRF91_UART_TASKS_STARTTX_OFFSET) +#define NRF91_UART0_TASKS_STOPTX (NRF91_UART0_BASE + NRF91_UART_TASKS_STOPTX_OFFSET) +#define NRF91_UART0_TASKS_SUSPEND (NRF91_UART0_BASE + NRF91_UART_TASKS_SUSPEND_OFFSET) +#define NRF91_UART0_EVENTS_CTS (NRF91_UART0_BASE + NRF91_UART_EVENTS_CTS_OFFSET) +#define NRF91_UART0_EVENTS_NCTS (NRF91_UART0_BASE + NRF91_UART_EVENTS_NCTS_OFFSET) +#define NRF91_UART0_EVENTS_RXDRDY (NRF91_UART0_BASE + NRF91_UART_EVENTS_RXDRDY_OFFSET) +#define NRF91_UART0_EVENTS_TXDRDY (NRF91_UART0_BASE + NRF91_UART_EVENTS_TXDRDY_OFFSET) +#define NRF91_UART0_EVENTS_ERROR (NRF91_UART0_BASE + NRF91_UART_EVENTS_ERROR_OFFSET) +#define NRF91_UART0_EVENTS_RXTO (NRF91_UART0_BASE + NRF91_UART_EVENTS_RXTO_OFFSET) +#define NRF91_UART0_SHORTS (NRF91_UART0_BASE + NRF91_UART_SHORTS_OFFSET) +#define NRF91_UART0_INTENSET (NRF91_UART0_BASE + NRF91_UART_INTENSET_OFFSET) +#define NRF91_UART0_INTENCLR (NRF91_UART0_BASE + NRF91_UART_INTENCLR_OFFSET) +#define NRF91_UART0_ERRORSRC (NRF91_UART0_BASE + NRF91_UART_ERRORSRC_OFFSET) +#define NRF91_UART0_ENABLE (NRF91_UART0_BASE + NRF91_UART_ENABLE_OFFSET) +#define NRF91_UART0_PSELRTS (NRF91_UART0_BASE + NRF91_UART_PSELRTS_OFFSET) +#define NRF91_UART0_PSELTXD (NRF91_UART0_BASE + NRF91_UART_PSELTXD_OFFSET) +#define NRF91_UART0_PSELCTS (NRF91_UART0_BASE + NRF91_UART_PSELCTS_OFFSET) +#define NRF91_UART0_PSELRXD (NRF91_UART0_BASE + NRF91_UART_PSELRXD_OFFSET) +#define NRF91_UART0_RXD (NRF91_UART0_BASE + NRF91_UART_RXD_OFFSET) +#define NRF91_UART0_TXD (NRF91_UART0_BASE + NRF91_UART_TXD_OFFSET) +#define NRF91_UART0_BAUDRATE (NRF91_UART0_BASE + NRF91_UART_BAUDRATE_OFFSET) +#define NRF91_UART0_CONFIG (NRF91_UART0_BASE + NRF91_UART_CONFIG_OFFSET) + +#ifdef CONFIG_NRF91_UART1 +# define NRF91_UARTE1_TASKS_STARTRX (NRF91_UARTE1_BASE + NRF91_UARTE_TASKS_STARTRX_OFFSET) +# define NRF91_UARTE1_TASKS_STOPRX (NRF91_UARTE1_BASE + NRF91_UARTE_TASKS_STOPRX_OFFSET) +# define NRF91_UARTE1_TASKS_STARTTX (NRF91_UARTE1_BASE + NRF91_UARTE_TASKS_STARTTX_OFFSET) +# define NRF91_UARTE1_TASKS_STOPTX (NRF91_UARTE1_BASE + NRF91_UARTE_TASKS_STOPTX_OFFSET) +# define NRF91_UARTE1_TASKS_FLUSHRX (NRF91_UARTE1_BASE + NRF91_UARTE_TASKS_FLUSHRX_OFFSET) +# define NRF91_UARTE1_EVENTS_CTS (NRF91_UARTE1_BASE + NRF91_UARTE_EVENTS_CTS_OFFSET) +# define NRF91_UARTE1_EVENTS_NCTS (NRF91_UARTE1_BASE + NRF91_UARTE_EVENTS_NCTS_OFFSET) +# define NRF91_UARTE1_EVENTS_RXDRDY (NRF91_UARTE1_BASE + NRF91_UARTE_EVENTS_RXDRDY_OFFSET) +# define NRF91_UARTE1_EVENTS_ENDRX (NRF91_UARTE1_BASE + NRF91_UARTE_EVENTS_ENDRX_OFFSET) +# define NRF91_UARTE1_EVENTS_TXDRDY (NRF91_UARTE1_BASE + NRF91_UARTE_EVENTS_TXDRDY_OFFSET) +# define NRF91_UARTE1_EVENTS_ENDTX (NRF91_UARTE1_BASE + NRF91_UARTE_EVENTS_ENDTX_OFFSET) +# define NRF91_UARTE1_EVENTS_ERROR (NRF91_UARTE1_BASE + NRF91_UARTE_EVENTS_ERROR_OFFSET) +# define NRF91_UARTE1_EVENTS_RXTO (NRF91_UARTE1_BASE + NRF91_UARTE_EVENTS_RXTO_OFFSET) +# define NRF91_UARTE1_EVENTS_RXSTARTED (NRF91_UARTE1_BASE + NRF91_UARTE_EVENTS_RXSTARTED_OFFSET) +# define NRF91_UARTE1_EVENTS_TXSTARTED (NRF91_UARTE1_BASE + NRF91_UARTE_EVENTS_TXSTARTED_OFFSET) +# define NRF91_UARTE1_EVENTS_TXSTOPPED (NRF91_UARTE1_BASE + NRF91_UARTE_EVENTS_TXSTOPPED_OFFSET) +# define NRF91_UARTE1_SHORTS (NRF91_UARTE1_BASE + NRF91_UARTE_SHORTS_OFFSET) +# define NRF91_UARTE1_INTEN (NRF91_UARTE1_BASE + NRF91_UARTE_INTEN_OFFSET) +# define NRF91_UARTE1_INTENSET (NRF91_UARTE1_BASE + NRF91_UARTE_INTENSET_OFFSET) +# define NRF91_UARTE1_INTENCLR (NRF91_UARTE1_BASE + NRF91_UARTE_INTENCLR_OFFSET) +# define NRF91_UARTE1_ERRORSRC (NRF91_UARTE1_BASE + NRF91_UARTE_ERRORSRC_OFFSET) +# define NRF91_UARTE1_ENABLE (NRF91_UARTE1_BASE + NRF91_UARTE_ENABLE_OFFSET) +# define NRF91_UARTE1_PSEL_RTS (NRF91_UARTE1_BASE + NRF91_UARTE_PSEL_RTS_OFFSET) +# define NRF91_UARTE1_PSEL_TXD (NRF91_UARTE1_BASE + NRF91_UARTE_PSEL_TXD_OFFSET) +# define NRF91_UARTE1_PSEL_CTS (NRF91_UARTE1_BASE + NRF91_UARTE_PSEL_CTS_OFFSET) +# define NRF91_UARTE1_PSEL_RXD (NRF91_UARTE1_BASE + NRF91_UARTE_PSEL_RXD_OFFSET) +# define NRF91_UARTE1_BAUDRATE (NRF91_UARTE1_BASE + NRF91_UARTE_BAUDRATE_OFFSET) +# define NRF91_UARTE1_RXD_PTR (NRF91_UARTE1_BASE + NRF91_UARTE_RXD_PTR_OFFSET) +# define NRF91_UARTE1_RXD_MAXCNT (NRF91_UARTE1_BASE + NRF91_UARTE_RXD_MAXCNT_OFFSET) +# define NRF91_UARTE1_RXD_AMOUNT (NRF91_UARTE1_BASE + NRF91_UARTE_RXD_AMOUNT_OFFSET) +# define NRF91_UARTE1_TXD_PTR (NRF91_UARTE1_BASE + NRF91_UARTE_TXD_PTR_OFFSET) +# define NRF91_UARTE1_TXD_MAXCNT (NRF91_UARTE1_BASE + NRF91_UARTE_TXD_MAXCNT_OFFSET) +# define NRF91_UARTE1_TXD_AMOUNT (NRF91_UARTE1_BASE + NRF91_UARTE_TXD_AMOUNT_OFFSET) +# define NRF91_UARTE1_CONFIG (NRF91_UARTE1_BASE + NRF91_UARTE_CONFIG_OFFSET) + +# define NRF91_UART1_TASKS_STARTRX (NRF91_UART1_BASE + NRF91_UART_TASKS_STARTRX_OFFSET) +# define NRF91_UART1_TASKS_STOPRX (NRF91_UART1_BASE + NRF91_UART_TASKS_STOPRX_OFFSET) +# define NRF91_UART1_TASKS_STARTTX (NRF91_UART1_BASE + NRF91_UART_TASKS_STARTTX_OFFSET) +# define NRF91_UART1_TASKS_STOPTX (NRF91_UART1_BASE + NRF91_UART_TASKS_STOPTX_OFFSET) +# define NRF91_UART1_TASKS_SUSPEND (NRF91_UART1_BASE + NRF91_UART_TASKS_SUSPEND_OFFSET) +# define NRF91_UART1_EVENTS_CTS (NRF91_UART1_BASE + NRF91_UART_EVENTS_CTS_OFFSET) +# define NRF91_UART1_EVENTS_NCTS (NRF91_UART1_BASE + NRF91_UART_EVENTS_NCTS_OFFSET) +# define NRF91_UART1_EVENTS_RXDRDY (NRF91_UART1_BASE + NRF91_UART_EVENTS_RXDRDY_OFFSET) +# define NRF91_UART1_EVENTS_TXDRDY (NRF91_UART1_BASE + NRF91_UART_EVENTS_TXDRDY_OFFSET) +# define NRF91_UART1_EVENTS_ERROR (NRF91_UART1_BASE + NRF91_UART_EVENTS_ERROR_OFFSET) +# define NRF91_UART1_EVENTS_RXTO (NRF91_UART1_BASE + NRF91_UART_EVENTS_RXTO_OFFSET) +# define NRF91_UART1_SHORTS (NRF91_UART1_BASE + NRF91_UART_SHORTS_OFFSET) +# define NRF91_UART1_INTENSET (NRF91_UART1_BASE + NRF91_UART_INTENSET_OFFSET) +# define NRF91_UART1_INTENCLR (NRF91_UART1_BASE + NRF91_UART_INTENCLR_OFFSET) +# define NRF91_UART1_ERRORSRC (NRF91_UART1_BASE + NRF91_UART_ERRORSRC_OFFSET) +# define NRF91_UART1_ENABLE (NRF91_UART1_BASE + NRF91_UART_ENABLE_OFFSET) +# define NRF91_UART1_PSELRTS (NRF91_UART1_BASE + NRF91_UART_PSELRTS_OFFSET) +# define NRF91_UART1_PSELTXD (NRF91_UART1_BASE + NRF91_UART_PSELTXD_OFFSET) +# define NRF91_UART1_PSELCTS (NRF91_UART1_BASE + NRF91_UART_PSELCTS_OFFSET) +# define NRF91_UART1_PSELRXD (NRF91_UART1_BASE + NRF91_UART_PSELRXD_OFFSET) +# define NRF91_UART1_RXD (NRF91_UART1_BASE + NRF91_UART_RXD_OFFSET) +# define NRF91_UART1_TXD (NRF91_UART1_BASE + NRF91_UART_TXD_OFFSET) +# define NRF91_UART1_BAUDRATE (NRF91_UART1_BASE + NRF91_UART_BAUDRATE_OFFSET) +# define NRF91_UART1_CONFIG (NRF91_UART1_BASE + NRF91_UART_CONFIG_OFFSET) +#endif + +/* UART Register Bitfield Definitions **************************************/ + +/* PSELRTS Register */ + +#define UART_PSELRTS_PIN_SHIFT (0) /* Bits 0-4: Pin number*/ +#define UART_PSELRTS_PIN_MASK (0x1f << UART_PSELRTS_PIN_SHIFT) +#define UART_PSELRTS_PORT_SHIFT (5) /* Bit 5: Port number */ +#define UART_PSELRTS_PORT_MASK (0x1 << UART_PSELRTS_PORT_SHIFT) +#define UART_PSELRTS_CONNECT (1 << 31) /* Bit 31: Connection */ +#define UART_PSELRTS_RESET (0xffffffff) + +/* PSELTXD Register */ + +#define UART_PSELTXD_PIN_SHIFT (0) /* Bits 0-4: Pin number*/ +#define UART_PSELTXD_PIN_MASK (0x1f << UART_PSELTXD_PIN_SHIFT) +#define UART_PSELTXD_PORT_SHIFT (5) /* Bit 5: Port number */ +#define UART_PSELTXD_PORT_MASK (0x1 << UART_PSELTXD_PORT_SHIFT) +#define UART_PSELTXD_CONNECT (1 << 31) /* Bit 31: Connection */ +#define UART_PSELTXD_RESET (0xffffffff) + +/* PSELCTS Register */ + +#define UART_PSELCTS_PIN_SHIFT (0) /* Bits 0-4: Pin number*/ +#define UART_PSELCTS_PIN_MASK (0x1f << UART_PSELCTS_PIN_SHIFT) +#define UART_PSELCTS_PORT_SHIFT (5) /* Bit 5: Port number */ +#define UART_PSELCTS_PORT_MASK (0x1 << UART_PSELCTS_PORT_SHIFT) +#define UART_PSELCTS_CONNECT (1 << 31) /* Bit 31: Connection */ +#define UART_PSELCTS_RESET (0xffffffff) + +/* PSELRXD Register */ + +#define UART_PSELRXD_PIN_SHIFT (0) /* Bits 0-4: Pin number*/ +#define UART_PSELRXD_PIN_MASK (0x1f << UART_PSELRXD_PIN_SHIFT) +#define UART_PSELRXD_PORT_SHIFT (5) /* Bit 5: Port number */ +#define UART_PSELRXD_PORT_MASK (0x1 << UART_PSELRXD_PORT_SHIFT) +#define UART_PSELRXD_CONNECT (1 << 31) /* Bit 31: Connection */ +#define UART_PSELRXD_RESET (0xffffffff) + +/* ENABLE Register */ + +#define NRF91_UART_ENABLE_DISABLE (0) +#define NRF91_UART_ENABLE_ENABLE (8) + +/* INTEN/INTENSET/INTENCLR Register */ + +#define UART_INT_CTS (1 << 0) +#define UART_INT_NCTS (1 << 1) +#define UART_INT_RXDRDY (1 << 2) +#define UART_INT_ENDRX (1 << 4) +#define UART_INT_TXDRDY (1 << 7) +#define UART_INT_ENDTX (1 << 8) +#define UART_INT_ERROR (1 << 9) +#define UART_INT_RXTO (1 << 17) +#define UART_INT_RXSTARTED (1 << 19) +#define UART_INT_TXSTARTED (1 << 20) +#define UART_INT_TXSTOPPED (1 << 22) + +/* BAUDRATE Register */ + +#define UART_BAUDRATE_1200 (0x0004f000) +#define UART_BAUDRATE_2400 (0x0009d000) +#define UART_BAUDRATE_4800 (0x0013b000) +#define UART_BAUDRATE_9600 (0x00275000) +#define UART_BAUDRATE_14400 (0x003af000) +#define UART_BAUDRATE_19200 (0x004ea000) +#define UART_BAUDRATE_28800 (0x0075c000) +#define UART_BAUDRATE_31250 (0x00800000) +#define UART_BAUDRATE_38400 (0x009d0000) +#define UART_BAUDRATE_56000 (0x00e50000) +#define UART_BAUDRATE_57600 (0x00eb0000) +#define UART_BAUDRATE_76000 (0x013a9000) +#define UART_BAUDRATE_115200 (0x01d60000) +#define UART_BAUDRATE_230400 (0x03b00000) +#define UART_BAUDRATE_250000 (0x04000000) +#define UART_BAUDRATE_460800 (0x07400000) +#define UART_BAUDRATE_921600 (0x0f000000) +#define UART_BAUDRATE_1000000 (0x10000000) + +/* CONFIG Register */ + +#define UART_CONFIG_HWFC (1 << 0) /* Bit 0: Hardware flow control */ +#define UART_CONFIG_PARITY_SHIFT (1) /* Bits 1-3: Parity */ +#define UART_CONFIG_PARITY (7 << UART_CONFIG_PARITY_SHIFT) +#define UART_CONFIG_STOP (1 << 4) /* Bit 4: Stop bits */ + +#endif /* __ARCH_ARM_SRC_NRF91_HARDWARE_NRF91!_UARTE_H */ diff --git a/arch/arm/src/nrf91/hardware/nrf91_uicr.h b/arch/arm/src/nrf91/hardware/nrf91_uicr.h new file mode 100644 index 0000000000..66b7b011fe --- /dev/null +++ b/arch/arm/src/nrf91/hardware/nrf91_uicr.h @@ -0,0 +1,63 @@ +/*************************************************************************** + * arch/arm/src/nrf91/hardware/nrf91_uicr.h + * + * 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. + * + ***************************************************************************/ + +#ifndef __ARCH_ARM_SRC_NRF91_HARDWARE_NRF91_UICR_H +#define __ARCH_ARM_SRC_NRF91_HARDWARE_NRF91_UICR_H + +/*************************************************************************** + * Included Files + ***************************************************************************/ + +#include +#include "hardware/nrf91_memorymap.h" + +/*************************************************************************** + * Pre-processor Definitions + ***************************************************************************/ + +/* UICR Register Offsets ***************************************************/ + +#define NRF91_UICR_APPROTECT_OFFSET 0x000 /* Access port protection */ +#define NRF91_UICR_XOSC32M_OFFSET 0x014 /* Oscillator control */ +#define NRF91_UICR_HFXOSRC_OFFSET 0x01C /* HFXO clock source selection */ +#define NRF91_UICR_HFXOCNT_OFFSET 0x020 /* HFXO startup counter */ +#define NRF91_UICR_APPNVMCPOFGUARD_OFFSET 0x024 /* Enable blocking NVM WRITE and aborting NVM ERASE for Application NVM in POFWARN condition */ +#define NRF91_UICR_SECUREAPPROTECT_OFFSET 0x02c /* Secure access port protection */ +#define NRF91_UICR_ERASEPROTECT_OFFSET 0x030 /* Erase protection */ +#define NRF91_UICR_OTP_OFFSET 0x100 /* One time programmable memory */ +#define NRF91_UICR_KEYSLOTCONFIGDEST_OFFSET 0x400 /* Key slot destination address */ +#define NRF91_UICR_KEYSLOTCONFIGPERM_OFFSET 0x404 /* Permissions for the key slot */ +#define NRF91_UICR_KEYSLOTKEYVALUE_OFFSET 0x800 /* Define bits [31+o*32:0+o*32] of value assigned to KMU key slot. */ + +/* UICR Register Addresses *************************************************/ + +#define NRF91_UICR_APPROTECT (NRF91_UICR_BASE + NRF91_UICR_APPROTECT_OFFSET) +#define NRF91_UICR_XOSC32M (NRF91_UICR_BASE + NRF91_UICR_XOSC32M_OFFSET) +#define NRF91_UICR_HFXOSRC (NRF91_UICR_BASE + NRF91_UICR_HFXOSRC_OFFSET) +#define NRF91_UICR_HFXOCNT (NRF91_UICR_BASE + NRF91_UICR_HFXOCNT_OFFSET) +#define NRF91_UICR_APPNVMCPOFGUARD (NRF91_UICR_BASE + NRF91_UICR_APPNVMCPOFGUARD_OFFSET) +#define NRF91_UICR_SECUREAPPROTECT (NRF91_UICR_BASE + NRF91_UICR_SECUREAPPROTECT_OFFSET) +#define NRF91_UICR_ERASEPROTECT (NRF91_UICR_BASE + NRF91_UICR_ERASEPROTECT_OFFSET) +#define NRF91_UICR_OTP (NRF91_UICR_BASE + NRF91_UICR_OTP_OFFSET) +#define NRF91_UICR_KEYSLOTCONFIGDEST (NRF91_UICR_BASE + NRF91_UICR_KEYSLOTCONFIGDEST_OFFSET) +#define NRF91_UICR_KEYSLOTCONFIGPERM (NRF91_UICR_BASE + NRF91_UICR_KEYSLOTCONFIGPERM_OFFSET) +#define NRF91_UICR_KEYSLOTKEYVALUE (NRF91_UICR_BASE + NRF91_UICR_KEYSLOTKEYVALUE_OFFSET) + +#endif /* __ARCH_ARM_SRC_NRF91_HARDWARE_NRF91_UICR_H */ diff --git a/arch/arm/src/nrf91/hardware/nrf91_utils.h b/arch/arm/src/nrf91/hardware/nrf91_utils.h new file mode 100644 index 0000000000..881b9201a3 --- /dev/null +++ b/arch/arm/src/nrf91/hardware/nrf91_utils.h @@ -0,0 +1,109 @@ +/**************************************************************************** + * arch/arm/src/nrf91/hardware/nrf91_utils.h + * + * 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. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_NRF91_HARDWARE_NRF91_UTILS_H +#define __ARCH_ARM_SRC_NRF91_HARDWARE_NRF91_UTILS_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Public Function Prototypes / Inline Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nrf91_clrpend + * + * Description: + * Clear a pending interrupt at the NVIC. This does not seem to be + * required for most interrupts. + * + ****************************************************************************/ + +void nrf91_clrpend(int irq); + +/**************************************************************************** + * Name: nrf91_easydma_valid + * + * Description: + * Validate if easyDMA transfer is possible. + * + ****************************************************************************/ + +bool nrf91_easydma_valid(uint32_t addr); + +/**************************************************************************** + * Name: nrf91_task_trigger + * + * Description: + * trigger the special task which is passed from task parameter + * + ****************************************************************************/ + +static inline void nrf91_task_trigger(uint32_t task) +{ + putreg32(1, task); +} + +/**************************************************************************** + * Name: nrf91_event_clear + * + * Description: + * clear the Event + * + ****************************************************************************/ + +static inline void nrf91_event_clear(uint32_t event) +{ + putreg32(0, event); +} + +/**************************************************************************** + * Name: nrf91_interrupt_enable + * + * Description: + * Enable the bitfield interrupt + * + ****************************************************************************/ + +static inline void nrf91_interrupt_enable(uint32_t reg_intenset, + uint32_t bitfield) +{ + putreg32(bitfield, reg_intenset); +} + +/**************************************************************************** + * Name: nrf91_interrupt_disable + * + * Description: + * Disable the bitfield interrupt + * + ****************************************************************************/ + +static inline void nrf91_interrupt_disable(uint32_t reg_intenclr, + uint32_t bitfield) +{ + putreg32(bitfield, reg_intenclr); +} + +#endif /* __ARCH_ARM_SRC_NRF91_HARDWARE_NRF91_UTILS_H */ diff --git a/arch/arm/src/nrf91/nrf91_allocateheap.c b/arch/arm/src/nrf91/nrf91_allocateheap.c new file mode 100644 index 0000000000..37ecfaa7ac --- /dev/null +++ b/arch/arm/src/nrf91/nrf91_allocateheap.c @@ -0,0 +1,191 @@ +/**************************************************************************** + * arch/arm/src/nrf91/nrf91_allocateheap.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 "hardware/nrf91_memorymap.h" + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ + +/* .bss and .data is always positioned in internal SRAM. The remaining SRAM + * after the static .bss, .data, and IDLE stack allocations are always added + * to the heap. + */ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* _sbss is the start of the BSS region (see the linker script) _ebss is the + * end of the BSS region (see the linker script). The idle task stack starts + * at the end of BSS and is of size CONFIG_IDLETHREAD_STACKSIZE. The IDLE + * thread is the thread that the system boots on and, eventually, becomes the + * idle, do nothing task that runs only when there is nothing else to run. + * The heap continues from there until the configured end of memory. + * g_idle_topstack is the beginning of this heap region (not necessarily + * aligned). + */ + +const uintptr_t g_idle_topstack = (uintptr_t)_ebss + + CONFIG_IDLETHREAD_STACKSIZE; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_allocate_heap/up_allocate_kheap + * + * Description: + * This function will be called to dynamically set aside the heap region. + * + * - For the normal "flat" build, this function returns the size of the + * single heap. + * - For the protected build (CONFIG_BUILD_PROTECTED=y) with both kernel- + * and user-space heaps (CONFIG_MM_KERNEL_HEAP=y), this function + * provides the size of the unprotected, user-space heap. + * - For the kernel build (CONFIG_BUILD_KERNEL=y), this function provides + * the size of the protected, kernel-space heap. + * + * If a protected kernel-space heap is provided, the kernel heap must be + * allocated by an analogous up_allocate_kheap(). A custom version of this + * file is needed if memory protection of the kernel heap is required. + * + * The following memory map is assumed for the flat build: + * + * .data region. Size determined at link time. + * .bss region Size determined at link time. + * IDLE thread stack. Size determined by CONFIG_IDLETHREAD_STACKSIZE. + * Heap. Extends to the end of SRAM. + * + * The following memory map is assumed for the kernel build: + * + * Kernel .data region. Size determined at link time. + * Kernel .bss region Size determined at link time. + * Kernel IDLE thread stack. Size determined by + * CONFIG_IDLETHREAD_STACKSIZE. + * Padding for alignment + * User .data region. Size determined at link time. + * User .bss region Size determined at link time. + * Kernel heap. Size determined by CONFIG_MM_KERNEL_HEAPSIZE. + * User heap. Extends to the end of SRAM. + * + ****************************************************************************/ + +#ifdef CONFIG_BUILD_KERNEL +void up_allocate_kheap(void **heap_start, size_t *heap_size) +#else +void up_allocate_heap(void **heap_start, size_t *heap_size) +#endif +{ +#if defined(CONFIG_BUILD_PROTECTED) && defined(CONFIG_MM_KERNEL_HEAP) + /* Get the unaligned size and position of the user-space heap. + * This heap begins after the user-space .bss section at an offset + * of CONFIG_MM_KERNEL_HEAPSIZE (subject to alignment). + */ + + uintptr_t ubase = (uintptr_t)USERSPACE->us_bssend + + CONFIG_MM_KERNEL_HEAPSIZE; + size_t usize = CONFIG_RAM_END - ubase; + + DEBUGASSERT(ubase < (uintptr_t)CONFIG_RAM_END); + + /* Return the user-space heap settings */ + + board_autoled_on(LED_HEAPALLOCATE); + *heap_start = (void *)ubase; + *heap_size = usize; +#else + + /* Return the heap settings */ + + board_autoled_on(LED_HEAPALLOCATE); + *heap_start = (void *)g_idle_topstack; + *heap_size = CONFIG_RAM_END - g_idle_topstack; +#endif +} + +/**************************************************************************** + * Name: up_allocate_kheap + * + * Description: + * For the kernel build (CONFIG_BUILD_PROTECTED/KERNEL=y) with both kernel- + * and user-space heaps (CONFIG_MM_KERNEL_HEAP=y), this function allocates + * the kernel-space heap. A custom version of this function is needed if + * memory protection of the kernel heap is required. + * + ****************************************************************************/ + +#if defined(CONFIG_BUILD_PROTECTED) && defined(CONFIG_MM_KERNEL_HEAP) +void up_allocate_kheap(void **heap_start, size_t *heap_size) +{ + /* Get the unaligned size and position of the user-space heap. + * This heap begins after the user-space .bss section at an offset + * of CONFIG_MM_KERNEL_HEAPSIZE (subject to alignment). + */ + + uintptr_t ubase = (uintptr_t)USERSPACE->us_bssend + + CONFIG_MM_KERNEL_HEAPSIZE; + DEBUGASSERT(ubase < (uintptr_t)CONFIG_RAM_END); + + /* Return the kernel heap settings (i.e., the part of the heap region + * that was not dedicated to the user heap). + */ + + *heap_start = (void *)USERSPACE->us_bssend; + *heap_size = ubase - (uintptr_t)USERSPACE->us_bssend; +} +#endif + +/**************************************************************************** + * Name: arm_addregion + * + * Description: + * Memory may be added in non-contiguous chunks. Additional chunks are + * added by calling this function. + * + ****************************************************************************/ + +#if CONFIG_MM_REGIONS > 1 +void arm_addregion(void) +{ +} +#endif /* CONFIG_MM_REGIONS > 1 */ diff --git a/arch/arm/src/nrf91/nrf91_clockconfig.c b/arch/arm/src/nrf91/nrf91_clockconfig.c new file mode 100644 index 0000000000..f104ae8d36 --- /dev/null +++ b/arch/arm/src/nrf91/nrf91_clockconfig.c @@ -0,0 +1,103 @@ +/**************************************************************************** + * arch/arm/src/nrf91/nrf91_clockconfig.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 "arm_internal.h" +#include "nrf91_clockconfig.h" +#include "hardware/nrf91_clock.h" +#include "hardware/nrf91_power.h" +#include "hardware/nrf91_gpio.h" + +#ifdef CONFIG_NRF91_APPCORE +# include "nrf91_oscconfig.h" +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nrf91_clockconfig + * + * Description: + * Called to initialize the NRF91xxx. This does whatever setup is needed + * to put the MCU in a usable state. This includes the initialization of + * clocking using the settings in board.h. This function also performs + * other low-level chip as necessary. + * + ****************************************************************************/ + +void nrf91_clockconfig(void) +{ +#ifdef CONFIG_NRF91_HFCLK_XTAL + /* Initialize HFCLK crystal oscillator */ + + putreg32(0x0, NRF91_CLOCK_EVENTS_HFCLKSTARTED); + putreg32(0x1, NRF91_CLOCK_TASKS_HFCLKSTART); + + while (!getreg32(NRF91_CLOCK_EVENTS_HFCLKSTARTED)) + { + /* wait for external oscillator to start */ + } +#endif + +#ifdef CONFIG_NRF91_USE_LFCLK + /* Initialize LFCLK */ + +#if defined(CONFIG_NRF91_LFCLK_XTAL) + putreg32(CLOCK_LFCLKSRC_SRC_LFXO, NRF91_CLOCK_LFCLKSRC); +#elif defined(CONFIG_NRF91_LFCLK_SYNTH) + putreg32(CLOCK_LFCLKSRC_SRC_LFSYNT, NRF91_CLOCK_LFCLKSRC); +#else + putreg32(CLOCK_LFCLKSRC_SRC_LFRC, NRF91_CLOCK_LFCLKSRC); +#endif + + /* Trigger LFCLK start */ + + putreg32(0x0, NRF91_CLOCK_EVENTS_LFCLKSTARTED); + putreg32(0x1, NRF91_CLOCK_TASKS_LFCLKSTART); + + /* NOTE: Oscillator must be configured on the app core */ + + while (!getreg32(NRF91_CLOCK_EVENTS_LFCLKSTARTED)) + { + /* Wait for LFCLK to be running */ + } + +#if defined(CONFIG_NRF91_LFCLK_RC) + /* TODO: calibrate LFCLK RC oscillator */ +#endif +#endif +} diff --git a/arch/arm/src/nrf91/nrf91_clockconfig.h b/arch/arm/src/nrf91/nrf91_clockconfig.h new file mode 100644 index 0000000000..803d9dbb56 --- /dev/null +++ b/arch/arm/src/nrf91/nrf91_clockconfig.h @@ -0,0 +1,79 @@ +/**************************************************************************** + * arch/arm/src/nrf91/nrf91_clockconfig.h + * + * 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. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_NRF91_NRF91_CLOCKCONFIG_H +#define __ARCH_ARM_SRC_NRF91_NRF91_CLOCKCONFIG_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Frequencies of internal clocks */ + +#define NRF91_SYSTEM_CLOCK 64000000 /* Default System clock value */ +#define NRF91_RTC_CLOCK 32768 /* RTC oscillator 32 kHz output + * (32k_clk) + */ + +#ifndef __ASSEMBLY__ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: nrf91_clockconfig + * + * Description: + * Called to initialize the NRF91xxx. This does whatever setup is needed + * to put the MCU in a usable state. This includes the initialization of + * clocking using the settings in board.h. This function also performs + * other low-level chip as necessary. + * + ****************************************************************************/ + +void nrf91_clockconfig(void); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_SRC_NRF91_NRF91_CLOCKCONFIG_H */ diff --git a/arch/arm/src/nrf91/nrf91_config.h b/arch/arm/src/nrf91/nrf91_config.h new file mode 100644 index 0000000000..397a071a9c --- /dev/null +++ b/arch/arm/src/nrf91/nrf91_config.h @@ -0,0 +1,83 @@ +/**************************************************************************** + * arch/arm/src/nrf91/nrf91_config.h + * + * 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. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_NRF91_NRF91_CONFIG_H +#define __ARCH_ARM_SRC_NRF91_NRF91_CONFIG_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include "chip.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ + +/* Make sure that no unsupported UART, I2C master, or SPI master peripherals + * are enabled. + */ + +/* Map logical UART names (Just for simplicity of naming) */ + +#undef HAVE_UART0 +#undef HAVE_UART1 + +#ifdef CONFIG_NRF91_UART0 +# define HAVE_UART0 1 +#endif + +#ifdef CONFIG_NRF91_UART1 +# define HAVE_UART1 1 +#endif + +/* Check if we have a UART device */ + +#undef CONFIG_NRF91_HAVE_UART +#undef HAVE_UART_DEVICE + +#if defined(HAVE_UART0) +# define HAVE_UART_DEVICE 1 +#endif + +#if defined(HAVE_UART1) +# define HAVE_UART_DEVICE 1 +#endif + +/* Is there a serial console? There should be at most one defined. */ + +#undef HAVE_UART_CONSOLE + +#if defined(CONFIG_UART0_SERIAL_CONSOLE) && defined(HAVE_UART0) +# undef CONFIG_UART1_SERIAL_CONSOLE +# define HAVE_UART_CONSOLE 1 +#endif + +#if defined(CONFIG_UART1_SERIAL_CONSOLE) && defined(HAVE_UART1) +# undef CONFIG_UART0_SERIAL_CONSOLE +# define HAVE_UART_CONSOLE 1 +#endif + +#endif /* __ARCH_ARM_SRC_NRF91_NRF91_CONFIG_H */ diff --git a/arch/arm/src/nrf91/nrf91_gpio.c b/arch/arm/src/nrf91/nrf91_gpio.c new file mode 100644 index 0000000000..56c222b50a --- /dev/null +++ b/arch/arm/src/nrf91/nrf91_gpio.c @@ -0,0 +1,428 @@ +/**************************************************************************** + * arch/arm/src/nrf91/nrf91_gpio.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 "arm_internal.h" +#include "hardware/nrf91_gpio.h" +#include "nrf91_gpio.h" + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nrf91_gpio_regget + * + * Description: + * Get a register address for given GPIO port and register offset + * + ****************************************************************************/ + +static inline uint32_t nrf91_gpio_regget(int port, uint32_t offset) +{ + uint32_t base = 0; + + /* Get base address for port */ + + if (port == 0) + { + base = NRF91_GPIO_P0_BASE; + } + else + { + ASSERT(0); + } + + return (base + offset); +} + +/**************************************************************************** + * Name: nrf91_gpio_input + * + * Description: + * Configure a GPIO input pin based on bit-encoded description of the pin. + * + ****************************************************************************/ + +static inline void nrf91_gpio_input(unsigned int port, unsigned int pin) +{ + uint32_t offset; + + offset = nrf91_gpio_regget(port, NRF91_GPIO_DIRCLR_OFFSET); + + /* Configure the pin as an input */ + + putreg32(1U << pin, offset); + + /* Enable input buffer */ + + offset = nrf91_gpio_regget(port, NRF91_GPIO_PIN_CNF_OFFSET(pin)); + modifyreg32(offset, GPIO_CNF_INPUT, 0); +} + +/**************************************************************************** + * Name: nrf91_gpio_output + * + * Description: + * Configure a GPIO output pin based on bit-encoded description of the pin. + * + ****************************************************************************/ + +static inline void nrf91_gpio_output(nrf91_pinset_t cfgset, + unsigned int port, unsigned int pin) +{ + uint32_t offset; + + /* Disable input buffer */ + + offset = nrf91_gpio_regget(port, NRF91_GPIO_PIN_CNF_OFFSET(pin)); + modifyreg32(offset, 0, GPIO_CNF_INPUT); + + offset = nrf91_gpio_regget(port, NRF91_GPIO_DIRSET_OFFSET); + + nrf91_gpio_write(cfgset, ((cfgset & GPIO_VALUE) != GPIO_VALUE_ZERO)); + + /* Configure the pin as an output */ + + putreg32(1U << pin, offset); +} + +/**************************************************************************** + * Name: nrf91_gpio_mode + * + * Description: + * Configure a GPIO mode based on bit-encoded description of the pin. + * + ****************************************************************************/ + +static inline void nrf91_gpio_mode(nrf91_pinset_t cfgset, + unsigned int port, unsigned int pin) +{ + uint32_t mode; + uint32_t regval; + uint32_t offset; + + offset = nrf91_gpio_regget(port, NRF91_GPIO_PIN_CNF_OFFSET(pin)); + + mode = cfgset & GPIO_MODE_MASK; + + regval = getreg32(offset); + regval &= ~GPIO_CNF_PULL_MASK; + + if (mode == GPIO_PULLUP) + { + regval |= GPIO_CNF_PULL_UP; + } + else if (mode == GPIO_PULLDOWN) + { + regval |= GPIO_CNF_PULL_DOWN; + } + + putreg32(regval, offset); +} + +/**************************************************************************** + * Name: nrf91_gpio_sense + * + * Description: + * Set SENSE configuration for an input pin + * + ****************************************************************************/ + +static inline void nrf91_gpio_sense(nrf91_pinset_t cfgset, + unsigned int port, unsigned int pin) +{ + uint32_t mode; + uint32_t regval; + uint32_t offset; + + mode = cfgset & GPIO_SENSE_MASK; + + offset = nrf91_gpio_regget(port, NRF91_GPIO_PIN_CNF_OFFSET(pin)); + regval = getreg32(offset); + + regval &= ~GPIO_CNF_SENSE_MASK; + + if (mode == GPIO_SENSE_HIGH) + { + regval |= GPIO_CNF_SENSE_HIGH; + } + else if (mode == GPIO_SENSE_LOW) + { + regval |= GPIO_CNF_SENSE_LOW; + } + + putreg32(regval, offset); +} + +/**************************************************************************** + * Name: nrf91_gpio_drive + * + * Description: + * Set DRIVE configuration for a pin + * + ****************************************************************************/ + +static inline void nrf91_gpio_drive(nrf91_pinset_t cfgset, + unsigned int port, unsigned int pin) +{ + uint32_t drive; + uint32_t regval; + uint32_t offset; + + drive = cfgset & GPIO_DRIVE_MASK; + + offset = nrf91_gpio_regget(port, NRF91_GPIO_PIN_CNF_OFFSET(pin)); + regval = getreg32(offset); + + regval &= ~GPIO_CNF_DRIVE_MASK; + + switch (drive) + { + case GPIO_DRIVE_S0S1: + regval |= GPIO_CNF_DRIVE_S0S1; + break; + case GPIO_DRIVE_S0H1: + regval |= GPIO_CNF_DRIVE_S0H1; + break; + case GPIO_DRIVE_S0D1: + regval |= GPIO_CNF_DRIVE_S0D1; + break; + case GPIO_DRIVE_H0D1: + regval |= GPIO_CNF_DRIVE_H0D1; + break; + case GPIO_DRIVE_H0H1: + regval |= GPIO_CNF_DRIVE_H0H1; + break; + case GPIO_DRIVE_H0S1: + regval |= GPIO_CNF_DRIVE_H0S1; + break; + case GPIO_DRIVE_D0H1: + regval |= GPIO_CNF_DRIVE_D0H1; + break; + case GPIO_DRIVE_D0S1: + regval |= GPIO_CNF_DRIVE_D0S1; + break; + } + + putreg32(regval, offset); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nrf91_gpio_config + * + * Description: + * Configure a GPIO pin based on bit-encoded description of the pin. + * + ****************************************************************************/ + +int nrf91_gpio_config(nrf91_pinset_t cfgset) +{ + unsigned int port = 0; + unsigned int pin; + irqstate_t flags; + int ret = OK; + + /* Verify that this hardware supports the select GPIO port */ + + port = (cfgset & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT; + + if (port < NRF91_GPIO_NPORTS) + { + /* Get the pin number and select the port configuration register for + * that pin. + */ + + pin = GPIO_PIN_DECODE(cfgset); + + flags = spin_lock_irqsave(NULL); + + /* First, configure the port as a generic input so that we have a + * known starting point and consistent behavior during the re- + * configuration. + */ + + nrf91_gpio_input(port, pin); + + /* Set the mode bits */ + + nrf91_gpio_mode(cfgset, port, pin); + + /* Set the drive bits (needed also for input pins + * for some peripherals). + */ + + nrf91_gpio_drive(cfgset, port, pin); + + /* Handle according to pin function */ + + switch (cfgset & GPIO_FUNC_MASK) + { + case GPIO_INPUT: /* GPIO input pin */ + nrf91_gpio_sense(cfgset, port, pin); + break; + + case GPIO_OUTPUT: /* GPIO outpout pin */ + nrf91_gpio_output(cfgset, port, pin); + break; + + default: + ret = -EINVAL; + } + + spin_unlock_irqrestore(NULL, flags); + } + else + { + ret = -EINVAL; + } + + return ret; +} + +/**************************************************************************** + * Name: nrf91_gpio_unconfig + * + * Description: + * Unconfigure a GPIO pin based on bit-encoded description of the pin. + * + ****************************************************************************/ + +int nrf91_gpio_unconfig(nrf91_pinset_t cfgset) +{ + unsigned int pin; + unsigned int port = 0; + uint32_t offset; + + /* Get port and pin number */ + + pin = GPIO_PIN_DECODE(cfgset); + port = GPIO_PORT_DECODE(cfgset); + + /* Get address offset */ + + offset = nrf91_gpio_regget(port, NRF91_GPIO_PIN_CNF_OFFSET(pin)); + + /* Configure as input and disconnect input buffer */ + + putreg32(GPIO_CNF_INPUT, offset); + + return OK; +} + +/**************************************************************************** + * Name: nrf91_gpio_write + * + * Description: + * Write one or zero to the selected GPIO pin + * + ****************************************************************************/ + +void nrf91_gpio_write(nrf91_pinset_t pinset, bool value) +{ + unsigned int pin; + unsigned int port = 0; + uint32_t offset; + + /* Get port and pin number */ + + pin = GPIO_PIN_DECODE(pinset); + port = GPIO_PORT_DECODE(pinset); + + /* Get register address */ + + if (value) + { + offset = nrf91_gpio_regget(port, NRF91_GPIO_OUTSET_OFFSET); + } + else + { + offset = nrf91_gpio_regget(port, NRF91_GPIO_OUTCLR_OFFSET); + } + + /* Put register value */ + + putreg32(1 << pin, offset); +} + +/**************************************************************************** + * Name: nrf91_gpio_read + * + * Description: + * Read one or zero from the selected GPIO pin + * + ****************************************************************************/ + +bool nrf91_gpio_read(nrf91_pinset_t pinset) +{ + unsigned int port; + unsigned int pin; + uint32_t regval; + uint32_t offset; + + /* Get port and pin number */ + + pin = GPIO_PIN_DECODE(pinset); + port = GPIO_PORT_DECODE(pinset); + + /* Get register address */ + + offset = nrf91_gpio_regget(port, NRF91_GPIO_IN_OFFSET); + + /* Get register value */ + + regval = getreg32(offset); + + return (regval >> pin) & 1UL; +} + +/**************************************************************************** + * Name: nrf91_gpio_detectmode + * + * Description: + * Set DETECTMODE to either default or latched + * + ****************************************************************************/ + +void nrf91_gpio_detectmode(int port, enum nrf91_gpio_detectmode_e mode) +{ + uint32_t offset = nrf91_gpio_regget(port, NRF91_GPIO_DETECTMODE_OFFSET); + + putreg32(mode == NRF91_GPIO_DETECTMODE_DETECT ? + GPIO_DETECTMODE_DEFAULT : + GPIO_DETECTMODE_LDETECT, offset); +} diff --git a/arch/arm/src/nrf91/nrf91_gpio.h b/arch/arm/src/nrf91/nrf91_gpio.h new file mode 100644 index 0000000000..c71cca79ef --- /dev/null +++ b/arch/arm/src/nrf91/nrf91_gpio.h @@ -0,0 +1,264 @@ +/**************************************************************************** + * arch/arm/src/nrf91/nrf91_gpio.h + * + * 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. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_NRF91_NRF91_GPIO_H +#define __ARCH_ARM_SRC_NRF91_NRF91_GPIO_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifndef __ASSEMBLY__ +# include +# include +#endif + +#include +#include "hardware/nrf91_gpio.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Bit-encoded input to nrf91_gpio_config() *********************************/ + +/* 32-Bit Encoding: .... .... .... .GGF FSSD DDDM MVPN NNNN + * + * Pin Function: FF + * Pin Sense: SS + * Pin Drive: DDDD + * Pin Mode bits: MM + * Initial value: V (output pins) + * Port number: P (0-1) + * Pin number: NNNNN (0-31) + */ + +/* Pin Function bits: + * Only meaningful when the GPIO function is GPIO_PIN + * + * .... .... .... ...F F... .... .... .... + */ + +#define GPIO_FUNC_SHIFT (15) /* Bits 15-16: GPIO mode */ +#define GPIO_FUNC_MASK (0x03 << GPIO_FUNC_SHIFT) +# define GPIO_INPUT (0x00 << GPIO_FUNC_SHIFT) /* 00000 GPIO input pin */ +# define GPIO_OUTPUT (0x01 << GPIO_FUNC_SHIFT) /* 00001 GPIO output pin */ + +/* Pin Sense bits: + * + * .... .... .... .... .SS. .... .... .... + */ + +#define GPIO_SENSE_SHIFT (13) /* Bits 13-14: Pin Sense mode */ +#define GPIO_SENSE_MASK (0x3 << GPIO_SENSE_SHIFT) +# define GPIO_SENSE_NONE (0 << GPIO_SENSE_SHIFT) +# define GPIO_SENSE_HIGH (2 << GPIO_SENSE_SHIFT) +# define GPIO_SENSE_LOW (3 << GPIO_SENSE_SHIFT) + +/* Pin Drive bits: + * + * .... .... .... .... ...D DDD. .... .... + */ + +#define GPIO_DRIVE_SHIFT (9) /* Bits 9-12: Pin pull-up mode */ +#define GPIO_DRIVE_MASK (0xf << GPIO_DRIVE_SHIFT) +# define GPIO_DRIVE_S0S1 (0 << GPIO_DRIVE_SHIFT) /* Standard '0', standard '1' */ +# define GPIO_DRIVE_H0S1 (1 << GPIO_DRIVE_SHIFT) /* High drive '0', standard '1' */ +# define GPIO_DRIVE_S0H1 (2 << GPIO_DRIVE_SHIFT) +# define GPIO_DRIVE_H0H1 (3 << GPIO_DRIVE_SHIFT) +# define GPIO_DRIVE_D0S1 (4 << GPIO_DRIVE_SHIFT) +# define GPIO_DRIVE_D0H1 (5 << GPIO_DRIVE_SHIFT) +# define GPIO_DRIVE_S0D1 (6 << GPIO_DRIVE_SHIFT) +# define GPIO_DRIVE_H0D1 (7 << GPIO_DRIVE_SHIFT) +# define GPIO_DRIVE_EOS1 (8 << GPIO_DRIVE_SHIFT) +# define GPIO_DRIVE_SOE1 (9 << GPIO_DRIVE_SHIFT) +# define GPIO_DRIVE_EOE1 (10 << GPIO_DRIVE_SHIFT) +# define GPIO_DRIVE_DOE1 (11 << GPIO_DRIVE_SHIFT) +# define GPIO_DRIVE_EOD1 (12 << GPIO_DRIVE_SHIFT) + +/* Pin Mode: MM + * + * .... .... .... .... .... ...M M... .... + */ + +#define GPIO_MODE_SHIFT (7) /* Bits 7-8: Pin pull-up mode */ +#define GPIO_MODE_MASK (0x3 << GPIO_MODE_SHIFT) +# define GPIO_FLOAT (0 << GPIO_MODE_SHIFT) /* Neither pull-up nor -down */ +# define GPIO_PULLDOWN (1 << GPIO_MODE_SHIFT) /* Pull-down resistor enabled */ +# define GPIO_PULLUP (2 << GPIO_MODE_SHIFT) /* Pull-up resistor enabled */ + +/* Initial value: V + * + * .... .... .... .... .... .... .V.. .... + */ + +#define GPIO_VALUE (1 << 6) /* Bit 6: Initial GPIO output value */ +# define GPIO_VALUE_ONE GPIO_VALUE +# define GPIO_VALUE_ZERO (0) + +/* Port number: PPP (0-5) + * + * .... .... .... .... .... .... ..P. .... + */ + +#define GPIO_PORT_SHIFT (5) /* Bit 5: Port number */ +#define GPIO_PORT_MASK (0x1 << GPIO_PORT_SHIFT) +# define GPIO_PORT0 (0 << GPIO_PORT_SHIFT) +# define GPIO_PORT1 (1 << GPIO_PORT_SHIFT) + +/* Pin number: NNNNN (0-31) + * + * .... .... .... .... .... .... ...N NNNN + */ + +#define GPIO_PIN_SHIFT 0 /* Bits 0-4: GPIO number: 0-31 */ +#define GPIO_PIN_MASK (0x1f << GPIO_PIN_SHIFT) +# define GPIO_PIN0 (0 << GPIO_PIN_SHIFT) +# define GPIO_PIN1 (1 << GPIO_PIN_SHIFT) +# define GPIO_PIN2 (2 << GPIO_PIN_SHIFT) +# define GPIO_PIN3 (3 << GPIO_PIN_SHIFT) +# define GPIO_PIN4 (4 << GPIO_PIN_SHIFT) +# define GPIO_PIN5 (5 << GPIO_PIN_SHIFT) +# define GPIO_PIN6 (6 << GPIO_PIN_SHIFT) +# define GPIO_PIN7 (7 << GPIO_PIN_SHIFT) +# define GPIO_PIN8 (8 << GPIO_PIN_SHIFT) +# define GPIO_PIN9 (9 << GPIO_PIN_SHIFT) +# define GPIO_PIN10 (10 << GPIO_PIN_SHIFT) +# define GPIO_PIN11 (11 << GPIO_PIN_SHIFT) +# define GPIO_PIN12 (12 << GPIO_PIN_SHIFT) +# define GPIO_PIN13 (13 << GPIO_PIN_SHIFT) +# define GPIO_PIN14 (14 << GPIO_PIN_SHIFT) +# define GPIO_PIN15 (15 << GPIO_PIN_SHIFT) +# define GPIO_PIN16 (16 << GPIO_PIN_SHIFT) +# define GPIO_PIN17 (17 << GPIO_PIN_SHIFT) +# define GPIO_PIN18 (18 << GPIO_PIN_SHIFT) +# define GPIO_PIN19 (19 << GPIO_PIN_SHIFT) +# define GPIO_PIN20 (20 << GPIO_PIN_SHIFT) +# define GPIO_PIN21 (21 << GPIO_PIN_SHIFT) +# define GPIO_PIN22 (22 << GPIO_PIN_SHIFT) +# define GPIO_PIN23 (23 << GPIO_PIN_SHIFT) +# define GPIO_PIN24 (24 << GPIO_PIN_SHIFT) +# define GPIO_PIN25 (25 << GPIO_PIN_SHIFT) +# define GPIO_PIN26 (26 << GPIO_PIN_SHIFT) +# define GPIO_PIN27 (27 << GPIO_PIN_SHIFT) +# define GPIO_PIN28 (28 << GPIO_PIN_SHIFT) +# define GPIO_PIN29 (29 << GPIO_PIN_SHIFT) +# define GPIO_PIN30 (30 << GPIO_PIN_SHIFT) +# define GPIO_PIN31 (31 << GPIO_PIN_SHIFT) +# define GPIO_PIN(n) ((n) << GPIO_PIN_SHIFT) + +/* Helper macros */ + +#define GPIO_PIN_DECODE(p) (((p) & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT) +#define GPIO_PORT_DECODE(p) (((p) & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +typedef uint32_t nrf91_pinset_t; + +enum nrf91_gpio_detectmode_e +{ + NRF91_GPIO_DETECTMODE_DETECT, + NRF91_GPIO_DETECTMODE_LDETECT, +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifndef __ASSEMBLY__ +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: nrf91_gpio_config + * + * Description: + * Configure a GPIO pin based on bit-encoded description of the pin. + * + ****************************************************************************/ + +int nrf91_gpio_config(nrf91_pinset_t cfgset); + +/**************************************************************************** + * Name: nrf91_gpio_unconfig + * + * Description: + * Unconfigure a GPIO pin based on bit-encoded description of the pin. + * + ****************************************************************************/ + +int nrf91_gpio_unconfig(nrf91_pinset_t cfgset); + +/**************************************************************************** + * Name: rnf52_gpio_write + * + * Description: + * Write one or zero to the selected GPIO pin + * + ****************************************************************************/ + +void nrf91_gpio_write(nrf91_pinset_t pinset, bool value); + +/**************************************************************************** + * Name: nrf91_gpio_read + * + * Description: + * Read one or zero from the selected GPIO pin + * + ****************************************************************************/ + +bool nrf91_gpio_read(nrf91_pinset_t pinset); + +/**************************************************************************** + * Function: nf52_gpio_dump + * + * Description: + * Dump all GPIO registers associated with the base address of the provided + * pinset. + * + ****************************************************************************/ + +#ifdef CONFIG_DEBUG_GPIO_INFO +int nrf91_gpio_dump(nrf91_pinset_t pinset, const char *msg); +#else +# define nrf91_gpio_dump(p,m) +#endif + +#ifdef __cplusplus +} +#endif +#endif /* __ASSEMBLY__ */ + +#endif /* __ARCH_ARM_SRC_NRF91_NRF91_GPIO_H */ diff --git a/arch/arm/src/nrf91/nrf91_i2c.c b/arch/arm/src/nrf91/nrf91_i2c.c new file mode 100644 index 0000000000..f600485e34 --- /dev/null +++ b/arch/arm/src/nrf91/nrf91_i2c.c @@ -0,0 +1,898 @@ +/**************************************************************************** + * arch/arm/src/nrf91/nrf91_i2c.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 "nrf91_gpio.h" +#include "nrf91_i2c.h" + +#include "hardware/nrf91_twi.h" +#include "hardware/nrf91_utils.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* I2C errors not functional yet */ + +#undef CONFIG_NRF91_I2C_ERRORS + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* I2C Device Private Data */ + +struct nrf91_i2c_priv_s +{ + const struct i2c_ops_s *ops; /* Standard I2C operations */ + uint32_t base; /* TWI base address */ + uint32_t scl_pin; /* SCL pin configuration */ + uint32_t sda_pin; /* SDA pin configuration */ + int refs; /* Reference count */ + int status; /* I2C transfer status */ +#ifndef CONFIG_I2C_POLLED + uint32_t irq; /* TWI interrupt */ +#endif + uint8_t msgc; /* Message count */ + struct i2c_msg_s *msgv; /* Message list */ + uint8_t *ptr; /* Current message buffer */ +#ifdef CONFIG_NRF91_I2C_MASTER_COPY_BUF_SIZE + /* Static buffer used for continued messages */ + + uint8_t copy_buf[CONFIG_NRF91_I2C_MASTER_COPY_BUF_SIZE]; +#endif + uint32_t freq; /* Current I2C frequency */ + int dcnt; /* Current message length */ + uint16_t flags; /* Current message flags */ + uint16_t addr; /* Current I2C address */ + mutex_t lock; /* Mutual exclusion mutex */ +#ifndef CONFIG_I2C_POLLED + sem_t sem_isr; /* Interrupt wait semaphore */ +#endif +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static inline void nrf91_i2c_putreg(struct nrf91_i2c_priv_s *priv, + uint32_t offset, + uint32_t value); +static inline uint32_t nrf91_i2c_getreg(struct nrf91_i2c_priv_s *priv, + uint32_t offset); +static int nrf91_i2c_transfer(struct i2c_master_s *dev, + struct i2c_msg_s *msgs, + int count); +#ifdef CONFIG_I2C_RESET +static int nrf91_i2c_reset(struct i2c_master_s *dev); +#endif +#ifndef CONFIG_I2C_POLLED +static int nrf91_i2c_isr(int irq, void *context, void *arg); +#endif +static int nrf91_i2c_deinit(struct nrf91_i2c_priv_s *priv); +static int nrf91_i2c_init(struct nrf91_i2c_priv_s *priv); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* I2C operations */ + +static const struct i2c_ops_s g_nrf91_i2c_ops = +{ + .transfer = nrf91_i2c_transfer +#ifdef CONFIG_I2C_RESET + , .reset = nrf91_i2c_reset +#endif +}; + +/* I2C0 (TWI0) device */ + +#ifdef CONFIG_NRF91_I2C0_MASTER + +static struct nrf91_i2c_priv_s g_nrf91_i2c0_priv = +{ + .ops = &g_nrf91_i2c_ops, + .base = NRF91_TWIM0_BASE, + .scl_pin = BOARD_I2C0_SCL_PIN, + .sda_pin = BOARD_I2C0_SDA_PIN, + .refs = 0, + .lock = NXMUTEX_INITIALIZER, +#ifndef CONFIG_I2C_POLLED + .sem_isr = SEM_INITIALIZER(0), + .irq = NRF91_IRQ_SERIAL0, +#endif + .msgc = 0, + .msgv = NULL, + .ptr = NULL, + .freq = 0, + .dcnt = 0, + .flags = 0, + .addr = 0, +}; +#endif + +/* I2C1 (TWI1) device */ + +#ifdef CONFIG_NRF91_I2C1_MASTER +static struct nrf91_i2c_priv_s g_nrf91_i2c1_priv = +{ + .ops = &g_nrf91_i2c_ops, + .base = NRF91_TWIM1_BASE, + .scl_pin = BOARD_I2C1_SCL_PIN, + .sda_pin = BOARD_I2C1_SDA_PIN, + .refs = 0, + .lock = NXMUTEX_INITIALIZER, +#ifndef CONFIG_I2C_POLLED + .sem_isr = SEM_INITIALIZER(0), + .irq = NRF91_IRQ_SERIAL1, +#endif + .msgc = 0, + .msgv = NULL, + .ptr = NULL, + .freq = 0, + .dcnt = 0, + .flags = 0, + .addr = 0, +}; +#endif + +/* I2C2 (TWI3) device */ + +#ifdef CONFIG_NRF91_I2C2_MASTER +static struct nrf91_i2c_priv_s g_nrf91_i2c2_priv = +{ + .ops = &g_nrf91_i2c_ops, + .base = NRF91_TWIM2_BASE, + .scl_pin = BOARD_I2C2_SCL_PIN, + .sda_pin = BOARD_I2C2_SDA_PIN, + .refs = 0, + .lock = NXMUTEX_INITIALIZER, +#ifndef CONFIG_I2C_POLLED + .sem_isr = SEM_INITIALIZER(0), + .irq = NRF91_IRQ_SERIAL2, +#endif + .msgc = 0, + .msgv = NULL, + .ptr = NULL, + .freq = 0, + .dcnt = 0, + .flags = 0, + .addr = 0, +}; +#endif + +/* I2C3 (TWI3) device */ + +#ifdef CONFIG_NRF91_I2C3_MASTER +static struct nrf91_i2c_priv_s g_nrf91_i2c3_priv = +{ + .ops = &g_nrf91_i2c_ops, + .base = NRF91_TWIM2_BASE, + .scl_pin = BOARD_I2C3_SCL_PIN, + .sda_pin = BOARD_I2C3_SDA_PIN, + .refs = 0, + .lock = NXMUTEX_INITIALIZER, +#ifndef CONFIG_I2C_POLLED + .sem_isr = SEM_INITIALIZER(0), + .irq = NRF91_IRQ_SERIAL3, +#endif + .msgc = 0, + .msgv = NULL, + .ptr = NULL, + .freq = 0, + .dcnt = 0, + .flags = 0, + .addr = 0, +}; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nrf91_i2c_putreg + * + * Description: + * Put a 32-bit register value by offset + * + ****************************************************************************/ + +static inline void nrf91_i2c_putreg(struct nrf91_i2c_priv_s *priv, + uint32_t offset, + uint32_t value) +{ + putreg32(value, priv->base + offset); +} + +/**************************************************************************** + * Name: nrf91_i2c_getreg + * + * Description: + * Get a 32-bit register value by offset + * + ****************************************************************************/ + +static inline uint32_t nrf91_i2c_getreg(struct nrf91_i2c_priv_s *priv, + uint32_t offset) +{ + return getreg32(priv->base + offset); +} + +/**************************************************************************** + * Name: nrf91_i2c_transfer + * + * Description: + * Generic I2C transfer function + * + ****************************************************************************/ + +static int nrf91_i2c_transfer(struct i2c_master_s *dev, + struct i2c_msg_s *msgs, + int count) +{ + struct nrf91_i2c_priv_s *priv = (struct nrf91_i2c_priv_s *)dev; + uint32_t regval = 0; + int ret = OK; +#ifndef CONFIG_NRF91_I2C_MASTER_DISABLE_NOSTART + uint8_t *pack_buf = NULL; +#endif + + ret = nxmutex_lock(&priv->lock); + if (ret < 0) + { + return ret; + } + + /* Reset ptr and dcnt */ + + priv->dcnt = 0; + priv->ptr = NULL; + + priv->msgv = msgs; + priv->msgc = count; + + /* Reset I2C transfer status */ + + priv->status = OK; + + i2cinfo("I2C TRANSFER count=%d\n", count); + + /* Do we need change I2C bus frequency ? */ + + if (priv->msgv->frequency != priv->freq) + { + /* Get TWI frequency */ + + switch (priv->msgv->frequency) + { + case 100000: + { + regval = TWIM_FREQUENCY_100KBPS; + break; + } + + case 250000: + { + regval = TWIM_FREQUENCY_250KBPS; + break; + } + + case 400000: + { + regval = TWIM_FREQUENCY_400KBPS; + break; + } + + default: + { + ret = -EINVAL; + goto errout; + } + } + + /* Write TWI frequency */ + + nrf91_i2c_putreg(priv, NRF91_TWIM_FREQUENCY_OFFSET, regval); + + /* Save the new I2C frequency */ + + priv->freq = priv->msgv->frequency; + } + + /* I2C transfer */ + + do + { + /* Get current message data */ + + priv->ptr = priv->msgv->buffer; + priv->dcnt = priv->msgv->length; + priv->flags = priv->msgv->flags; + priv->addr = priv->msgv->addr; + + i2cinfo("ptr=%p dcnt=%d flags=%d addr=%d\n", + priv->ptr, priv->dcnt, priv->flags, priv->addr); + + /* Write TWI address */ + + regval = priv->addr; + nrf91_i2c_putreg(priv, NRF91_TWIM_ADDRESS_OFFSET, regval); + + if ((priv->flags & I2C_M_READ) == 0) + { +#ifndef CONFIG_NRF91_I2C_MASTER_DISABLE_NOSTART + /* Check if we need to combine messages */ + + if (priv->msgc > 1) + { + if (priv->msgv[1].flags & I2C_M_NOSTART) + { + /* More than 2 messages not supported */ + + DEBUGASSERT(priv->msgc < 3); + + /* Combine buffers */ + + if ((priv->msgv[0].length + + priv->msgv[1].length) <= + CONFIG_NRF91_I2C_MASTER_COPY_BUF_SIZE) + { + pack_buf = priv->copy_buf; + } + else + { + pack_buf = kmm_malloc(priv->msgv[0].length + + priv->msgv[1].length); + if (pack_buf == NULL) + { + return -ENOMEM; + } + } + + /* Combine messages */ + + memcpy(pack_buf, priv->msgv[0].buffer, + priv->msgv[0].length); + memcpy(pack_buf + priv->msgv[0].length, + priv->msgv[1].buffer, priv->msgv[1].length); + + /* Use new buffer to transmit data */ + + priv->ptr = pack_buf; + priv->dcnt = priv->msgv[0].length + priv->msgv[1].length; + + /* Next message */ + + priv->msgc -= 1; + priv->msgv += 1; + } + } +#else + if (priv->msgc > 1) + { + if (priv->msgv[1].flags & I2C_M_NOSTART) + { + /* Not supported */ + + DEBUGPANIC(); + } + } +#endif + + /* Write TXD data pointer */ + + regval = (uint32_t)priv->ptr; + DEBUGASSERT(nrf91_easydma_valid(regval)); + nrf91_i2c_putreg(priv, NRF91_TWIM_TXDPTR_OFFSET, regval); + + /* Write number of bytes in TXD buffer */ + + regval = priv->dcnt; + nrf91_i2c_putreg(priv, NRF91_TWIM_TXMAXCNT_OFFSET, regval); + + /* Start TX sequence */ + + nrf91_i2c_putreg(priv, NRF91_TWIM_TASKS_STARTTX_OFFSET, 1); + + /* Wait for last TX event */ + +#ifdef CONFIG_I2C_POLLED + while (nrf91_i2c_getreg(priv, + NRF91_TWIM_EVENTS_LASTTX_OFFSET) != 1); + while (1) + { + regval = nrf91_i2c_getreg(priv, + NRF91_TWIM_ERRORSRC_OFFSET) & 0x7; + if (regval != 0) + { + i2cerr("Error SRC: 0x%08" PRIx32 "\n", regval); + ret = -1; + nrf91_i2c_putreg(priv, + NRF91_TWIM_ERRORSRC_OFFSET, 0x7); + goto errout; + } + + if (nrf91_i2c_getreg(priv, + NRF91_TWIM_EVENTS_LASTTX_OFFSET) == 1) + { + break; + } + } + + /* Clear event */ + + nrf91_i2c_putreg(priv, NRF91_TWIM_EVENTS_LASTTX_OFFSET, 0); +#else + nxsem_wait(&priv->sem_isr); + + if (priv->status < 0) + { + goto errout; + } +#endif + } + else + { + /* Write RXD data pointer */ + + regval = (uint32_t)priv->ptr; + DEBUGASSERT(nrf91_easydma_valid(regval)); + nrf91_i2c_putreg(priv, NRF91_TWIM_RXDPTR_OFFSET, regval); + + /* Write number of bytes in RXD buffer */ + + regval = priv->dcnt; + nrf91_i2c_putreg(priv, NRF91_TWIM_RXDMAXCNT_OFFSET, regval); + + /* Start RX sequence */ + + nrf91_i2c_putreg(priv, NRF91_TWIM_TASKS_STARTRX_OFFSET, 1); + + /* Wait for last RX done */ + +#ifdef CONFIG_I2C_POLLED + while (1) + { + regval = nrf91_i2c_getreg(priv, + NRF91_TWIM_ERRORSRC_OFFSET) & 0x7; + if (regval != 0) + { + i2cerr("Error SRC: 0x%08" PRIx32 "\n", regval); + ret = -1; + nrf91_i2c_putreg(priv, + NRF91_TWIM_ERRORSRC_OFFSET, 0x7); + goto errout; + } + + if (nrf91_i2c_getreg(priv, + NRF91_TWIM_EVENTS_LASTRX_OFFSET) == 1) + { + break; + } + } + + /* Clear event */ + + nrf91_i2c_putreg(priv, NRF91_TWIM_EVENTS_LASTRX_OFFSET, 0); +#else + nxsem_wait(&priv->sem_isr); + + if (priv->status < 0) + { + goto errout; + } +#endif + } + + /* Next message */ + + priv->msgc -= 1; + priv->msgv += 1; + } + while (priv->msgc > 0); + + /* TWIM stop */ + + nrf91_i2c_putreg(priv, NRF91_TWIM_TASKS_STOP_OFFSET, 1); + + /* Wait for stop event */ + +#ifdef CONFIG_I2C_POLLED + while (1) + { + regval = nrf91_i2c_getreg(priv, + NRF91_TWIM_ERRORSRC_OFFSET) & 0x7; + if (regval != 0) + { + i2cerr("Error SRC: 0x%08" PRIx32 "\n", regval); + ret = -1; + nrf91_i2c_putreg(priv, + NRF91_TWIM_ERRORSRC_OFFSET, 0x7); + goto errout; + } + + if (nrf91_i2c_getreg(priv, + NRF91_TWIM_EVENTS_STOPPED_OFFSET) == 1) + { + break; + } + } + + /* Clear event */ + + nrf91_i2c_putreg(priv, NRF91_TWIM_EVENTS_STOPPED_OFFSET, 0); +#else + nxsem_wait(&priv->sem_isr); + + if (priv->status < 0) + { + goto errout; + } +#endif + +errout: +#ifndef CONFIG_NRF91_I2C_MASTER_DISABLE_NOSTART + if (pack_buf != NULL && pack_buf != priv->copy_buf) + { + kmm_free(pack_buf); + } +#endif + + nxmutex_unlock(&priv->lock); + return ret; +} + +/**************************************************************************** + * Name: nrf91_i2c_reset + * + * Description: + * Perform an I2C bus reset in an attempt to break loose stuck I2C devices. + * + * Input Parameters: + * dev - Device-specific state data + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +#ifdef CONFIG_I2C_RESET +static int nrf91_i2c_reset(struct i2c_master_s *dev) +{ +#error not implemented +} +#endif + +/**************************************************************************** + * Name: nrf91_i2c_isr + * + * Description: + * Common I2C interrupt service routine + * + ****************************************************************************/ + +#ifndef CONFIG_I2C_POLLED +static int nrf91_i2c_isr(int irq, void *context, void *arg) +{ + struct nrf91_i2c_priv_s *priv = (struct nrf91_i2c_priv_s *)arg; + + /* Reset I2C status */ + + priv->status = OK; + + if ((priv->flags & I2C_M_READ) == 0) + { + if (nrf91_i2c_getreg(priv, NRF91_TWIM_EVENTS_LASTTX_OFFSET) == 1) + { + i2cinfo("I2C LASTTX\n"); + + /* TX done */ + + nxsem_post(&priv->sem_isr); + + /* Clear event */ + + nrf91_i2c_putreg(priv, NRF91_TWIM_EVENTS_LASTTX_OFFSET, 0); + + return OK; + } + } + else + { + if (nrf91_i2c_getreg(priv, NRF91_TWIM_EVENTS_LASTRX_OFFSET) == 1) + { + i2cinfo("I2C LASTRX\n"); + + /* RX done */ + + nxsem_post(&priv->sem_isr); + + /* Clear event */ + + nrf91_i2c_putreg(priv, NRF91_TWIM_EVENTS_LASTRX_OFFSET, 0); + + return OK; + } + } + + if (nrf91_i2c_getreg(priv, NRF91_TWIM_EVENTS_STOPPED_OFFSET) == 1) + { + i2cinfo("I2C STOPPED\n"); + + /* STOPPED event */ + + nxsem_post(&priv->sem_isr); + + /* Clear event */ + + nrf91_i2c_putreg(priv, NRF91_TWIM_EVENTS_STOPPED_OFFSET, 0); + } + +#ifdef CONFIG_NRF91_I2C_ERRORS + if (nrf91_i2c_getreg(priv, NRF91_TWIM_EVENTS_ERROR_OFFSET) == 1) + { + i2cerr("I2C ERROR\n"); + + /* Set ERROR status */ + + priv->status = ERROR; + + /* ERROR event */ + + nxsem_post(&priv->sem_isr); + + /* Clear event */ + + nrf91_i2c_putreg(priv, NRF91_TWIM_EVENTS_ERROR_OFFSET, 0); + } +#endif + + return OK; +} +#endif + +/**************************************************************************** + * Name: nrf91_i2c_init + * + * Description: + * Setup the I2C hardware, ready for operation with defaults + * + ****************************************************************************/ + +static int nrf91_i2c_init(struct nrf91_i2c_priv_s *priv) +{ + uint32_t regval = 0; + int pin = 0; + int port = 0; + + /* Disable TWI interface */ + + nrf91_i2c_putreg(priv, NRF91_TWIM_ENABLE_OFFSET, TWIM_ENABLE_DIS); + + /* Configure SCL and SDA pins */ + + nrf91_gpio_config(priv->scl_pin); + nrf91_gpio_config(priv->sda_pin); + + /* Select SCL pin */ + + pin = GPIO_PIN_DECODE(priv->scl_pin); + port = GPIO_PORT_DECODE(priv->scl_pin); + + regval = (pin << TWIM_PSELSCL_PIN_SHIFT); + regval |= (port << TWIM_PSELSCL_PORT_SHIFT); + nrf91_i2c_putreg(priv, NRF91_TWIM_PSELSCL_OFFSET, regval); + + /* Select SDA pin */ + + pin = GPIO_PIN_DECODE(priv->sda_pin); + port = GPIO_PORT_DECODE(priv->sda_pin); + + regval = (pin << TWIM_PSELSDA_PIN_SHIFT); + regval |= (port << TWIM_PSELSDA_PORT_SHIFT); + nrf91_i2c_putreg(priv, NRF91_TWIM_PSELSDA_OFFSET, regval); + + /* Enable TWI interface */ + + nrf91_i2c_putreg(priv, NRF91_TWIM_ENABLE_OFFSET, TWIM_ENABLE_EN); + +#ifndef CONFIG_I2C_POLLED + /* Enable I2C interrupts */ + +#ifdef CONFIG_NRF91_I2C_ERRORS + regval = (TWIM_INT_LASTRX | TWIM_INT_LASTTX | TWIM_INT_STOPPED | + TWIM_INT_ERROR); +#else + regval = (TWIM_INT_LASTRX | TWIM_INT_LASTTX | TWIM_INT_STOPPED); +#endif + nrf91_i2c_putreg(priv, NRF91_TWIM_INTEN_OFFSET, regval); + + /* Attach error and event interrupts to the ISRs */ + + irq_attach(priv->irq, nrf91_i2c_isr, priv); + up_enable_irq(priv->irq); +#endif + + return OK; +} + +/**************************************************************************** + * Name: nrf91_i2c_deinit + * + * Description: + * Shutdown the I2C hardware + * + ****************************************************************************/ + +static int nrf91_i2c_deinit(struct nrf91_i2c_priv_s *priv) +{ + /* Disable TWI interface */ + + nrf91_i2c_putreg(priv, NRF91_TWIM_ENABLE_OFFSET, TWIM_ENABLE_DIS); + + /* Unconfigure GPIO pins */ + + nrf91_gpio_unconfig(priv->scl_pin); + nrf91_gpio_unconfig(priv->sda_pin); + + /* Deatach TWI from GPIO */ + + nrf91_i2c_putreg(priv, NRF91_TWIM_PSELSCL_OFFSET, TWIM_PSELSCL_RESET); + nrf91_i2c_putreg(priv, NRF91_TWIM_PSELSDA_OFFSET, TWIM_PSELSDA_RESET); + + /* Disable and detach interrupts */ + +#ifndef CONFIG_I2C_POLLED + up_disable_irq(priv->irq); + irq_detach(priv->irq); +#endif + + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nrf91_i2cbus_initialize + * + * Description: + * Initialize one I2C bus + * + ****************************************************************************/ + +struct i2c_master_s *nrf91_i2cbus_initialize(int port) +{ + struct nrf91_i2c_priv_s *priv = NULL; + + i2cinfo("I2C INITIALIZE port=%d\n", port); + + /* Get interface */ + + switch (port) + { +#ifdef CONFIG_NRF91_I2C0_MASTER + case 0: + { + priv = (struct nrf91_i2c_priv_s *)&g_nrf91_i2c0_priv; + break; + } +#endif + +#ifdef CONFIG_NRF91_I2C1_MASTER + case 1: + { + priv = (struct nrf91_i2c_priv_s *)&g_nrf91_i2c1_priv; + break; + } +#endif + +#ifdef CONFIG_NRF91_I2C2_MASTER + case 2: + { + priv = (struct nrf91_i2c_priv_s *)&g_nrf91_i2c2_priv; + break; + } +#endif + +#ifdef CONFIG_NRF91_I2C3_MASTER + case 3: + { + priv = (struct nrf91_i2c_priv_s *)&g_nrf91_i2c3_priv; + break; + } +#endif + + default: + { + return NULL; + } + } + + /* Initialize private data for the first time, increment reference count, + * power-up hardware and configure GPIOs. + */ + + nxmutex_lock(&priv->lock); + if (priv->refs++ == 0) + { + /* Initialize I2C */ + + nrf91_i2c_init(priv); + } + + nxmutex_unlock(&priv->lock); + return (struct i2c_master_s *)priv; +} + +/**************************************************************************** + * Name: nrf91_i2cbus_uninitialize + * + * Description: + * Uninitialize an I2C bus + * + ****************************************************************************/ + +int nrf91_i2cbus_uninitialize(struct i2c_master_s *dev) +{ + struct nrf91_i2c_priv_s *priv = (struct nrf91_i2c_priv_s *)dev; + + DEBUGASSERT(dev); + + /* Decrement reference count and check for underflow */ + + if (priv->refs == 0) + { + return ERROR; + } + + nxmutex_lock(&priv->lock); + if (--priv->refs) + { + nxmutex_unlock(&priv->lock); + return OK; + } + + /* Disable power and other HW resource (GPIO's) */ + + nrf91_i2c_deinit(priv); + nxmutex_unlock(&priv->lock); + + return OK; +} diff --git a/arch/arm/src/nrf91/nrf91_i2c.h b/arch/arm/src/nrf91/nrf91_i2c.h new file mode 100644 index 0000000000..b22e8607ac --- /dev/null +++ b/arch/arm/src/nrf91/nrf91_i2c.h @@ -0,0 +1,73 @@ +/**************************************************************************** + * arch/arm/src/nrf91/nrf91_i2c.h + * + * 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. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_NRF91_NRF91_I2C_H +#define __ARCH_ARM_SRC_NRF91_NRF91_I2C_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include "chip.h" + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: nrf91_i2cbus_initialize + * + * Description: + * Initialize the selected I2C port. And return a unique instance of struct + * struct i2c_master_s. This function may be called to obtain multiple + * instances of the interface, each of which may be set up with a + * different frequency and slave address. + * + * Input Parameters: + * Port number (for hardware that has multiple TWI interfaces) + * + * Returned Value: + * Valid I2C device structure reference on success; a NULL on failure + * + ****************************************************************************/ + +struct i2c_master_s *nrf91_i2cbus_initialize(int port); + +/**************************************************************************** + * Name: nrf91_i2cbus_uninitialize + * + * Description: + * De-initialize the selected I2C port, and power down the device. + * + * Input Parameters: + * Device structure as returned by the nrf91_i2cbus_initialize() + * + * Returned Value: + * OK on success, ERROR when internal reference count mismatch or dev + * points to invalid hardware device. + * + ****************************************************************************/ + +int nrf91_i2cbus_uninitialize(struct i2c_master_s *dev); + +#endif /* __ARCH_ARM_SRC_NRF91_NRF91_I2C_H */ diff --git a/arch/arm/src/nrf91/nrf91_idle.c b/arch/arm/src/nrf91/nrf91_idle.c new file mode 100644 index 0000000000..5c9062aabb --- /dev/null +++ b/arch/arm/src/nrf91/nrf91_idle.c @@ -0,0 +1,96 @@ +/**************************************************************************** + * arch/arm/src/nrf91/nrf91_idle.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 "arm_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Does the board support an IDLE LED to indicate that the board is in the + * IDLE state? + */ + +#if defined(CONFIG_ARCH_LEDS) && defined(LED_IDLE) +# define BEGIN_IDLE() board_autoled_on(LED_IDLE) +# define END_IDLE() board_autoled_off(LED_IDLE) +#else +# define BEGIN_IDLE() +# define END_IDLE() +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_idle + * + * Description: + * up_idle() is the logic that will be executed when there is no other + * ready-to-run task. This is processor idle time and will continue until + * some interrupt occurs to cause a context switch from the idle task. + * + * Processing in this state may be processor-specific. e.g., this is where + * power management operations might be performed. + * + ****************************************************************************/ + +void up_idle(void) +{ +#if defined(CONFIG_SUPPRESS_INTERRUPTS) || defined(CONFIG_SUPPRESS_TIMER_INTS) + /* If the system is idle and there are no timer interrupts, then process + * "fake" timer interrupts. Hopefully, something will wake up. + */ + + nxsched_process_timer(); +#else + + /* Sleep until an interrupt occurs to save power + * + * The SysTick's clock will only tick when the CPU is + * running (not in WFE/WFI) or when the system is in debug interface mode. + */ + +#ifdef CONFIG_NRF91_SYSTIMER_RTC + BEGIN_IDLE(); + asm("WFI"); + END_IDLE(); +#endif +#endif +} diff --git a/arch/arm/src/nrf91/nrf91_irq.c b/arch/arm/src/nrf91/nrf91_irq.c new file mode 100644 index 0000000000..e4704464e2 --- /dev/null +++ b/arch/arm/src/nrf91/nrf91_irq.c @@ -0,0 +1,525 @@ +/**************************************************************************** + * arch/arm/src/nrf91/nrf91_irq.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 "chip.h" +#include "nvic.h" +#include "ram_vectors.h" +#include "arm_internal.h" +#include "nrf91_irq.h" +#ifdef CONFIG_NRF91_GPIOTE +# include "nrf91_gpiote.h" +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Get a 32-bit version of the default priority */ + +#define DEFPRIORITY32 \ + (NVIC_SYSH_PRIORITY_DEFAULT << 24 | NVIC_SYSH_PRIORITY_DEFAULT << 16 | \ + NVIC_SYSH_PRIORITY_DEFAULT << 8 | NVIC_SYSH_PRIORITY_DEFAULT) + +/* Given the address of a NVIC ENABLE register, this is the offset to + * the corresponding CLEAR ENABLE register. + */ + +#define NVIC_ENA_OFFSET (0) +#define NVIC_CLRENA_OFFSET (NVIC_IRQ0_31_CLEAR - NVIC_IRQ0_31_ENABLE) + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nrf91_dumpnvic + * + * Description: + * Dump some interesting NVIC registers + * + ****************************************************************************/ + +#if defined(CONFIG_DEBUG_IRQ_INFO) +static void nrf91_dumpnvic(const char *msg, int irq) +{ + irqstate_t flags; + + flags = enter_critical_section(); + + irqinfo("NVIC (%s, irq=%d):\n", msg, irq); + irqinfo(" INTCTRL: %08x VECTAB: %08x\n", + getreg32(NVIC_INTCTRL), getreg32(NVIC_VECTAB)); +#if 0 + irqinfo(" SYSH ENABLE MEMFAULT: %08x BUSFAULT: %08x\n", + getreg32(NVIC_SYSHCON_MEMFAULTENA), + getreg32(NVIC_SYSHCON_BUSFAULTENA)); + irqinfo(" USGFAULT: %08x SYSTICK: %08x\n", + getreg32(NVIC_SYSHCON_USGFAULTENA), + getreg32(NVIC_SYSTICK_CTRL_ENABLE)); +#endif + irqinfo(" IRQ ENABLE: %08x %08x\n", + getreg32(NVIC_IRQ0_31_ENABLE), + getreg32(NVIC_IRQ32_63_ENABLE)); + irqinfo(" SYSH_PRIO: %08x %08x %08x\n", + getreg32(NVIC_SYSH4_7_PRIORITY), + getreg32(NVIC_SYSH8_11_PRIORITY), + getreg32(NVIC_SYSH12_15_PRIORITY)); + irqinfo(" IRQ PRIO: %08x %08x %08x %08x\n", + getreg32(NVIC_IRQ0_3_PRIORITY), + getreg32(NVIC_IRQ4_7_PRIORITY), + getreg32(NVIC_IRQ8_11_PRIORITY), + getreg32(NVIC_IRQ12_15_PRIORITY)); + irqinfo(" %08x %08x %08x %08x\n", + getreg32(NVIC_IRQ16_19_PRIORITY), + getreg32(NVIC_IRQ20_23_PRIORITY), + getreg32(NVIC_IRQ24_27_PRIORITY), + getreg32(NVIC_IRQ28_31_PRIORITY)); + irqinfo(" %08x %08x %08x %08x\n", + getreg32(NVIC_IRQ32_35_PRIORITY), + getreg32(NVIC_IRQ36_39_PRIORITY), + getreg32(NVIC_IRQ40_43_PRIORITY), + getreg32(NVIC_IRQ44_47_PRIORITY)); + irqinfo(" %08x %08x %08x\n", + getreg32(NVIC_IRQ48_51_PRIORITY), + getreg32(NVIC_IRQ52_55_PRIORITY), + getreg32(NVIC_IRQ56_59_PRIORITY)); + + leave_critical_section(flags); +} +#else +# define nrf91_dumpnvic(msg, irq) +#endif + +/**************************************************************************** + * Name: nrf91_nmi, nrf91_pendsv, + * nrf91_dbgmonitor, nrf91_pendsv, nrf91_reserved + * + * Description: + * Handlers for various exceptions. None are handled and all are fatal + * error conditions. The only advantage these provided over the default + * unexpected interrupt handler is that they provide a diagnostic output. + * + ****************************************************************************/ + +#ifdef CONFIG_DEBUG_FEATURES +static int nrf91_nmi(int irq, void *context, void *arg) +{ + up_irq_save(); + _err("PANIC!!! NMI received\n"); + PANIC(); + return 0; +} + +static int nrf91_pendsv(int irq, void *context, void *arg) +{ + up_irq_save(); + _err("PANIC!!! PendSV received\n"); + PANIC(); + return 0; +} + +static int nrf91_dbgmonitor(int irq, void *context, void *arg) +{ + up_irq_save(); + _err("PANIC!!! Debug Monitor received\n"); + PANIC(); + return 0; +} + +static int nrf91_reserved(int irq, void *context, void *arg) +{ + up_irq_save(); + _err("PANIC!!! Reserved interrupt\n"); + PANIC(); + return 0; +} +#endif + +/**************************************************************************** + * Name: nrf91_prioritize_syscall + * + * Description: + * Set the priority of an exception. This function may be needed + * internally even if support for prioritized interrupts is not enabled. + * + ****************************************************************************/ + +#ifdef CONFIG_ARMV8M_USEBASEPRI +static inline void nrf91_prioritize_syscall(int priority) +{ + uint32_t regval; + + /* SVCALL is system handler 11 */ + + regval = getreg32(NVIC_SYSH8_11_PRIORITY); + regval &= ~NVIC_SYSH_PRIORITY_PR11_MASK; + regval |= (priority << NVIC_SYSH_PRIORITY_PR11_SHIFT); + putreg32(regval, NVIC_SYSH8_11_PRIORITY); +} +#endif + +/**************************************************************************** + * Name: nrf91_irqinfo + * + * Description: + * Given an IRQ number, provide the register and bit setting to enable or + * disable the irq. + * + ****************************************************************************/ + +static int nrf91_irqinfo(int irq, uintptr_t *regaddr, uint32_t *bit, + uintptr_t offset) +{ + int n; + + DEBUGASSERT(irq >= NRF91_IRQ_NMI && irq < NR_IRQS); + + /* Check for external interrupt */ + + if (irq >= NRF91_IRQ_EXTINT) + { + n = irq - NRF91_IRQ_EXTINT; + *regaddr = NVIC_IRQ_ENABLE(n) + offset; + *bit = (uint32_t)1 << (n & 0x1f); + } + + /* Handle processor exceptions. Only a few can be disabled */ + + else + { + *regaddr = NVIC_SYSHCON; + if (irq == NRF91_IRQ_MEMFAULT) + { + *bit = NVIC_SYSHCON_MEMFAULTENA; + } + else if (irq == NRF91_IRQ_BUSFAULT) + { + *bit = NVIC_SYSHCON_BUSFAULTENA; + } + else if (irq == NRF91_IRQ_USAGEFAULT) + { + *bit = NVIC_SYSHCON_USGFAULTENA; + } + else if (irq == NRF91_IRQ_SYSTICK) + { + *regaddr = NVIC_SYSTICK_CTRL; + *bit = NVIC_SYSTICK_CTRL_ENABLE; + } + else + { + return ERROR; /* Invalid or unsupported exception */ + } + } + + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_irqinitialize + * + * Description: + * Complete initialization of the interrupt system and enable normal, + * interrupt processing. + * + ****************************************************************************/ + +void up_irqinitialize(void) +{ + uint32_t regaddr; +#if defined(CONFIG_DEBUG_FEATURES) && !defined(CONFIG_ARMV8M_USEBASEPRI) + uint32_t regval; +#endif + int num_priority_registers; + int i; + + /* Disable all interrupts */ + + for (i = 0; i < NRF91_IRQ_NEXTINT; i += 32) + { + putreg32(0xffffffff, NVIC_IRQ_CLEAR(i)); + } + + /* Make sure that we are using the correct vector table. The default + * vector address is 0x0000:0000 but if we are executing code that is + * positioned in SRAM or in external FLASH, then we may need to reset + * the interrupt vector so that it refers to the table in SRAM or in + * external FLASH. + */ + + putreg32((uint32_t)_vectors, NVIC_VECTAB); + +#ifdef CONFIG_ARCH_RAMVECTORS + /* If CONFIG_ARCH_RAMVECTORS is defined, then we are using a RAM-based + * vector table that requires special initialization. + */ + + arm_ramvec_initialize(); +#endif + + /* Set all interrupts (and exceptions) to the default priority */ + + putreg32(DEFPRIORITY32, NVIC_SYSH4_7_PRIORITY); + putreg32(DEFPRIORITY32, NVIC_SYSH8_11_PRIORITY); + putreg32(DEFPRIORITY32, NVIC_SYSH12_15_PRIORITY); + + /* The NVIC ICTR register (bits 0-4) holds the number of interrupt + * lines that the NVIC supports: + * + * 0 -> 32 interrupt lines, 8 priority registers + * 1 -> 64 " " " ", 16 priority registers + * 2 -> 96 " " " ", 32 priority registers + * ... + */ + + num_priority_registers = (getreg32(NVIC_ICTR) + 1) * 8; + + /* Now set all of the interrupt lines to the default priority */ + + regaddr = NVIC_IRQ0_3_PRIORITY; + while (num_priority_registers--) + { + putreg32(DEFPRIORITY32, regaddr); + regaddr += 4; + } + + /* Attach the SVCall and Hard Fault exception handlers. The SVCall + * exception is used for performing context switches; The Hard Fault + * must also be caught because a SVCall may show up as a Hard Fault + * under certain conditions. + */ + + irq_attach(NRF91_IRQ_SVCALL, arm_svcall, NULL); + irq_attach(NRF91_IRQ_HARDFAULT, arm_hardfault, NULL); + + /* Set the priority of the SVCall interrupt */ + +#ifdef CONFIG_ARCH_IRQPRIO +# if 0 + up_prioritize_irq(NRF91_IRQ_PENDSV, NVIC_SYSH_PRIORITY_MIN); +# endif +#endif + +#ifdef CONFIG_ARMV8M_USEBASEPRI + nrf91_prioritize_syscall(NVIC_SYSH_SVCALL_PRIORITY); +#endif + +#ifdef CONFIG_ARM_MPU + /* If the MPU is enabled, then attach and enable the Memory Management + * Fault handler. + */ + + irq_attach(NRF91_IRQ_MEMFAULT, arm_memfault, NULL); + up_enable_irq(NRF91_IRQ_MEMFAULT); +#endif + + /* Attach all other processor exceptions (except reset and sys tick) */ + +#ifdef CONFIG_DEBUG_FEATURES + irq_attach(NRF91_IRQ_NMI, nrf91_nmi, NULL); +#ifndef CONFIG_ARM_MPU + irq_attach(NRF91_IRQ_MEMFAULT, arm_memfault, NULL); +#endif + irq_attach(NRF91_IRQ_BUSFAULT, arm_busfault, NULL); + irq_attach(NRF91_IRQ_USAGEFAULT, arm_usagefault, NULL); + irq_attach(NRF91_IRQ_PENDSV, nrf91_pendsv, NULL); + irq_attach(NRF91_IRQ_DBGMONITOR, nrf91_dbgmonitor, NULL); + irq_attach(NRF91_IRQ_RESERVED, nrf91_reserved, NULL); +#endif + + nrf91_dumpnvic("initial", NRF91_IRQ_NIRQS); + +#if defined(CONFIG_DEBUG_FEATURES) && !defined(CONFIG_ARMV8M_USEBASEPRI) + /* If a debugger is connected, try to prevent it from catching hardfaults. + * If CONFIG_ARMV8M_USEBASEPRI, no hardfaults are expected in normal + * operation. + */ + + regval = getreg32(NVIC_DEMCR); + regval &= ~NVIC_DEMCR_VCHARDERR; + putreg32(regval, NVIC_DEMCR); +#endif + +#ifdef CONFIG_NRF91_GPIOTE + /* Initialize GPIOTE */ + + nrf91_gpiote_init(); +#endif + +#ifndef CONFIG_SUPPRESS_INTERRUPTS + /* And finally, enable interrupts */ + + up_irq_enable(); +#endif +} + +/**************************************************************************** + * Name: up_disable_irq + * + * Description: + * Disable the IRQ specified by 'irq' + * + ****************************************************************************/ + +void up_disable_irq(int irq) +{ + uintptr_t regaddr; + uint32_t regval; + uint32_t bit; + + if (nrf91_irqinfo(irq, ®addr, &bit, NVIC_CLRENA_OFFSET) == 0) + { + /* Modify the appropriate bit in the register to disable the interrupt. + * For normal interrupts, we need to set the bit in the associated + * Interrupt Clear Enable register. For other exceptions, we need to + * clear the bit in the System Handler Control and State Register. + */ + + if (irq >= NRF91_IRQ_EXTINT) + { + putreg32(bit, regaddr); + } + else + { + regval = getreg32(regaddr); + regval &= ~bit; + putreg32(regval, regaddr); + } + } + + nrf91_dumpnvic("disable", irq); +} + +/**************************************************************************** + * Name: up_enable_irq + * + * Description: + * Enable the IRQ specified by 'irq' + * + ****************************************************************************/ + +void up_enable_irq(int irq) +{ + uintptr_t regaddr; + uint32_t regval; + uint32_t bit; + + if (nrf91_irqinfo(irq, ®addr, &bit, NVIC_ENA_OFFSET) == 0) + { + /* Modify the appropriate bit in the register to enable the interrupt. + * For normal interrupts, we need to set the bit in the associated + * Interrupt Set Enable register. For other exceptions, we need to + * set the bit in the System Handler Control and State Register. + */ + + if (irq >= NRF91_IRQ_EXTINT) + { + putreg32(bit, regaddr); + } + else + { + regval = getreg32(regaddr); + regval |= bit; + putreg32(regval, regaddr); + } + } + + nrf91_dumpnvic("enable", irq); +} + +/**************************************************************************** + * Name: arm_ack_irq + * + * Description: + * Acknowledge the IRQ + * + ****************************************************************************/ + +void arm_ack_irq(int irq) +{ + nrf91_clrpend(irq); +} + +/**************************************************************************** + * Name: up_prioritize_irq + * + * Description: + * Set the priority of an IRQ. + * + * Since this API is not supported on all architectures, it should be + * avoided in common implementations where possible. + * + ****************************************************************************/ + +#ifdef CONFIG_ARCH_IRQPRIO +int up_prioritize_irq(int irq, int priority) +{ + uint32_t regaddr; + uint32_t regval; + int shift; + + DEBUGASSERT(irq >= NRF91_IRQ_MEMFAULT && irq < NR_IRQS && + (unsigned)priority <= NVIC_SYSH_PRIORITY_MIN); + + if (irq < NRF91_IRQ_EXTINT) + { + /* NVIC_SYSH_PRIORITY() maps {0..15} to one of three priority + * registers (0-3 are invalid) + */ + + regaddr = NVIC_SYSH_PRIORITY(irq); + irq -= 4; + } + else + { + /* NVIC_IRQ_PRIORITY() maps {0..} to one of many priority registers */ + + irq -= NRF91_IRQ_EXTINT; + regaddr = NVIC_IRQ_PRIORITY(irq); + } + + regval = getreg32(regaddr); + shift = ((irq & 3) << 3); + regval &= ~(0xff << shift); + regval |= (priority << shift); + putreg32(regval, regaddr); + + nrf91_dumpnvic("prioritize", irq); + return OK; +} +#endif diff --git a/arch/arm/src/nrf91/nrf91_irq.h b/arch/arm/src/nrf91/nrf91_irq.h new file mode 100644 index 0000000000..b40d860411 --- /dev/null +++ b/arch/arm/src/nrf91/nrf91_irq.h @@ -0,0 +1,45 @@ +/**************************************************************************** + * arch/arm/src/nrf91/nrf91_irq.h + * + * 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. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_NRF91_NRF91_IRQ_H +#define __ARCH_ARM_SRC_NRF91_NRF91_IRQ_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: nrf91_clrpend + * + * Description: + * Clear a pending interrupt at the NVIC. This does not seem to be + * required for most interrupts. + * + ****************************************************************************/ + +void nrf91_clrpend(int irq); + +#endif /* __ARCH_ARM_SRC_NRF91_NRF91_IRQ_H */ diff --git a/arch/arm/src/nrf91/nrf91_lowputc.c b/arch/arm/src/nrf91/nrf91_lowputc.c new file mode 100644 index 0000000000..2fbf42e8d9 --- /dev/null +++ b/arch/arm/src/nrf91/nrf91_lowputc.c @@ -0,0 +1,443 @@ +/**************************************************************************** + * arch/arm/src/nrf91/nrf91_lowputc.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 "arm_internal.h" +#include "hardware/nrf91_memorymap.h" +#include "hardware/nrf91_uarte.h" + +#include "nrf91_config.h" +#include "nrf91_clockconfig.h" +#include "nrf91_gpio.h" +#include "nrf91_lowputc.h" + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifdef HAVE_UART_CONSOLE + +#ifdef CONFIG_UART0_SERIAL_CONSOLE +# define CONSOLE_BASE NRF91_UART0_BASE +# define CONSOLE_BAUD CONFIG_UART0_BAUD +# define CONSOLE_BITS CONFIG_UART0_BITS +# define CONSOLE_PARITY CONFIG_UART0_PARITY +# define CONSOLE_2STOP CONFIG_UART0_2STOP +# define CONSOLE_TX_PIN BOARD_UART0_TX_PIN +# define CONSOLE_RX_PIN BOARD_UART0_RX_PIN +#elif CONFIG_UART1_SERIAL_CONSOLE +# define CONSOLE_BASE NRF91_UART1_BASE +# define CONSOLE_BAUD CONFIG_UART1_BAUD +# define CONSOLE_BITS CONFIG_UART1_BITS +# define CONSOLE_PARITY CONFIG_UART1_PARITY +# define CONSOLE_2STOP CONFIG_UART1_2STOP +# define CONSOLE_TX_PIN BOARD_UART1_TX_PIN +# define CONSOLE_RX_PIN BOARD_UART1_RX_PIN +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* UART console configuration */ + +static const struct uart_config_s g_console_config = +{ + .baud = CONSOLE_BAUD, + .parity = CONSOLE_PARITY, + .bits = CONSOLE_BITS, + .stopbits2 = CONSOLE_2STOP, + .txpin = CONSOLE_TX_PIN, + .rxpin = CONSOLE_RX_PIN, +}; +#endif /* HAVE_UART_CONSOLE */ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nrf91_setbaud + * + * Description: + * Configure the UART BAUD. + * + ****************************************************************************/ + +#ifdef HAVE_UART_DEVICE +static void nrf91_setbaud(uintptr_t base, const struct uart_config_s *config) +{ + uint32_t br = 0; + + switch (config->baud) + { + case 1200: + { + br = UART_BAUDRATE_1200; + break; + } + + case 2400: + { + br = UART_BAUDRATE_2400; + break; + } + + case 4800: + { + br = UART_BAUDRATE_4800; + break; + } + + case 9600: + { + br = UART_BAUDRATE_9600; + break; + } + + case 14400: + { + br = UART_BAUDRATE_14400; + break; + } + + case 19200: + { + br = UART_BAUDRATE_19200; + break; + } + + case 28800: + { + br = UART_BAUDRATE_28800; + break; + } + +#ifdef UART_BAUDRATE_31250 + case 31250: + { + br = UART_BAUDRATE_31250; + break; + } +#endif + + case 38400: + { + br = UART_BAUDRATE_38400; + break; + } + +#ifdef UART_BAUDRATE_56000 + case 56000: + { + br = UART_BAUDRATE_56000; + break; + } +#endif + + case 57600: + { + br = UART_BAUDRATE_57600; + break; + } + + case 76000: + { + br = UART_BAUDRATE_76000; + break; + } + + case 115200: + { + br = UART_BAUDRATE_115200; + break; + } + + case 230400: + { + br = UART_BAUDRATE_230400; + break; + } + + case 250000: + { + br = UART_BAUDRATE_250000; + break; + } + + case 460800: + { + br = UART_BAUDRATE_460800; + break; + } + + case 921600: + { + br = UART_BAUDRATE_921600; + break; + } + + default: + { + DEBUGPANIC(); + break; + } + } + + putreg32(br, base + NRF91_UART_BAUDRATE_OFFSET); +} + +/**************************************************************************** + * Name: nrf91_setparity + ****************************************************************************/ + +static void nrf91_setparity(uintptr_t base, + const struct uart_config_s *config) +{ + uint32_t regval = 0; + + regval = getreg32(base + NRF91_UART_CONFIG_OFFSET); + + if (config->parity == 2) + { + /* Include even parity */ + + regval |= UART_CONFIG_PARITY; + } + else + { + /* Exclude parity */ + + regval &= ~UART_CONFIG_PARITY; + } + + putreg32(regval, base + NRF91_UART_CONFIG_OFFSET); +} + +/**************************************************************************** + * Name: nrf91_setstops + ****************************************************************************/ + +#ifdef HAVE_UART_STOPBITS +static void nrf91_setstops(uintptr_t base, + const struct uart_config_s *config) +{ + uint32_t regval = 0; + + regval = getreg32(base + NRF91_UART_CONFIG_OFFSET); + + if (config->stopbits2 == true) + { + regval |= UART_CONFIG_STOP; + } + else + { + regval &= ~UART_CONFIG_STOP; + } + + putreg32(regval, base + NRF91_UART_CONFIG_OFFSET); +} +#endif + +/**************************************************************************** + * Name: nrf91_sethwflow + ****************************************************************************/ + +static void nrf91_sethwflow(uintptr_t base, + const struct uart_config_s *config) +{ + /* TODO */ +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nrf91_lowsetup + * + * Description: + * Called at the very beginning of _start. Performs low level + * initialization including setup of the console UART. + * This UART initialization is done early so that the serial console is + * available for debugging very early in the boot sequence. + * + ****************************************************************************/ + +void nrf91_lowsetup(void) +{ +#ifdef HAVE_UART_DEVICE +#ifdef HAVE_UART_CONSOLE + /* Configure the console UART (if any) */ + + nrf91_usart_configure(CONSOLE_BASE, &g_console_config); + +#endif /* HAVE_UART_CONSOLE */ +#endif /* HAVE_UART_DEVICE */ +} + +/**************************************************************************** + * Name: nrf91_usart_configure + * + * Description: + * Configure a UART for non-interrupt driven operation + * + ****************************************************************************/ + +#ifdef HAVE_UART_DEVICE +void nrf91_usart_configure(uintptr_t base, + const struct uart_config_s *config) +{ + uint32_t pin = 0; + uint32_t port = 0; + uint32_t regval = 0; + + putreg32(1, base + NRF91_UART_TASKS_STOPRX_OFFSET); + putreg32(1, base + NRF91_UART_TASKS_STOPTX_OFFSET); + putreg32(NRF91_UART_ENABLE_DISABLE, base + NRF91_UART_ENABLE_OFFSET); + + /* Set UART format */ + + nrf91_usart_setformat(base, config); + + /* Config GPIO pins for uart */ + + nrf91_gpio_config(config->txpin); + nrf91_gpio_config(config->rxpin); + + /* Setect TX pins for UART */ + + pin = GPIO_PIN_DECODE(config->txpin); + port = GPIO_PORT_DECODE(config->txpin); + + regval = (pin << UART_PSELTXD_PIN_SHIFT); + regval |= (port << UART_PSELTXD_PORT_SHIFT); + putreg32(regval, base + NRF91_UART_PSELTXD_OFFSET); + + /* Setect RX pins for UART */ + + pin = GPIO_PIN_DECODE(config->rxpin); + port = GPIO_PORT_DECODE(config->rxpin); + + regval = (pin << UART_PSELRXD_PIN_SHIFT); + regval |= (port << UART_PSELRXD_PORT_SHIFT); + putreg32(regval, base + NRF91_UART_PSELRXD_OFFSET); + + /* Enable UART */ + + putreg32(NRF91_UART_ENABLE_ENABLE, base + NRF91_UART_ENABLE_OFFSET); +} + +/**************************************************************************** + * Name: nrf91_usart_disable + * + * Description: + * Disable a UART. it will be necessary to again call + * nrf91_usart_configure() in order to use this UART channel again. + * + ****************************************************************************/ + +void nrf91_usart_disable(uintptr_t base, const struct uart_config_s *config) +{ + /* Disable interrupts */ + + /* Disable the UART */ + + putreg32(1, base + NRF91_UART_TASKS_STOPRX_OFFSET); + putreg32(1, base + NRF91_UART_TASKS_STOPTX_OFFSET); + putreg32(NRF91_UART_ENABLE_DISABLE, base + NRF91_UART_ENABLE_OFFSET); + + putreg32(0xffffffff, base + NRF91_UART_PSELTXD_OFFSET); + putreg32(0xffffffff, base + NRF91_UART_PSELRXD_OFFSET); + + /* Unconfigure GPIO */ + + nrf91_gpio_unconfig(config->rxpin); + nrf91_gpio_unconfig(config->txpin); + + /* Deatach TWI from GPIO */ + + putreg32(UART_PSELTXD_RESET, base + NRF91_UART_PSELTXD_OFFSET); + putreg32(UART_PSELRXD_RESET, base + NRF91_UART_PSELRXD_OFFSET); +} + +/**************************************************************************** + * Name: nrf91_usart_setformat + * + * Description: + * Set the USART line format and speed. + * + ****************************************************************************/ + +void nrf91_usart_setformat(uintptr_t base, + const struct uart_config_s *config) +{ + /* Configure baud */ + + nrf91_setbaud(base, config); + + /* Configure polarity */ + + nrf91_setparity(base, config); + +#ifdef HAVE_UART_STOPBITS + /* Configure STOP bits */ + + nrf91_setstops(base, config); +#endif + + /* Configure hardware flow control */ + + nrf91_sethwflow(base, config); +} +#endif + +/**************************************************************************** + * Name: arm_lowputc + * + * Description: + * Output one byte on the serial console + * + ****************************************************************************/ + +void arm_lowputc(char ch) +{ +#ifdef HAVE_UART_CONSOLE + putreg32(1, CONSOLE_BASE + NRF91_UART_TASKS_STARTTX_OFFSET); + putreg32(0, CONSOLE_BASE + NRF91_UART_EVENTS_TXDRDY_OFFSET); + putreg32(ch, CONSOLE_BASE + NRF91_UART_TXD_OFFSET); + while (getreg32(CONSOLE_BASE + NRF91_UART_EVENTS_TXDRDY_OFFSET) == 0) + { + } + + putreg32(1, CONSOLE_BASE + NRF91_UART_TASKS_STOPTX_OFFSET); +#endif +} diff --git a/arch/arm/src/nrf91/nrf91_lowputc.h b/arch/arm/src/nrf91/nrf91_lowputc.h new file mode 100644 index 0000000000..69e654f1ea --- /dev/null +++ b/arch/arm/src/nrf91/nrf91_lowputc.h @@ -0,0 +1,117 @@ +/**************************************************************************** + * arch/arm/src/nrf91/nrf91_lowputc.h + * + * 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. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_NRF91_NRF91_LOWPUTC_H +#define __ARCH_ARM_SRC_NRF91_NRF91_LOWPUTC_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include "nrf91_gpio.h" +#include "nrf91_config.h" + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +#ifdef HAVE_UART_DEVICE +/* This structure describes the configuration of an UART */ + +struct uart_config_s +{ + uint32_t baud; /* Configured baud */ + uint8_t parity; /* 0=none, 1=odd, 2=even */ + uint8_t bits; /* Number of bits (5-9) */ + bool stopbits2; /* Configure with 2 stop bits instead of 1 */ +#ifdef CONFIG_SERIAL_IFLOWCONTROL + bool iflow; /* Input flow control supported */ +#endif +#ifdef CONFIG_SERIAL_OFLOWCONTROL + bool oflow; /* Output flow control supported. */ +#endif + nrf91_pinset_t txpin; /* TX pin */ + nrf91_pinset_t rxpin; /* RX pin */ +}; +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: nrf91_lowsetup + * + * Description: + * Called at the very beginning of _start. Performs low level + * initialization including setup of the console UART. This UART + * initialization is done early so that the serial console is available + * for debugging very early in the boot sequence. + * + ****************************************************************************/ + +void nrf91_lowsetup(void); + +/**************************************************************************** + * Name: nrf91_usart_configure + * + * Description: + * Configure a UART for non-interrupt driven operation + * + ****************************************************************************/ + +#ifdef HAVE_UART_DEVICE +void nrf91_usart_configure(uintptr_t base, + const struct uart_config_s *config); +#endif + +/**************************************************************************** + * Name: nrf91_usart_disable + * + * Description: + * Disable a UART. it will be necessary to again call + * nrf91_usart_configure() in order to use this UART channel again. + * + ****************************************************************************/ + +#ifdef HAVE_UART_DEVICE +void nrf91_usart_disable(uintptr_t base, + const struct uart_config_s *config); +#endif + +/**************************************************************************** + * Name: nrf91_usart_setformat + * + * Description: + * Set the USART line format and speed. + * + ****************************************************************************/ + +#ifdef HAVE_UART_DEVICE +void nrf91_usart_setformat(uintptr_t base, + const struct uart_config_s *config); +#endif + +#endif /* __ARCH_ARM_SRC_NRF91_NRF91_LOWPUTC_H */ diff --git a/arch/arm/src/nrf91/nrf91_modem.c b/arch/arm/src/nrf91/nrf91_modem.c new file mode 100644 index 0000000000..8605c5b2a0 --- /dev/null +++ b/arch/arm/src/nrf91/nrf91_modem.c @@ -0,0 +1,95 @@ +/**************************************************************************** + * arch/arm/src/nrf91/nrf91_modem.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 "chip.h" + +#include "nrf_modem.h" + +#include "nrf91_modem.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef CONFIG_ARCH_TRUSTZONE_NONSECURE +# error NRF91 modem works only in non-secure environment +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nrf91_modem_fault_handler + ****************************************************************************/ + +static void nrf91_modem_fault_handler(struct nrf_modem_fault_info *info) +{ + nerr("Modem hard fault"); + ASSERT(0); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nrf91_modem_initialize + ****************************************************************************/ + +int nrf91_modem_initialize(void) +{ + struct nrf_modem_init_params init_params; + int ret = OK; + + /* Modem parameters */ + + init_params.shmem.ctrl.base = NRF91_SHMEM_CTRL_BASE; + init_params.shmem.ctrl.size = NRF91_SHMEM_CTRL_SIZE; + init_params.shmem.tx.base = NRF91_SHMEM_TX_BASE; + init_params.shmem.tx.size = NRF91_SHMEM_TX_SIZE; + init_params.shmem.rx.base = NRF91_SHMEM_RX_BASE; + init_params.shmem.rx.size = NRF91_SHMEM_RX_SIZE; + init_params.shmem.trace.base = NRF91_SHMEM_TRACE_BASE; + init_params.shmem.trace.size = NRF91_SHMEM_TRACE_SIZE; + init_params.ipc_irq_prio = NVIC_SYSH_PRIORITY_DEFAULT; + init_params.fault_handler = nrf91_modem_fault_handler; + + /* Initialize modem */ + + ret = nrf_modem_init(&init_params); + if (ret < 0) + { + nerr("nrf_modem_init failed %d\n", ret); + } + + return ret; +} diff --git a/arch/arm/src/nrf91/nrf91_modem.h b/arch/arm/src/nrf91/nrf91_modem.h new file mode 100644 index 0000000000..dcd8b40439 --- /dev/null +++ b/arch/arm/src/nrf91/nrf91_modem.h @@ -0,0 +1,74 @@ +/**************************************************************************** + * arch/arm/src/nrf91/nrf91_modem.h + * + * 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 + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Constant from nrf_modem */ + +#define NRF91_SHMEM_CTRL_SIZE (0x4e8) + +/* Shared memory configuration */ + +#define NRF91_SHMEM_START_ADDR (0x20000000) +#define NRF91_SHMEM_CTRL_BASE (NRF91_SHMEM_START_ADDR) +#define NRF91_SHMEM_TX_BASE (NRF91_SHMEM_CTRL_BASE+NRF91_SHMEM_CTRL_SIZE) +#define NRF91_SHMEM_TX_SIZE (CONFIG_NRF91_MODEM_SHMEM_TX_SIZE) +#define NRF91_SHMEM_RX_BASE (NRF91_SHMEM_TX_BASE+NRF91_SHMEM_TX_SIZE) +#define NRF91_SHMEM_RX_SIZE (CONFIG_NRF91_MODEM_SHMEM_RX_SIZE) +#define NRF91_SHMEM_TRACE_BASE (NRF91_SHMEM_RX_BASE+NRF91_SHMEM_RX_SIZE) +#define NRF91_SHMEM_TRACE_SIZE (CONFIG_NRF91_MODEM_SHMEM_TRACE_SIZE) + +#if !(NRF91_SHMEM_CTRL_BASE % 4 == 0) +# error SHMEM base addres must be word-aligned (4 bytes) +#endif + +#if !(NRF91_SHMEM_TX_BASE % 4 == 0) +# error SHMEM base addres must be word-aligned (4 bytes) +#endif + +#if !(NRF91_SHMEM_RX_BASE % 4 == 0) +# error SHMEM base addres must be word-aligned (4 bytes) +#endif + +#if !(NRF91_SHMEM_TRACE_BASE % 4 == 0) +# error SHMEM base addres must be word-aligned (4 bytes) +#endif + +#ifdef CONFIG_ARCH_FPU +# error missing FPU configuration - FPU must be activated in SPE and NSPE +#endif + +/**************************************************************************** + * Public Functions Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: nrf91_modem_initialize + ****************************************************************************/ + +int nrf91_modem_initialize(void); diff --git a/arch/arm/src/nrf91/nrf91_modem_at.c b/arch/arm/src/nrf91/nrf91_modem_at.c new file mode 100644 index 0000000000..917b7644c3 --- /dev/null +++ b/arch/arm/src/nrf91/nrf91_modem_at.c @@ -0,0 +1,255 @@ +/**************************************************************************** + * arch/arm/src/nrf91/nrf91_modem_at.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 "nrf_modem_at.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define NRF91_MODEM_AT_RX 255 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct nrf91_modem_at_s +{ + char rxbuf[NRF91_MODEM_AT_RX]; + size_t rx_i; + sem_t rx_sem; + mutex_t lock; +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static void nrf91_modem_at_notify_handler(const char *notif); +static void nrf91_modem_at_resp_handler(const char *resp); +static ssize_t nrf91_modem_at_read(struct file *filep, char *buffer, + size_t buflen); +static ssize_t nrf91_modem_at_write(struct file *filep, const char *buffer, + size_t buflen); +static int nrf91_modem_at_ioctl(struct file *filep, int cmd, + unsigned long arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct file_operations g_nrf91_modem_at_fops = +{ + NULL, /* open */ + NULL, /* close */ + nrf91_modem_at_read, /* read */ + nrf91_modem_at_write, /* write */ + NULL, /* seek */ + nrf91_modem_at_ioctl, /* ioctl */ + NULL, /* mmap */ + NULL, /* truncate */ + NULL /* poll */ +}; + +static struct nrf91_modem_at_s g_nrf91_modem_at; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nrf91_modem_at_notify_handler + ****************************************************************************/ + +static void nrf91_modem_at_notify_handler(const char *notif) +{ + struct nrf91_modem_at_s *dev = &g_nrf91_modem_at; + + /* Copy notify */ + + strncpy(&dev->rxbuf[dev->rx_i], notif, NRF91_MODEM_AT_RX - dev->rx_i); + dev->rx_i += strlen(notif); + + /* Wake-up any thread waiting in recv */ + + nxsem_post(&dev->rx_sem); +} + +/**************************************************************************** + * Name: nrf91_modem_at_resp_handler + ****************************************************************************/ + +static void nrf91_modem_at_resp_handler(const char *resp) +{ + struct nrf91_modem_at_s *dev = &g_nrf91_modem_at; + + /* Copy response */ + + strncpy(&dev->rxbuf[dev->rx_i], resp, NRF91_MODEM_AT_RX - dev->rx_i); + dev->rx_i += strlen(resp); + + /* Wake-up any thread waiting in recv */ + + nxsem_post(&dev->rx_sem); +} + +/**************************************************************************** + * Name: nrf91_modem_at_read + ****************************************************************************/ + +static ssize_t nrf91_modem_at_read(struct file *filep, char *buffer, + size_t len) +{ + struct nrf91_modem_at_s *dev = NULL; + struct inode *inode = NULL; + int ret = 0; + + DEBUGASSERT(filep); + inode = filep->f_inode; + + DEBUGASSERT(inode && inode->i_private); + dev = (struct nrf91_modem_at_s *)inode->i_private; + + ret = nxmutex_lock(&dev->lock); + if (ret < 0) + { + return ret; + } + + if ((filep->f_oflags & O_NONBLOCK) != 0) + { + nxsem_trywait(&dev->rx_sem); + ret = 0; + } + else + { + ret = nxsem_wait(&dev->rx_sem); + } + + if (ret < 0) + { + return ret; + } + + /* Get response data */ + + if (len > dev->rx_i) + { + len = dev->rx_i; + } + + strncpy(buffer, dev->rxbuf, len); + dev->rx_i = 0; + ret = len; + + nxmutex_unlock(&dev->lock); + return ret; +} + +/**************************************************************************** + * Name: nrf91_modem_at_write + ****************************************************************************/ + +static ssize_t nrf91_modem_at_write(struct file *filep, const char *buffer, + size_t len) +{ + struct nrf91_modem_at_s *dev = NULL; + struct inode *inode = NULL; + int ret = 0; + + DEBUGASSERT(filep); + inode = filep->f_inode; + + DEBUGASSERT(inode && inode->i_private); + dev = (struct nrf91_modem_at_s *)inode->i_private; + + ret = nxmutex_lock(&dev->lock); + if (ret < 0) + { + return ret; + } + + /* Send AT command */ + + ret = nrf_modem_at_cmd_async(nrf91_modem_at_resp_handler, buffer); + + nxmutex_unlock(&dev->lock); + return ret; +} + +/**************************************************************************** + * Name: nrf91_modem_at_ioct + ****************************************************************************/ + +static int nrf91_modem_at_ioctl(struct file *filep, int cmd, + unsigned long arg) +{ + return -ENOTTY; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nrf91_at_register + ****************************************************************************/ + +int nrf91_at_register(const char *path) +{ + struct nrf91_modem_at_s *dev = &g_nrf91_modem_at; + int ret = OK; + + /* Initialize mutex & sem */ + + memset(&g_nrf91_modem_at, 0, sizeof(struct nrf91_modem_at_s)); + + nxmutex_init(&dev->lock); + nxsem_init(&dev->rx_sem, 0, 0); + + /* Initialize AT modem */ + + nrf_modem_at_notif_handler_set(nrf91_modem_at_notify_handler); + nrf_modem_at_cmd_custom_set(NULL, 0); + + /* Register driver */ + + ret = register_driver(path, &g_nrf91_modem_at_fops, 0666, dev); + if (ret < 0) + { + nerr("ERROR: register_driver failed: %d\n", ret); + } + + return ret; +} diff --git a/arch/arm/src/nrf91/nrf91_modem_at.h b/arch/arm/src/nrf91/nrf91_modem_at.h new file mode 100644 index 0000000000..bdcd574e29 --- /dev/null +++ b/arch/arm/src/nrf91/nrf91_modem_at.h @@ -0,0 +1,35 @@ +/**************************************************************************** + * arch/arm/src/nrf91/nrf91_modem_at.h + * + * 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 + +/**************************************************************************** + * Public Functions Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: nrf91_at_register + ****************************************************************************/ + +int nrf91_at_register(const char *path); diff --git a/arch/arm/src/nrf91/nrf91_modem_os.c b/arch/arm/src/nrf91/nrf91_modem_os.c new file mode 100644 index 0000000000..75a9d41bc5 --- /dev/null +++ b/arch/arm/src/nrf91/nrf91_modem_os.c @@ -0,0 +1,515 @@ +/**************************************************************************** + * arch/arm/src/nrf91/nrf91_modem_os.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 "nrf_modem.h" +#include "nrf_modem_os.h" + +#include "nrf91_modem.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define NRF_ESHUTDOWN 110 + +#define NRF91_MODEM_WAITING_PREALLOC (32) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct nrf91_modem_os_waiting_s +{ + sem_t sem; + uint32_t context; + bool waiting; + struct timespec ts_start; +}; + +struct nrf91_modem_os_s +{ + sem_t sem[NRF_MODEM_OS_NUM_SEM_REQUIRED]; + uint8_t sem_cntr; + struct nrf91_modem_os_waiting_s waiting[NRF91_MODEM_WAITING_PREALLOC]; +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct nrf91_modem_os_s g_nrf91_modem_os; +static struct mm_heap_s *g_shmtxheap = NULL; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nrf_waiting_get + ****************************************************************************/ + +struct nrf91_modem_os_waiting_s *nrf_waiting_get(void) +{ + struct nrf91_modem_os_waiting_s *ret = NULL; + int i = 0; + + for (i = 0; i < NRF91_MODEM_WAITING_PREALLOC; i++) + { + if (g_nrf91_modem_os.waiting[i].waiting == false) + { + ret = &g_nrf91_modem_os.waiting[i]; + nxsem_init(&ret->sem, 0, 0); + break; + } + } + + return ret; +} + +/**************************************************************************** + * Name: nrf_waiting_free + ****************************************************************************/ + +void nrf_waiting_free(struct nrf91_modem_os_waiting_s *w) +{ + sem_destroy(&w->sem); + w->context = 0; + w->waiting = false; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nrf_modem_os_init + * + * Description: + * Initialize the glue layer. + * + ****************************************************************************/ + +void nrf_modem_os_init(void) +{ + memset(&g_nrf91_modem_os, 0, sizeof(struct nrf91_modem_os_s)); + + /* Initialize shared memory TX heap */ + + g_shmtxheap = mm_initialize("shmtx", + (void *) NRF91_SHMEM_TX_BASE, + NRF91_SHMEM_TX_SIZE); +} + +/**************************************************************************** + * Name: nrf_modem_os_shutdown + * + * Description: + * Deinitialize the glue layer. + * + * When shutdown is called, all pending calls to @c nrf_modem_os_timedwait + * shall exit and return -NRF_ESHUTDOWN. + * + ****************************************************************************/ + +void nrf_modem_os_shutdown(void) +{ + struct nrf91_modem_os_waiting_s *waiting = NULL; + int i = 0; + + /* Wake up all waiting semaphores */ + + for (i = 0; i < NRF91_MODEM_WAITING_PREALLOC; i++) + { + waiting = &g_nrf91_modem_os.waiting[i]; + if (waiting->waiting == true) + { + sem_post(&waiting->sem); + } + } + + /* Uninitialize shared memory TX heap */ + + mm_uninitialize(g_shmtxheap); +} + +/**************************************************************************** + * Name: nrf_modem_os_shm_tx_alloc + * + * Description: + * Allocate a buffer on the TX area of shared memory. + * + ****************************************************************************/ + +void *nrf_modem_os_shm_tx_alloc(size_t bytes) +{ + return mm_malloc(g_shmtxheap, bytes); +} + +/**************************************************************************** + * Name: nrf_modem_os_shm_tx_free + * + * Description: + * Free a shared memory buffer in the TX area. + * + ****************************************************************************/ + +void nrf_modem_os_shm_tx_free(void *mem) +{ + return mm_free(g_shmtxheap, mem); +} + +/**************************************************************************** + * Name: nrf_modem_os_alloc + * + * Description: + * Allocate a buffer on the library heap. + * + ****************************************************************************/ + +void *nrf_modem_os_alloc(size_t bytes) +{ + return malloc(bytes); +} + +/**************************************************************************** + * Name: nrf_modem_os_free + * + * Description: + * Free a memory buffer in the library heap. + * + ****************************************************************************/ + +void nrf_modem_os_free(void *mem) +{ + free(mem); +} + +/**************************************************************************** + * Name: nrf_modem_os_busywait + * + * Description: + * Busy wait. + * + ****************************************************************************/ + +void nrf_modem_os_busywait(int32_t usec) +{ + up_udelay(usec); +} + +/**************************************************************************** + * Name: nrf_modem_os_timedwait + * + * Description: + * Put a thread to sleep for a specific time or until an event occurs. + * + ****************************************************************************/ + +int32_t nrf_modem_os_timedwait(uint32_t context, int32_t *timeout) +{ + struct nrf91_modem_os_waiting_s *waiting = NULL; + struct timespec ts_now; + struct timespec abstime; + int32_t remaining = 0; + int32_t diff = 0; + int ret = OK; + + /* Modem is not initialized or was shut down */ + + if (!nrf_modem_is_initialized()) + { + ret = -NRF_ESHUTDOWN; + goto errout; + } + + if (*timeout == 0) + { + ret = -EAGAIN; + goto errout; + } + + /* Get free waiting slot */ + + waiting = nrf_waiting_get(); + if (waiting == NULL) + { + ret = -ENOMEM; + goto errout; + } + + waiting->context = context; + waiting->waiting = true; + clock_systime_timespec(&waiting->ts_start); + + if (*timeout < 0) + { + /* Wait for event */ + + sem_wait(&waiting->sem); + ret = OK; + goto errout; + } + else + { + /* Wait for event or timeout */ + + abstime.tv_sec = *timeout / 1000; + abstime.tv_nsec = (*timeout % 1000) * 1000000; + + sem_timedwait(&waiting->sem, &abstime); + } + + /* Free a waiting slot */ + + nrf_waiting_free(waiting); + + /* Modem is not initialized or was shut down */ + + if (!nrf_modem_is_initialized()) + { + ret = -NRF_ESHUTDOWN; + goto errout; + } + + clock_systime_timespec(&ts_now); + + diff = ((ts_now.tv_sec - waiting->ts_start.tv_sec) * 1000 + + (ts_now.tv_nsec - waiting->ts_start.tv_nsec) / 1000000); + + remaining = *timeout - diff; + + /* Return remaining timeout */ + + *timeout = (remaining > 0) ? remaining : 0; + + if (*timeout == 0) + { + ret = -EAGAIN; + } + +errout: + return ret; +} + +/**************************************************************************** + * Name: nrf_modem_os_event_notify + * + * Description: + * Notify the application that an event has occurred. + * + ****************************************************************************/ + +void nrf_modem_os_event_notify(uint32_t context) +{ + struct nrf91_modem_os_waiting_s *waiting = NULL; + int i = 0; + + for (i = 0; i < NRF91_MODEM_WAITING_PREALLOC; i++) + { + waiting = &g_nrf91_modem_os.waiting[i]; + if (waiting->waiting == true) + { + if (waiting->context == context || context == 0) + { + sem_post(&waiting->sem); + } + } + } +} + +/**************************************************************************** + * Name: nrf_modem_os_sleep + * + * Description: + * Put a thread to sleep for a specific amount of time. + * + ****************************************************************************/ + +int nrf_modem_os_sleep(uint32_t timeout) +{ + /* Timeout in ms */ + + usleep(timeout * 1000); + return OK; +} + +/**************************************************************************** + * Name: nrf_modem_os_errno_set + * + * Description: + * Set errno. + * + ****************************************************************************/ + +void nrf_modem_os_errno_set(int errno_val) +{ + set_errno(errno_val); +} + +/**************************************************************************** + * Name: nrf_modem_os_is_in_isr + * + * Description: + * Check if executing in interrupt context. + * + ****************************************************************************/ + +bool nrf_modem_os_is_in_isr(void) +{ + return up_interrupt_context(); +} + +/**************************************************************************** + * Name: nrf_modem_os_sem_init + * + * Description: + * Initialize a semaphore. + * + ****************************************************************************/ + +int nrf_modem_os_sem_init(void **sem, unsigned int initial_count, + unsigned int limit) +{ + sem_t *modemsem = &g_nrf91_modem_os.sem[g_nrf91_modem_os.sem_cntr]; + int ret = OK; + + UNUSED(limit); + + DEBUGASSERT(g_nrf91_modem_os.sem_cntr < NRF_MODEM_OS_NUM_SEM_REQUIRED); + ret = sem_init(modemsem, 0, initial_count); + g_nrf91_modem_os.sem_cntr++; + + *sem = (void *)modemsem; + + return ret; +} + +/**************************************************************************** + * Name: nrf_modem_os_sem_give + * + * Description: + * Give a semaphore. + * + ****************************************************************************/ + +void nrf_modem_os_sem_give(void *sem) +{ + sem_post((sem_t *)sem); +} + +/**************************************************************************** + * Name: nrf_modem_os_sem_take + * + * Description: + * Take a semaphore. + * + ****************************************************************************/ + +int nrf_modem_os_sem_take(void *sem, int timeout) +{ + int ret = OK; + sem_t *s = sem; + + if (timeout == -1) + { + ret = sem_wait(s); + } + else + { + struct timespec abstime; + + abstime.tv_sec = timeout / 1000; + abstime.tv_nsec = (timeout % 1000) * 1000000; + + ret = sem_timedwait(s, &abstime); + } + + return ret; +} + +/**************************************************************************** + * Name: nrf_modem_os_sem_count_get + * + * Description: + * Get a semaphore's count. + * + ****************************************************************************/ + +unsigned int nrf_modem_os_sem_count_get(void *sem) +{ + int sval = 0; + + sem_getvalue((sem_t *)sem, &sval); + return sval; +} + +/**************************************************************************** + * Name: nrf_modem_os_log + * + * Description: + * Generic logging procedure. + * + ****************************************************************************/ + +void nrf_modem_os_log(int level, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + syslog(level, fmt, ap); + va_end(ap); +} + +/**************************************************************************** + * Name: nrf_modem_os_logdump + * + * Description: + * Logging procedure for dumping hex representation of object. + * + ****************************************************************************/ + +void nrf_modem_os_logdump(int level, const char *str, const void *data, + size_t len) +{ + syslog(level, "nrf_modem_os_logdump"); + lib_dumpbuffer(str, data, len); +} diff --git a/arch/arm/src/nrf91/nrf91_nrfx_ipc.c b/arch/arm/src/nrf91/nrf91_nrfx_ipc.c new file mode 100644 index 0000000000..b9d3105524 --- /dev/null +++ b/arch/arm/src/nrf91/nrf91_nrfx_ipc.c @@ -0,0 +1,168 @@ +/**************************************************************************** + * arch/arm/src/nrf91/nrf91_nrfx_ipc.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 "arm_internal.h" + +#include "hardware/nrf91_ipc.h" + +#include "nrf91_nrfx_ipc.h" + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static nrfx_ipc_handler_t g_nrfx_ipc_handler = NULL; +static void *g_nrfx_ipc_context = NULL; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nrfx_ipc_irq_handler + ****************************************************************************/ + +static int nrfx_ipc_irq_handler(int irq, void *context, void *arg) +{ + uint32_t regval = 0; + int i = 0; + + regval = getreg32(NRF91_IPC_INTPEND); + + for (i = 0; i < NRF91_IPC_CHANS; i += 1) + { + if (regval & IPC_CHAN_ID(i)) + { + /* Clear EVENT */ + + putreg32(0, NRF91_IPC_EVENTS_RECEIVE(i)); + + /* Handle event */ + + g_nrfx_ipc_handler(i, g_nrfx_ipc_context); + } + } + + return 0; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nrfx_ipc_init + ****************************************************************************/ + +nrfx_err_t nrfx_ipc_init(uint8_t irq_priority, nrfx_ipc_handler_t handler, + void *context) +{ + /* Store arguments */ + + g_nrfx_ipc_handler = handler; + g_nrfx_ipc_context = context; + + /* Attach modem IPC handler and set priority */ + + irq_attach(NRF91_IRQ_IPC, nrfx_ipc_irq_handler, 0); + up_prioritize_irq(NRF91_IRQ_IPC, irq_priority); + +#if 0 + /* IPC interrupts non-secure */ + + up_secure_irq(NRF91_IRQ_IPC, false); +#endif + + /* Enable IPC interrupts */ + + up_enable_irq(NRF91_IRQ_IPC); + + return 0; +} + +/**************************************************************************** + * Name: nrfx_ipc_uninit + ****************************************************************************/ + +void nrfx_ipc_uninit(void) +{ + up_disable_irq(NRF91_IRQ_IPC); +} + +/**************************************************************************** + * Name: nrfx_ipc_config_load + ****************************************************************************/ + +void nrfx_ipc_config_load(const nrfx_ipc_config_t *config) +{ + int i = 0; + + /* Configure send events */ + + for (i = 0; i < IPC_CONF_NUM; i++) + { + putreg32(config->send_task_config[i], + NRF91_IPC_SEND_CNF(i)); + } + + /* Configure receive events */ + + for (i = 0; i < IPC_CONF_NUM; i++) + { + putreg32(config->receive_event_config[i], + NRF91_IPC_RECEIVE_CNF(i)); + } + + /* Enable interrupts for a given channel */ + + putreg32(config->receive_events_enabled, + NRF91_IPC_INTENSET); +} + +/**************************************************************************** + * Name: nrfx_ipc_receive_event_enable + ****************************************************************************/ + +void nrfx_ipc_receive_event_enable(uint8_t event_index) +{ + /* Enable interrupts for a given channel */ + + putreg32(IPC_CHAN_ID(event_index), NRF91_IPC_INTENSET); +} + +/**************************************************************************** + * Name: nrfx_ipc_receive_event_disable + ****************************************************************************/ + +void nrfx_ipc_receive_event_disable(uint8_t event_index) +{ + /* Disable interrupts for a given channel */ + + putreg32(IPC_CHAN_ID(event_index), NRF91_IPC_INTENCLR); +} diff --git a/arch/arm/src/nrf91/nrf91_nrfx_ipc.h b/arch/arm/src/nrf91/nrf91_nrfx_ipc.h new file mode 100644 index 0000000000..f2614676e6 --- /dev/null +++ b/arch/arm/src/nrf91/nrf91_nrfx_ipc.h @@ -0,0 +1,85 @@ +/**************************************************************************** + * arch/arm/src/nrf91/nrf91_nrfx_ipc.h + * + * 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 "hardware/nrf91_memorymap.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define IPC_CONF_NUM (NRF91_IPC_CHANS) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +typedef void (*nrfx_ipc_handler_t)(uint8_t event_idx, void *context); + +typedef struct +{ + uint32_t send_task_config[IPC_CONF_NUM]; + uint32_t receive_event_config[IPC_CONF_NUM]; + uint32_t receive_events_enabled; +} nrfx_ipc_config_t; + +typedef int nrfx_err_t; + +/**************************************************************************** + * Public Functions Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: nrfx_ipc_uninit + ****************************************************************************/ + +void nrfx_ipc_uninit(void); + +/**************************************************************************** + * Name: nrfx_ipc_init + ****************************************************************************/ + +nrfx_err_t nrfx_ipc_init(uint8_t irq_priority, nrfx_ipc_handler_t handler, + void *context); + +/**************************************************************************** + * Name: nrfx_ipc_config_load + ****************************************************************************/ + +void nrfx_ipc_config_load(const nrfx_ipc_config_t *config); + +/**************************************************************************** + * Name: nrfx_ipc_receive_event_enable + ****************************************************************************/ + +void nrfx_ipc_receive_event_enable(uint8_t event_index); + +/**************************************************************************** + * Name: nrfx_ipc_receive_event_disable + ****************************************************************************/ + +void nrfx_ipc_receive_event_disable(uint8_t event_index); diff --git a/arch/arm/src/nrf91/nrf91_rtc.c b/arch/arm/src/nrf91/nrf91_rtc.c new file mode 100644 index 0000000000..ebf82e032b --- /dev/null +++ b/arch/arm/src/nrf91/nrf91_rtc.c @@ -0,0 +1,801 @@ +/**************************************************************************** + * arch/arm/src/nrf91/nrf91_rtc.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 "arm_internal.h" +#include "hardware/nrf91_rtc.h" + +#include "nrf91_rtc.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct nrf91_rtc_priv_s +{ + struct nrf91_rtc_ops_s *ops; + uint32_t base; + uint32_t irq; + uint8_t chan; + bool inuse; +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* RTC registers access *****************************************************/ + +static uint32_t nrf91_rtc_getreg(struct nrf91_rtc_dev_s *dev, + uint32_t offset); +static void nrf91_rtc_putreg(struct nrf91_rtc_dev_s *dev, + uint32_t offset, + uint32_t value); + +/* RTC helpers **************************************************************/ + +static uint32_t nrf91_rtc_irq2reg(struct nrf91_rtc_dev_s *dev, + uint8_t s); +static uint32_t nrf91_rtc_evt2reg(struct nrf91_rtc_dev_s *dev, + uint8_t evt); + +/* RTC operations ***********************************************************/ + +static int nrf91_rtc_start(struct nrf91_rtc_dev_s *dev); +static int nrf91_rtc_stop(struct nrf91_rtc_dev_s *dev); +static int nrf91_rtc_clear(struct nrf91_rtc_dev_s *dev); +static int nrf91_rtc_trgovrflw(struct nrf91_rtc_dev_s *dev); +static int nrf91_rtc_getcounter(struct nrf91_rtc_dev_s *dev, + uint32_t *cc); +static int nrf91_rtc_setcc(struct nrf91_rtc_dev_s *dev, uint8_t i, + uint32_t cc); +static int nrf91_rtc_getcc(struct nrf91_rtc_dev_s *dev, uint8_t i, + uint32_t *cc); +static int nrf91_rtc_setpre(struct nrf91_rtc_dev_s *dev, uint16_t pre); +static int nrf91_rtc_setisr(struct nrf91_rtc_dev_s *dev, xcpt_t handler, + void * arg); +static int nrf91_rtc_enableint(struct nrf91_rtc_dev_s *dev, uint8_t s); +static int nrf91_rtc_disableint(struct nrf91_rtc_dev_s *dev, uint8_t s); +static int nrf91_rtc_checkint(struct nrf91_rtc_dev_s *dev, uint8_t s); +static int nrf91_rtc_ackint(struct nrf91_rtc_dev_s *dev, uint8_t s); +static int nrf91_rtc_enableevt(struct nrf91_rtc_dev_s *dev, uint8_t evt); +static int nrf91_rtc_disableevt(struct nrf91_rtc_dev_s *dev, + uint8_t evt); +static uint32_t nrf91_rtc_getbase(struct nrf91_rtc_dev_s *dev); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* NRF91 RTC ops */ + +struct nrf91_rtc_ops_s nrf91_rtc_ops = +{ + .start = nrf91_rtc_start, + .stop = nrf91_rtc_stop, + .clear = nrf91_rtc_clear, + .trgovrflw = nrf91_rtc_trgovrflw, + .getcounter = nrf91_rtc_getcounter, + .setcc = nrf91_rtc_setcc, + .getcc = nrf91_rtc_getcc, + .setpre = nrf91_rtc_setpre, + .setisr = nrf91_rtc_setisr, + .enableint = nrf91_rtc_enableint, + .disableint = nrf91_rtc_disableint, + .checkint = nrf91_rtc_checkint, + .ackint = nrf91_rtc_ackint, + .enableevt = nrf91_rtc_enableevt, + .disableevt = nrf91_rtc_disableevt, + .getbase = nrf91_rtc_getbase, +}; + +#ifdef CONFIG_NRF91_RTC0 +/* RTC0 */ + +struct nrf91_rtc_priv_s g_nrf91_rtc0_priv = +{ + .ops = &nrf91_rtc_ops, + .base = NRF91_RTC0_BASE, + .irq = NRF91_IRQ_RTC0, + .chan = 4, + .inuse = false, +}; +#endif + +#ifdef CONFIG_NRF91_RTC1 +/* RTC1 */ + +struct nrf91_rtc_priv_s g_nrf91_rtc1_priv = +{ + .ops = &nrf91_rtc_ops, + .base = NRF91_RTC1_BASE, + .irq = NRF91_IRQ_RTC1, + .chan = 4, + .inuse = false, +}; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nrf91_rtc_getreg + * + * Description: + * Get a 32-bit register value by offset + * + ****************************************************************************/ + +static uint32_t nrf91_rtc_getreg(struct nrf91_rtc_dev_s *dev, + uint32_t offset) +{ + DEBUGASSERT(dev); + + return getreg32(((struct nrf91_rtc_priv_s *)dev)->base + offset); +} + +/**************************************************************************** + * Name: nrf91_rtc_putreg + * + * Description: + * Put a 32-bit register value by offset + * + ****************************************************************************/ + +static void nrf91_rtc_putreg(struct nrf91_rtc_dev_s *dev, + uint32_t offset, + uint32_t value) +{ + DEBUGASSERT(dev); + + putreg32(value, ((struct nrf91_rtc_priv_s *)dev)->base + offset); +} + +/**************************************************************************** + * Name: nrf91_rtc_irq2reg + * + * Description: + * Get the value of the interrupt register corresponding to the given + * interrupt source + * + ****************************************************************************/ + +static uint32_t nrf91_rtc_irq2reg(struct nrf91_rtc_dev_s *dev, uint8_t s) +{ + uint32_t regval = 0; + + switch (s) + { + case NRF91_RTC_EVT_TICK: + { + regval = RTC_INT_TICK; + break; + } + + case NRF91_RTC_EVT_OVRFLW: + { + regval = RTC_INT_OVRFLW; + break; + } + + case NRF91_RTC_EVT_COMPARE0: + { + regval = RTC_INT_COMPARE(0); + break; + } + + case NRF91_RTC_EVT_COMPARE1: + { + regval = RTC_INT_COMPARE(1); + break; + } + + case NRF91_RTC_EVT_COMPARE2: + { + regval = RTC_INT_COMPARE(2); + break; + } + + case NRF91_RTC_EVT_COMPARE3: + { + regval = RTC_INT_COMPARE(3); + break; + } + + default: + { + rtcerr("ERROR: unsupported IRQ source %d\n", s); + regval = 0; + goto errout; + } + } + +errout: + return regval; +} + +/**************************************************************************** + * Name: nrf91_rtc_evt2reg + * + * Description: + * Get the offset of the event register corresponding to the given event + * + ****************************************************************************/ + +static uint32_t nrf91_rtc_evt2reg(struct nrf91_rtc_dev_s *dev, + uint8_t evt) +{ + uint32_t regval; + + switch (evt) + { + case NRF91_RTC_EVT_TICK: + { + regval = RTC_EVTEN_TICK; + break; + } + + case NRF91_RTC_EVT_OVRFLW: + { + regval = RTC_EVTEN_OVRFLW; + break; + } + + case NRF91_RTC_EVT_COMPARE0: + { + regval = RTC_EVTEN_COMPARE(0); + break; + } + + case NRF91_RTC_EVT_COMPARE1: + { + regval = RTC_EVTEN_COMPARE(1); + break; + } + + case NRF91_RTC_EVT_COMPARE2: + { + regval = RTC_EVTEN_COMPARE(2); + break; + } + + case NRF91_RTC_EVT_COMPARE3: + { + regval = RTC_EVTEN_COMPARE(3); + break; + } + + default: + { + rtcerr("ERROR: unsupported EVENT %d\n", evt); + regval = 0; + goto errout; + } + } + +errout: + return regval; +} + +/**************************************************************************** + * Name: nrf91_rtc_start + ****************************************************************************/ + +static int nrf91_rtc_start(struct nrf91_rtc_dev_s *dev) +{ + DEBUGASSERT(dev); + + nrf91_rtc_putreg(dev, NRF91_RTC_TASKS_START_OFFSET, RTC_TASKS_START); + + return OK; +} + +/**************************************************************************** + * Name: nrf91_rtc_stop + ****************************************************************************/ + +static int nrf91_rtc_stop(struct nrf91_rtc_dev_s *dev) +{ + DEBUGASSERT(dev); + + nrf91_rtc_putreg(dev, NRF91_RTC_TASKS_STOP_OFFSET, RTC_TASKS_STOP); + + return OK; +} + +/**************************************************************************** + * Name: nrf91_rtc_clear + ****************************************************************************/ + +static int nrf91_rtc_clear(struct nrf91_rtc_dev_s *dev) +{ + DEBUGASSERT(dev); + + nrf91_rtc_putreg(dev, NRF91_RTC_TASKS_CLEAR_OFFSET, RTC_TASKS_CLEAR); + + return OK; +} + +/**************************************************************************** + * Name: nrf91_rtc_trgovrflw + ****************************************************************************/ + +static int nrf91_rtc_trgovrflw(struct nrf91_rtc_dev_s *dev) +{ + DEBUGASSERT(dev); + + nrf91_rtc_putreg(dev, NRF91_RTC_TASKS_TRIGOVRFLW_OFFSET, + RTC_TASKS_TRIGOVRFLW); + + return OK; +} + +static int nrf91_rtc_getcounter(struct nrf91_rtc_dev_s *dev, + uint32_t *ctr) +{ + DEBUGASSERT(dev); + DEBUGASSERT(ctr); + + *ctr = nrf91_rtc_getreg(dev, NRF91_RTC_COUNTER_OFFSET); + + return OK; +} + +/**************************************************************************** + * Name: nrf91_rtc_setcc + ****************************************************************************/ + +static int nrf91_rtc_setcc(struct nrf91_rtc_dev_s *dev, uint8_t i, + uint32_t cc) +{ + struct nrf91_rtc_priv_s *rtc = NULL; + int ret = OK; + + DEBUGASSERT(dev); + + rtc = (struct nrf91_rtc_priv_s *)dev; + + /* Is the channel supported? */ + + if (i > rtc->chan) + { + rtcerr("ERROR: unsupported RTCER channel %d\n", i); + ret = -EINVAL; + goto errout; + } + + nrf91_rtc_putreg(dev, NRF91_RTC_CC_OFFSET(i), cc); + +errout: + return ret; +} + +/**************************************************************************** + * Name: nrf91_rtc_getcc + ****************************************************************************/ + +static int nrf91_rtc_getcc(struct nrf91_rtc_dev_s *dev, uint8_t i, + uint32_t *cc) +{ + struct nrf91_rtc_priv_s *rtc = NULL; + int ret = OK; + + DEBUGASSERT(dev); + DEBUGASSERT(cc); + + rtc = (struct nrf91_rtc_priv_s *)dev; + + /* Is the channel supported? */ + + if (i > rtc->chan) + { + rtcerr("ERROR: unsupported RTCER channel %d\n", i); + ret = -EINVAL; + goto errout; + } + + *cc = nrf91_rtc_getreg(dev, NRF91_RTC_CC_OFFSET(i)); + +errout: + return ret; +} + +/**************************************************************************** + * Name: nrf91_rtc_setpre + ****************************************************************************/ + +static int nrf91_rtc_setpre(struct nrf91_rtc_dev_s *dev, uint16_t pre) +{ + int ret = OK; + + DEBUGASSERT(dev); + + if (pre > RTC_PRESCALER_MAX) + { + rtcerr("ERROR: unsupported RTC prescaler %d\n", pre); + ret = -EINVAL; + goto errout; + } + + nrf91_rtc_putreg(dev, NRF91_RTC_PRESCALER_OFFSET, pre); + +errout: + return ret; +} + +/**************************************************************************** + * Name: nrf91_rtc_setisr + ****************************************************************************/ + +static int nrf91_rtc_setisr(struct nrf91_rtc_dev_s *dev, xcpt_t handler, + void *arg) +{ + struct nrf91_rtc_priv_s *rtc = NULL; + int ret = OK; + + DEBUGASSERT(dev); + + rtc = (struct nrf91_rtc_priv_s *)dev; + + /* Disable interrupt when callback is removed */ + + if (!handler) + { + up_disable_irq(rtc->irq); + irq_detach(rtc->irq); + ret = OK; + goto errout; + } + + /* Otherwise set callback and enable interrupt */ + + irq_attach(rtc->irq, handler, arg); + up_enable_irq(rtc->irq); + +errout: + return ret; +} + +/**************************************************************************** + * Name: nrf91_rtc_enableint + ****************************************************************************/ + +static int nrf91_rtc_enableint(struct nrf91_rtc_dev_s *dev, uint8_t s) +{ + uint32_t regval = 0; + int ret = OK; + + DEBUGASSERT(dev); + + /* Get register value for given interrupt source */ + + regval = nrf91_rtc_irq2reg(dev, s); + if (regval == 0) + { + ret = -EINVAL; + goto errout; + } + + nrf91_rtc_putreg(dev, NRF91_RTC_INTENSET_OFFSET, regval); + +errout: + return ret; +} + +/**************************************************************************** + * Name: nrf91_rtc_disableint + ****************************************************************************/ + +static int nrf91_rtc_disableint(struct nrf91_rtc_dev_s *dev, uint8_t s) +{ + uint32_t regval = 0; + int ret = OK; + + DEBUGASSERT(dev); + + /* Get register value for given interrupt source */ + + regval = nrf91_rtc_irq2reg(dev, s); + if (regval == 0) + { + ret = -EINVAL; + goto errout; + } + + nrf91_rtc_putreg(dev, NRF91_RTC_INTENCLR_OFFSET, regval); + +errout: + return ret; +} + +/**************************************************************************** + * Name: nrf91_rtc_checkint + ****************************************************************************/ + +static int nrf91_rtc_checkint(struct nrf91_rtc_dev_s *dev, uint8_t s) +{ + int ret = 0; + + DEBUGASSERT(dev); + + switch (s) + { + case NRF91_RTC_EVT_TICK: + { + ret = nrf91_rtc_getreg(dev, NRF91_RTC_EVENTS_TICK_OFFSET); + break; + } + + case NRF91_RTC_EVT_OVRFLW: + { + ret = nrf91_rtc_getreg(dev, NRF91_RTC_EVENTS_OVRFLW_OFFSET); + break; + } + + case NRF91_RTC_EVT_COMPARE0: + { + ret = nrf91_rtc_getreg(dev, NRF91_RTC_EVENTS_COMPARE_OFFSET(0)); + break; + } + + case NRF91_RTC_EVT_COMPARE1: + { + ret = nrf91_rtc_getreg(dev, NRF91_RTC_EVENTS_COMPARE_OFFSET(1)); + break; + } + + case NRF91_RTC_EVT_COMPARE2: + { + ret = nrf91_rtc_getreg(dev, NRF91_RTC_EVENTS_COMPARE_OFFSET(2)); + break; + } + + case NRF91_RTC_EVT_COMPARE3: + { + ret = nrf91_rtc_getreg(dev, NRF91_RTC_EVENTS_COMPARE_OFFSET(3)); + break; + } + + default: + { + rtcerr("ERROR: unsupported IRQ source %d\n", s); + ret = -EINVAL; + goto errout; + } + } + +errout: + return ret; +} + +/**************************************************************************** + * Name: nrf91_rtc_ackint + ****************************************************************************/ + +static int nrf91_rtc_ackint(struct nrf91_rtc_dev_s *dev, uint8_t s) +{ + int ret = 0; + + DEBUGASSERT(dev); + + switch (s) + { + case NRF91_RTC_EVT_TICK: + { + nrf91_rtc_putreg(dev, NRF91_RTC_EVENTS_TICK_OFFSET, 0); + break; + } + + case NRF91_RTC_EVT_OVRFLW: + { + nrf91_rtc_putreg(dev, NRF91_RTC_EVENTS_OVRFLW_OFFSET, 0); + break; + } + + case NRF91_RTC_EVT_COMPARE0: + { + nrf91_rtc_putreg(dev, NRF91_RTC_EVENTS_COMPARE_OFFSET(0), 0); + break; + } + + case NRF91_RTC_EVT_COMPARE1: + { + nrf91_rtc_putreg(dev, NRF91_RTC_EVENTS_COMPARE_OFFSET(1), 0); + break; + } + + case NRF91_RTC_EVT_COMPARE2: + { + nrf91_rtc_putreg(dev, NRF91_RTC_EVENTS_COMPARE_OFFSET(2), 0); + break; + } + + case NRF91_RTC_EVT_COMPARE3: + { + nrf91_rtc_putreg(dev, NRF91_RTC_EVENTS_COMPARE_OFFSET(3), 0); + break; + } + + default: + { + rtcerr("ERROR: unsupported IRQ source %d\n", s); + ret = -EINVAL; + goto errout; + } + } + +errout: + return ret; +} + +/**************************************************************************** + * Name: nrf91_rtc_enableevt + ****************************************************************************/ + +static int nrf91_rtc_enableevt(struct nrf91_rtc_dev_s *dev, uint8_t evt) +{ + uint32_t regval = 0; + int ret = OK; + + DEBUGASSERT(dev); + + /* Get register value for given event */ + + regval = nrf91_rtc_evt2reg(dev, evt); + if (regval == 0) + { + ret = -EINVAL; + goto errout; + } + + nrf91_rtc_putreg(dev, NRF91_RTC_EVTENSET_OFFSET, regval); + +errout: + return ret; +} + +/**************************************************************************** + * Name: nrf91_rtc_disableevt + ****************************************************************************/ + +static int nrf91_rtc_disableevt(struct nrf91_rtc_dev_s *dev, uint8_t evt) +{ + uint32_t regval = 0; + int ret = OK; + + DEBUGASSERT(dev); + + /* Get register value for given event */ + + regval = nrf91_rtc_evt2reg(dev, evt); + if (regval == 0) + { + ret = -EINVAL; + goto errout; + } + + nrf91_rtc_putreg(dev, NRF91_RTC_EVTENCLR_OFFSET, regval); + +errout: + return ret; +} + +/**************************************************************************** + * Name: nrf91_rtc_getbase + ****************************************************************************/ + +static uint32_t nrf91_rtc_getbase(struct nrf91_rtc_dev_s *dev) +{ + struct nrf91_rtc_priv_s *rtc = (struct nrf91_rtc_priv_s *)dev; + DEBUGASSERT(dev); + + return rtc->base; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nrf91_rtc_init + * + * Description: + * Initialize RTC device + * + ****************************************************************************/ + +struct nrf91_rtc_dev_s *nrf91_rtc_init(int rtc) +{ + struct nrf91_rtc_priv_s *priv = NULL; + + /* Get RTC instance */ + + switch (rtc) + { +#ifdef CONFIG_NRF91_RTC0 + case 0: + { + priv = &g_nrf91_rtc0_priv; + break; + } +#endif + +#ifdef CONFIG_NRF91_RTC1 + case 1: + { + priv = &g_nrf91_rtc1_priv; + break; + } +#endif + + default: + { + rtcerr("ERROR: unsupported RTC %d\n", rtc); + goto errout; + } + } + + if (priv->inuse != false) + { + /* RTC already in use */ + + priv = NULL; + } + +errout: + return (struct nrf91_rtc_dev_s *)priv; +} + +/**************************************************************************** + * Name: nrf91_rtc_deinit + * + * Description: + * Deinit RTC device + * + ****************************************************************************/ + +int nrf91_rtc_deinit(struct nrf91_rtc_dev_s *dev) +{ + struct nrf91_rtc_priv_s *rtc = NULL; + + DEBUGASSERT(dev); + + rtc = (struct nrf91_rtc_priv_s *)dev; + + rtc->inuse = false; + + return OK; +} diff --git a/arch/arm/src/nrf91/nrf91_rtc.h b/arch/arm/src/nrf91/nrf91_rtc.h new file mode 100644 index 0000000000..acbbe02b52 --- /dev/null +++ b/arch/arm/src/nrf91/nrf91_rtc.h @@ -0,0 +1,139 @@ +/**************************************************************************** + * arch/arm/src/nrf91/nrf91_rtc.h + * + * 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. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_NRF91_NRF91_RTC_H +#define __ARCH_ARM_SRC_NRF91_NRF91_RTC_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Helpers ******************************************************************/ + +#define NRF91_RTC_START(d) ((d)->ops->start(d)) +#define NRF91_RTC_STOP(d) ((d)->ops->stop(d)) +#define NRF91_RTC_CLEAR(d) ((d)->ops->clear(d)) +#define NRF91_RTC_TRGOVRFLW(d) ((d)->ops->trgovrflw(d)) +#define NRF91_RTC_GETCOUNTER(d, c) ((d)->ops->getcounter(d, c)) +#define NRF91_RTC_SETCC(d, i, cc) ((d)->ops->setcc(d, i, cc)) +#define NRF91_RTC_GETCC(d, i, cc) ((d)->ops->setcc(d, i, cc)) +#define NRF91_RTC_SETPRE(d, pre) ((d)->ops->setpre(d, pre)) +#define NRF91_RTC_SETISR(d, hnd, arg) ((d)->ops->setisr(d, hnd, arg)) +#define NRF91_RTC_ENABLEINT(d, s) ((d)->ops->enableint(d, s)) +#define NRF91_RTC_DISABLEINT(d, s) ((d)->ops->disableint(d, s)) +#define NRF91_RTC_CHECKINT(d, s) ((d)->ops->checkint(d, s)) +#define NRF91_RTC_ACKINT(d, s) ((d)->ops->ackint(d, s)) +#define NRF91_RTC_ENABLEEVT(d, s) ((d)->ops->enableevt(d, s)) +#define NRF91_RTC_DISABLEEVT(d, s) ((d)->ops->disableevt(d, s)) +#define NRF91_RTC_GETBASE(d) ((d)->ops->getbase(d)) + +/* These are defined for direct access to registers, which is needed in some + * critical parts where access speed is important + */ + +#define NRF91_RTC_GETCOUNTER_REG(base) (getreg32(base + NRF91_RTC_COUNTER_OFFSET)) +#define NRF91_RTC_SETCC_REG(base, ch, cc) (putreg32(cc, base + NRF91_RTC_CC_OFFSET(ch))) +#define NRF91_RTC_GETCC_REG(base, ch) (getreg32(base + NRF91_RTC_CC_OFFSET(ch))) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* RTC CC index */ + +enum nrf91_rtc_cc_e +{ + NRF91_RTC_CC0 = 0, + NRF91_RTC_CC1 = 1, + NRF91_RTC_CC2 = 2, + NRF91_RTC_CC3 = 3, +}; + +/* RTC Interrupts/Events */ + +enum nrf91_rtc_evt_e +{ + NRF91_RTC_EVT_TICK = 0, + NRF91_RTC_EVT_OVRFLW = 1, + NRF91_RTC_EVT_COMPARE0 = 2, + NRF91_RTC_EVT_COMPARE1 = 3, + NRF91_RTC_EVT_COMPARE2 = 4, + NRF91_RTC_EVT_COMPARE3 = 5, +}; + +/* NRF91 RTC device */ + +struct nrf91_rtc_dev_s +{ + struct nrf91_rtc_ops_s *ops; +}; + +/* NRF91 RTC ops */ + +struct nrf91_rtc_ops_s +{ + /* RTC tasks */ + + int (*start)(struct nrf91_rtc_dev_s *dev); + int (*stop)(struct nrf91_rtc_dev_s *dev); + int (*clear)(struct nrf91_rtc_dev_s *dev); + int (*trgovrflw)(struct nrf91_rtc_dev_s *dev); + + /* RTC operations */ + + int (*getcounter)(struct nrf91_rtc_dev_s *dev, uint32_t *cc); + int (*setcc)(struct nrf91_rtc_dev_s *dev, uint8_t i, uint32_t cc); + int (*getcc)(struct nrf91_rtc_dev_s *dev, uint8_t i, uint32_t *cc); + int (*setpre)(struct nrf91_rtc_dev_s *dev, uint16_t pre); + + /* RTC interrupts */ + + int (*setisr)(struct nrf91_rtc_dev_s *dev, xcpt_t handler, void *arg); + int (*enableint)(struct nrf91_rtc_dev_s *dev, uint8_t source); + int (*disableint)(struct nrf91_rtc_dev_s *dev, uint8_t source); + int (*checkint)(struct nrf91_rtc_dev_s *dev, uint8_t source); + int (*ackint)(struct nrf91_rtc_dev_s *dev, uint8_t source); + + /* RTC events */ + + int (*enableevt)(struct nrf91_rtc_dev_s *dev, uint8_t evt); + int (*disableevt)(struct nrf91_rtc_dev_s *dev, uint8_t evt); + + /* Utility */ + + uint32_t (*getbase)(struct nrf91_rtc_dev_s *dev); +}; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +struct nrf91_rtc_dev_s *nrf91_rtc_init(int rtc); +int nrf91_rtc_deinit(struct nrf91_rtc_dev_s *dev); + +#endif /* __ARCH_ARM_SRC_NRF91_NRF91_RTC_H */ diff --git a/arch/arm/src/nrf91/nrf91_serial.c b/arch/arm/src/nrf91/nrf91_serial.c new file mode 100644 index 0000000000..c11a2503e3 --- /dev/null +++ b/arch/arm/src/nrf91/nrf91_serial.c @@ -0,0 +1,863 @@ +/**************************************************************************** + * arch/arm/src/nrf91/nrf91_serial.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 +#include +#include +#include + +#ifdef CONFIG_SERIAL_TERMIOS +# include +#endif + +#include + +#include "arm_internal.h" +#include "chip.h" +#include "nrf91_config.h" +#include "hardware/nrf91_uarte.h" +#include "nrf91_clockconfig.h" +#include "nrf91_lowputc.h" +#include "nrf91_serial.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* How many UARTs are supported */ + +#ifdef HAVE_UART1 +# define NRF91_NUART 2 +#else +# define NRF91_NUART 1 +#endif + +/* Some sanity checks *******************************************************/ + +/* Is there at least one UART enabled and configured as a RS-232 device? */ + +#ifndef HAVE_UART_DEVICE +# warning "No UARTs enabled" +#endif + +/* If we are not using the serial driver for the console, then we still must + * provide some minimal implementation of up_putc. + */ + +#if defined(HAVE_UART_DEVICE) && defined(USE_SERIALDRIVER) + +/* Which UART with be tty0/console and which tty1-4? The console will + * always be ttyS0. If there is no console then will use the lowest + * numbered UART. + */ + +#ifdef CONFIG_UART0_SERIAL_CONSOLE +# define CONSOLE_DEV g_uart0port /* UART0 is console */ +# define TTYS0_DEV g_uart0port /* UART0 is ttyS0 */ +#elif CONFIG_UART1_SERIAL_CONSOLE +# define CONSOLE_DEV g_uart1port /* UART1 is console */ +# define TTYS0_DEV g_uart1port /* UART1 is ttyS0 */ +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* This structure provides the state of one UART device */ + +struct nrf91_dev_s +{ + uintptr_t uartbase; /* Base address of UART registers */ + uint8_t irq; /* IRQ associated with this UART */ + bool rx_available; /* rx byte available */ + + /* UART configuration */ + + struct uart_config_s config; +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int nrf91_setup(struct uart_dev_s *dev); +static void nrf91_shutdown(struct uart_dev_s *dev); +static int nrf91_attach(struct uart_dev_s *dev); +static void nrf91_detach(struct uart_dev_s *dev); +static int nrf91_interrupt(int irq, void *context, void *arg); +static int nrf91_ioctl(struct file *filep, int cmd, unsigned long arg); +static int nrf91_receive(struct uart_dev_s *dev, unsigned int *status); +static void nrf91_rxint(struct uart_dev_s *dev, bool enable); +static bool nrf91_rxavailable(struct uart_dev_s *dev); +static void nrf91_send(struct uart_dev_s *dev, int ch); +static void nrf91_txint(struct uart_dev_s *dev, bool enable); +static bool nrf91_txready(struct uart_dev_s *dev); +static bool nrf91_txempty(struct uart_dev_s *dev); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct uart_ops_s g_uart_ops = +{ + .setup = nrf91_setup, + .shutdown = nrf91_shutdown, + .attach = nrf91_attach, + .detach = nrf91_detach, + .ioctl = nrf91_ioctl, + .receive = nrf91_receive, + .rxint = nrf91_rxint, + .rxavailable = nrf91_rxavailable, +#ifdef CONFIG_SERIAL_IFLOWCONTROL + .rxflowcontrol = NULL, +#endif + .send = nrf91_send, + .txint = nrf91_txint, + .txready = nrf91_txready, + .txempty = nrf91_txempty, +}; + +/* I/O buffers */ + +#ifdef HAVE_UART0 +static char g_uart0rxbuffer[CONFIG_UART0_RXBUFSIZE]; +static char g_uart0txbuffer[CONFIG_UART0_TXBUFSIZE]; +#endif +#ifdef HAVE_UART1 +static char g_uart1rxbuffer[CONFIG_UART1_RXBUFSIZE]; +static char g_uart1txbuffer[CONFIG_UART1_TXBUFSIZE]; +#endif + +/* This describes the state of the NRF91 UART0 port. */ + +#ifdef HAVE_UART0 +static struct nrf91_dev_s g_uart0priv = +{ + .uartbase = NRF91_UART0_BASE, + .irq = NRF91_IRQ_SERIAL0, + .rx_available = false, + .config = + { + .baud = CONFIG_UART0_BAUD, + .parity = CONFIG_UART0_PARITY, + .bits = CONFIG_UART0_BITS, + .stopbits2 = CONFIG_UART0_2STOP, +#ifdef CONFIG_UART0_IFLOWCONTROL + .iflow = true, +#endif +#ifdef CONFIG_UART0_OFLOWCONTROL + .oflow = true, +#endif + .txpin = BOARD_UART0_TX_PIN, + .rxpin = BOARD_UART0_RX_PIN, + } +}; + +static uart_dev_t g_uart0port = +{ + .recv = + { + .size = CONFIG_UART0_RXBUFSIZE, + .buffer = g_uart0rxbuffer, + }, + .xmit = + { + .size = CONFIG_UART0_TXBUFSIZE, + .buffer = g_uart0txbuffer, + }, + .ops = &g_uart_ops, + .priv = &g_uart0priv, +}; +#endif + +/* This describes the state of the NRF91 UART1 port. */ + +#ifdef HAVE_UART1 +static struct nrf91_dev_s g_uart1priv = +{ + .uartbase = NRF91_UART1_BASE, + .irq = NRF91_IRQ_SERIAL1, + .rx_available = false, + .config = + { + .baud = CONFIG_UART1_BAUD, + .parity = CONFIG_UART1_PARITY, + .bits = CONFIG_UART1_BITS, + .stopbits2 = CONFIG_UART1_2STOP, +#ifdef CONFIG_UART1_IFLOWCONTROL + .iflow = true, +#endif +#ifdef CONFIG_UART1_OFLOWCONTROL + .oflow = true, +#endif + .txpin = BOARD_UART1_TX_PIN, + .rxpin = BOARD_UART1_RX_PIN, + } +}; + +static uart_dev_t g_uart1port = +{ + .recv = + { + .size = CONFIG_UART1_RXBUFSIZE, + .buffer = g_uart1rxbuffer, + }, + .xmit = + { + .size = CONFIG_UART1_TXBUFSIZE, + .buffer = g_uart1txbuffer, + }, + .ops = &g_uart_ops, + .priv = &g_uart1priv, +}; +#endif + +/* This table lets us iterate over the configured UARTs */ + +static struct uart_dev_s * const g_uart_devs[NRF91_NUART] = +{ +#ifdef HAVE_UART0 + [0] = &g_uart0port, +#endif +#ifdef HAVE_UART1 + [1] = &g_uart1port +#endif +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nrf91_setup + * + * Description: + * Configure the UART baud, bits, parity, etc. This method is called the + * first time that the serial port is opened. + * + ****************************************************************************/ + +static int nrf91_setup(struct uart_dev_s *dev) +{ +#ifndef CONFIG_SUPPRESS_UART_CONFIG + struct nrf91_dev_s *priv = (struct nrf91_dev_s *)dev->priv; + + /* TODO: Configure the UART as an RS-232 UART */ + + /* REVISIT: If nrf91_usart_configure() called 2nd time uart stops working. + * Rx interrupt keeps firing. + * configuring is done on __start + * + * UPDATE 19.12.2019: No problems described above were observed, + * but just in case we leave the above note for some time. + */ + + nrf91_usart_configure(priv->uartbase, &priv->config); +#endif + + /* TODO: configure UART if not selected as console */ + + return OK; +} + +/**************************************************************************** + * Name: nrf91_shutdown + * + * Description: + * Disable the UART. This method is called when the serial + * port is closed + * + ****************************************************************************/ + +static void nrf91_shutdown(struct uart_dev_s *dev) +{ + struct nrf91_dev_s *priv = (struct nrf91_dev_s *)dev->priv; + + /* Disable interrupts */ + + /* Reset hardware and disable Rx and Tx */ + + nrf91_usart_disable(priv->uartbase, &priv->config); +} + +/**************************************************************************** + * Name: nrf91_attach + * + * Description: + * Configure the UART to operation in interrupt driven mode. This method + * is called when the serial port is opened. Normally, this is just after + * the the setup() method is called, however, the serial console may + * operate in a non-interrupt driven mode during the boot phase. + * + * RX and TX interrupts are not enabled when by the attach method (unless + * the hardware supports multiple levels of interrupt enabling). + * The RX and TX interrupts are not enabled until the txint() and rxint() + * methods are called. + * + ****************************************************************************/ + +static int nrf91_attach(struct uart_dev_s *dev) +{ + struct nrf91_dev_s *priv = (struct nrf91_dev_s *)dev->priv; + int ret; + + /* Attach and enable the IRQ(s). The interrupts are (probably) still + * disabled in the C2 register. + */ + + ret = irq_attach(priv->irq, nrf91_interrupt, dev); + if (ret == OK) + { + up_enable_irq(priv->irq); + } + + return ret; +} + +/**************************************************************************** + * Name: nrf91_detach + * + * Description: + * Detach UART interrupts. This method is called when the serial port is + * closed normally just before the shutdown method is called. + * The exception is the serial console which is never shutdown. + * + ****************************************************************************/ + +static void nrf91_detach(struct uart_dev_s *dev) +{ + struct nrf91_dev_s *priv = (struct nrf91_dev_s *)dev->priv; + + /* Disable interrupts */ + + putreg32(UART_INT_RXDRDY, priv->uartbase + NRF91_UART_INTENCLR_OFFSET); + up_disable_irq(priv->irq); + + /* Detach from the interrupt(s) */ + + irq_detach(priv->irq); +} + +/**************************************************************************** + * Name: nrf91_interrupt + * + * Description: + * This is the UART interrupt handler. It will be invoked when an + * interrupt is received on the 'irq'. It should call uart_xmitchars or + * uart_recvchars to perform the appropriate data transfers. The + * interrupt handling logic must be able to map the 'arg' to the + * appropriate uart_dev_s structure in order to call these functions. + * + ****************************************************************************/ + +static int nrf91_interrupt(int irq, void *context, void *arg) +{ + struct uart_dev_s *dev = (struct uart_dev_s *)arg; + struct nrf91_dev_s *priv; + uint32_t regval; + + DEBUGASSERT(dev != NULL && dev->priv != NULL); + priv = (struct nrf91_dev_s *)dev->priv; + + /* Check RX event */ + + regval = getreg32(priv->uartbase + NRF91_UART_EVENTS_RXDRDY_OFFSET); + + if (regval != 0) + { + putreg32(0, priv->uartbase + NRF91_UART_EVENTS_RXDRDY_OFFSET); + priv->rx_available = true; + uart_recvchars(dev); + } + + /* Clear errors */ + + putreg32(0, priv->uartbase + NRF91_UART_ERRORSRC_OFFSET); + + return OK; +} + +/**************************************************************************** + * Name: nrf91_set_format + * + * Description: + * Set the serial line format and speed. + * + ****************************************************************************/ + +#ifdef CONFIG_SERIAL_TERMIOS +void nrf91_set_format(struct uart_dev_s *dev) +{ + struct nrf91_dev_s *priv = (struct nrf91_dev_s *)dev->priv; + + nrf91_usart_setformat(priv->uartbase, &priv->config); +} +#endif + +/**************************************************************************** + * Name: nrf91_ioctl + * + * Description: + * All ioctl calls will be routed through this method + * + ****************************************************************************/ + +static int nrf91_ioctl(struct file *filep, int cmd, unsigned long arg) +{ +#ifdef CONFIG_SERIAL_TERMIOS + struct inode *inode = filep->f_inode; + struct uart_dev_s *dev = inode->i_private; + struct nrf91_dev_s *priv = (struct nrf91_dev_s *)dev->priv; + struct uart_config_s *config = &priv->config; +#endif + int ret = OK; + + switch (cmd) + { +#ifdef CONFIG_SERIAL_TERMIOS + case TCGETS: + { + struct termios *termiosp = (struct termios *)arg; + + if (!termiosp) + { + ret = -EINVAL; + break; + } + + termiosp->c_cflag = ((config->parity != 0) ? PARENB : 0) + | ((config->parity == 1) ? PARODD : 0) + | ((config->stopbits2) ? CSTOPB : 0) | +#ifdef CONFIG_SERIAL_OFLOWCONTROL + ((config->oflow) ? CCTS_OFLOW : 0) | +#endif +#ifdef CONFIG_SERIAL_IFLOWCONTROL + ((config->iflow) ? CRTS_IFLOW : 0) | +#endif + CS8; + + cfsetispeed(termiosp, config->baud); + + break; + } + + case TCSETS: + { + struct termios *termiosp = (struct termios *)arg; + + if (!termiosp) + { + ret = -EINVAL; + break; + } + + /* Perform some sanity checks before accepting any changes */ + + if ((termiosp->c_cflag & CSIZE) != CS8) + { + ret = -EINVAL; + break; + } + +#ifndef HAVE_UART_STOPBITS + if ((termiosp->c_cflag & CSTOPB) != 0) + { + ret = -EINVAL; + break; + } +#endif + + if (termiosp->c_cflag & PARODD) + { + ret = -EINVAL; + break; + } + + /* TODO: CCTS_OFLOW and CRTS_IFLOW */ + + /* Parity */ + + if (termiosp->c_cflag & PARENB) + { + config->parity = (termiosp->c_cflag & PARODD) ? 1 : 2; + } + else + { + config->parity = 0; + } + +#ifdef HAVE_UART_STOPBITS + /* Stop bits */ + + config->stopbits2 = (termiosp->c_cflag & CSTOPB) != 0; +#endif + + /* Note that only cfgetispeed is used because we have knowledge + * that only one speed is supported. + */ + + config->baud = cfgetispeed(termiosp); + + /* Effect the changes */ + + nrf91_set_format(dev); + + break; + } +#endif + + default: + { + ret = -ENOTTY; + break; + } + } + + return ret; +} + +/**************************************************************************** + * Name: nrf91_receive + * + * Description: + * Called (usually) from the interrupt level to receive one + * character from the UART. Error bits associated with the + * receipt are provided in the return 'status'. + * + ****************************************************************************/ + +static int nrf91_receive(struct uart_dev_s *dev, unsigned int *status) +{ + struct nrf91_dev_s *priv = (struct nrf91_dev_s *)dev->priv; + uint32_t data; + + /* Get input data along with receiver control information */ + + data = getreg32(priv->uartbase + NRF91_UART_RXD_OFFSET); + priv->rx_available = false; + + /* Return receiver control information */ + + if (status) + { + *status = 0x00; + } + + /* Then return the actual received data. */ + + return data; +} + +/**************************************************************************** + * Name: nrf91_rxint + * + * Description: + * Call to enable or disable RX interrupts + * + ****************************************************************************/ + +static void nrf91_rxint(struct uart_dev_s *dev, bool enable) +{ + struct nrf91_dev_s *priv = (struct nrf91_dev_s *)dev->priv; + + if (enable) + { +#ifndef CONFIG_SUPPRESS_SERIAL_INTS + /* Receive an interrupt when their is anything in the Rx data register + * (or an Rx timeout occurs). + */ + + putreg32(UART_INT_RXDRDY, priv->uartbase + NRF91_UART_INTENSET_OFFSET); + putreg32(1, priv->uartbase + NRF91_UART_TASKS_STARTRX_OFFSET); + +#endif + } + else + { + putreg32(UART_INT_RXDRDY, priv->uartbase + NRF91_UART_INTENCLR_OFFSET); + putreg32(1, priv->uartbase + NRF91_UART_TASKS_STOPRX_OFFSET); + } +} + +/**************************************************************************** + * Name: nrf91_rxavailable + * + * Description: + * Return true if the receive register is not empty + * + ****************************************************************************/ + +static bool nrf91_rxavailable(struct uart_dev_s *dev) +{ + struct nrf91_dev_s *priv = (struct nrf91_dev_s *)dev->priv; + + /* Return true if the receive buffer/fifo is not "empty." */ + + return priv->rx_available; +} + +/**************************************************************************** + * Name: nrf91_send + * + * Description: + * This method will send one byte on the UART. + * + ****************************************************************************/ + +static void nrf91_send(struct uart_dev_s *dev, int ch) +{ + struct nrf91_dev_s *priv = (struct nrf91_dev_s *)dev->priv; + + putreg32(0, priv->uartbase + NRF91_UART_EVENTS_TXDRDY_OFFSET); + putreg32(1, priv->uartbase + NRF91_UART_TASKS_STARTTX_OFFSET); + + putreg32(ch, priv->uartbase + NRF91_UART_TXD_OFFSET); + while (getreg32(priv->uartbase + NRF91_UART_EVENTS_TXDRDY_OFFSET) == 0) + { + } + + putreg32(1, priv->uartbase + NRF91_UART_TASKS_STOPTX_OFFSET); +} + +/**************************************************************************** + * Name: nrf91_txint + * + * Description: + * Call to enable or disable TX interrupts + * + ****************************************************************************/ + +static void nrf91_txint(struct uart_dev_s *dev, bool enable) +{ + /* struct nrf91_dev_s *priv = (struct nrf91_dev_s *)dev->priv; */ + + if (enable) + { +#ifndef CONFIG_SUPPRESS_SERIAL_INTS + irqstate_t flags; + + /* Enable the TX interrupt */ + + flags = enter_critical_section(); + + /* Fake a TX interrupt here by just calling uart_xmitchars() with + * interrupts disabled (note this may recurse). + */ + + uart_xmitchars(dev); + leave_critical_section(flags); +#endif + } + else + { + /* Disable the TX interrupt */ + } +} + +/**************************************************************************** + * Name: nrf91_txready + * + * Description: + * Return true if the tranmsit data register is empty + * + ****************************************************************************/ + +static bool nrf91_txready(struct uart_dev_s *dev) +{ + /* struct nrf91_dev_s *priv = (struct nrf91_dev_s *)dev->priv; */ + + /* Return true if the transmit FIFO is "not full." */ + + return true; +} + +/**************************************************************************** + * Name: nrf91_txempty + * + * Description: + * Return true if the transmit data register is empty + * + ****************************************************************************/ + +static bool nrf91_txempty(struct uart_dev_s *dev) +{ + /* struct nrf91_dev_s *priv = (struct nrf91_dev_s *)dev->priv; */ + + /* Return true if the transmit FIFO is "empty." */ + + return true; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nrf91_earlyserialinit + * + * Description: + * Performs the low level UART initialization early in debug so that the + * serial console will be available during bootup. This must be called + * before nrf91_serialinit. NOTE: This function depends on GPIO pin + * configuration performed in nrf91_lowsetup() and main clock + * initialization performed in nrf_clock_configure(). + * + ****************************************************************************/ + +#ifdef USE_EARLYSERIALINIT +void nrf91_earlyserialinit(void) +{ + /* Configuration whichever one is the console */ + +#ifdef HAVE_UART_CONSOLE + CONSOLE_DEV.isconsole = true; + nrf91_setup(&CONSOLE_DEV); +#endif +} +#endif + +/**************************************************************************** + * Name: arm_serialinit + * + * Description: + * Register serial console and serial ports. This assumes + * that nrf91_earlyserialinit was called previously. + * + * Input Parameters: + * None + * + * Returns Value: + * None + * + ****************************************************************************/ + +void arm_serialinit(void) +{ + unsigned minor = 0; + unsigned i = 0; + char devname[16]; + +#ifdef HAVE_UART_CONSOLE + /* Register the serial console */ + + uart_register("/dev/console", &CONSOLE_DEV); +#endif + + uart_register("/dev/ttyS0", &TTYS0_DEV); + minor = 1; + + /* Register all remaining UARTs */ + + strlcpy(devname, "/dev/ttySx", sizeof(devname)); + + for (i = 0; i < NRF91_NUART; i++) + { + /* Don't create a device for non-configured ports. */ + + if (g_uart_devs[i] == 0) + { + continue; + } + + /* Don't create a device for the console - we did that above */ + + if (g_uart_devs[i]->isconsole) + { + continue; + } + + /* Register USARTs as devices in increasing order */ + + devname[9] = '0' + minor++; + uart_register(devname, g_uart_devs[i]); + } +} + +/**************************************************************************** + * Name: up_putc + * + * Description: + * Provide priority, low-level access to support OS debug writes + * + ****************************************************************************/ + +int up_putc(int ch) +{ +#ifdef HAVE_UART_CONSOLE + /* struct nrf91_dev_s *priv = (struct nrf91_dev_s *)CONSOLE_DEV.priv; */ + + /* Check for LF */ + + if (ch == '\n') + { + /* Add CR */ + + arm_lowputc('\r'); + } + + arm_lowputc(ch); +#endif + + return ch; +} + +#else /* USE_SERIALDRIVER */ + +/**************************************************************************** + * Name: up_putc + * + * Description: + * Provide priority, low-level access to support OS debug writes + * + ****************************************************************************/ + +int up_putc(int ch) +{ +#ifdef HAVE_UART_CONSOLE + /* Check for LF */ + + if (ch == '\n') + { + /* Add CR */ + + arm_lowputc('\r'); + } + + arm_lowputc(ch); + return ch; +#endif +} + +#endif /* HAVE_UART_DEVICE && USE_SERIALDRIVER */ diff --git a/arch/arm/src/nrf91/nrf91_serial.h b/arch/arm/src/nrf91/nrf91_serial.h new file mode 100644 index 0000000000..d439e12741 --- /dev/null +++ b/arch/arm/src/nrf91/nrf91_serial.h @@ -0,0 +1,52 @@ +/**************************************************************************** + * arch/arm/src/nrf91/nrf91_serial.h + * + * 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. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_NRF91_NRF91_SERIAL_H +#define __ARCH_ARM_SRC_NRF91_NRF91_SERIAL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "nrf91_config.h" + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: nrf91_earlyserialinit + * + * Description: + * Performs the low level UART initialization early in debug so that the + * serial console will be available during bootup. This must be called + * before nrf91_serialinit. NOTE: This function depends on GPIO pin + * configuration performed in xmc_lowsetup() and main clock initialization + * performed in xmc_clock_configure(). + * + ****************************************************************************/ + +#ifdef USE_EARLYSERIALINIT +void nrf91_earlyserialinit(void); +#endif + +#endif /* __ARCH_ARM_SRC_NRF91_NRF91@_SERIAL_H */ diff --git a/arch/arm/src/nrf91/nrf91_spi.c b/arch/arm/src/nrf91/nrf91_spi.c new file mode 100644 index 0000000000..c0361375fb --- /dev/null +++ b/arch/arm/src/nrf91/nrf91_spi.c @@ -0,0 +1,1503 @@ +/**************************************************************************** + * arch/arm/src/nrf91/nrf91_spi.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 + +#include "arm_internal.h" +#include "barriers.h" + +#include "nrf91_gpio.h" +#include "nrf91_spi.h" + +#include "hardware/nrf91_spi.h" +#include "hardware/nrf91_utils.h" + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct nrf91_spidev_s +{ + struct spi_dev_s spidev; /* Externally visible part of the SPI interface */ + uint32_t base; /* Base address of SPI register */ +#ifdef CONFIG_NRF91_SPI_MASTER_INTERRUPTS + uint32_t irq; /* SPI IRQ number */ +#endif + nrf91_pinset_t sck_pin; /* SCK pin configuration */ + uint32_t frequency; /* Requested clock frequency */ + uint8_t mode; /* Mode 0,1,2,3 */ + + mutex_t lock; /* Held while chip is selected for mutual + * exclusion + */ +#ifdef CONFIG_NRF91_SPI_MASTER_INTERRUPTS + sem_t sem_isr; /* Interrupt wait semaphore */ +#endif + bool initialized; +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static inline void nrf91_spi_putreg(struct nrf91_spidev_s *priv, + uint32_t offset, + uint32_t value); +static inline uint32_t nrf91_spi_getreg(struct nrf91_spidev_s *priv, + uint32_t offset); + +/* SPI methods */ + +static int nrf91_spi_lock(struct spi_dev_s *dev, bool lock); +static uint32_t nrf91_spi_setfrequency(struct spi_dev_s *dev, + uint32_t frequency); +static void nrf91_spi_setmode(struct spi_dev_s *priv, + enum spi_mode_e mode); +static void nrf91_spi_setbits(struct spi_dev_s *priv, int nbits); +#ifdef CONFIG_SPI_HWFEATURES +static int nrf91_spi_hwfeatures(struct spi_dev_s *dev, + spi_hwfeatures_t features); +#endif +static uint32_t nrf91_spi_send(struct spi_dev_s *dev, uint32_t wd); +static void nrf91_spi_exchange(struct spi_dev_s *dev, + const void *txbuffer, + void *rxbuffer, size_t nwords); +#ifndef CONFIG_SPI_EXCHANGE +static void nrf91_spi_sndblock(struct spi_dev_s *dev, + const void *txbuffer, + size_t nwords); +static void nrf91_spi_recvblock(struct spi_dev_s *dev, + void *rxbuffer, + size_t nwords); +#endif + +#ifdef CONFIG_NRF91_SPI_MASTER_INTERRUPTS +static int nrf91_spi_isr(int irq, void *context, void *arg); +#endif + +/* Initialization */ + +static int nrf91_spi_init(struct nrf91_spidev_s *priv); +static void nrf91_spi_pselinit(struct nrf91_spidev_s *priv, + uint32_t offset, nrf91_pinset_t pinset); +static void nrf91_spi_gpioinit(struct nrf91_spidev_s *priv); + +#ifdef CONFIG_PM +static int nrf91_spi_deinit(struct nrf91_spidev_s *priv); +static void nrf91_spi_gpiodeinit(struct nrf91_spidev_s *priv); + +static int nrf91_spi_pm_prepare(struct pm_callback_s *cb, int domain, + enum pm_state_e pmstate); +static void nrf91_spi_pm_notify(struct pm_callback_s *cb, int domain, + enum pm_state_e pmstate); +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +#ifdef CONFIG_PM +struct pm_callback_s g_pm_callbacks = +{ + .prepare = nrf91_spi_pm_prepare, + .notify = nrf91_spi_pm_notify +}; +#endif + +/* SPI0 */ + +#ifdef CONFIG_NRF91_SPI0_MASTER +static const struct spi_ops_s g_spi0ops = +{ + .lock = nrf91_spi_lock, + .select = nrf91_spi0select, + .setfrequency = nrf91_spi_setfrequency, + .setmode = nrf91_spi_setmode, + .setbits = nrf91_spi_setbits, +# ifdef CONFIG_SPI_HWFEATURES + .hwfeatures = nrf91_spi_hwfeatures, +# endif + .status = nrf91_spi0status, +# ifdef CONFIG_SPI_CMDDATA + .cmddata = nrf91_spi0cmddata, +# endif + .send = nrf91_spi_send, +# ifdef CONFIG_SPI_EXCHANGE + .exchange = nrf91_spi_exchange, +# else + .sndblock = nrf91_spi_sndblock, + .recvblock = nrf91_spi_recvblock, +# endif +#ifdef CONFIG_SPI_TRIGGER + .trigger = nrf91_spi_trigger, +#endif +#ifdef CONFIG_SPI_CALLBACK + .registercallback = nrf91_spi0register, /* Provided externally */ +#else + .registercallback = NULL, /* Not implemented */ +#endif +}; + +static struct nrf91_spidev_s g_spi0dev = +{ + .spidev = + { + .ops = &g_spi0ops, + }, + + .base = NRF91_SPIM0_BASE, + .lock = NXMUTEX_INITIALIZER, +#ifdef CONFIG_NRF91_SPI_MASTER_INTERRUPTS + .sem_isr = SEM_INITIALIZER(0), + .irq = NRF91_IRQ_SERIAL0, +#endif + .sck_pin = BOARD_SPI0_SCK_PIN, + .frequency = 0, + .mode = 0 +}; +#endif + +/* SPI1 */ + +#ifdef CONFIG_NRF91_SPI1_MASTER +static const struct spi_ops_s g_spi1ops = +{ + .lock = nrf91_spi_lock, + .select = nrf91_spi1select, + .setfrequency = nrf91_spi_setfrequency, + .setmode = nrf91_spi_setmode, + .setbits = nrf91_spi_setbits, +# ifdef CONFIG_SPI_HWFEATURES + .hwfeatures = nrf91_spi_hwfeatures, +# endif + .status = nrf91_spi1status, +# ifdef CONFIG_SPI_CMDDATA + .cmddata = nrf91_spi1cmddata, +# endif + .send = nrf91_spi_send, +# ifdef CONFIG_SPI_EXCHANGE + .exchange = nrf91_spi_exchange, +# else + .sndlock = nrf91_spi_sndblock, + .recvblock = nrf91_spi_recvblock, +# endif +#ifdef CONFIG_SPI_TRIGGER + .trigger = nrf91_spi_trigger, +#endif +#ifdef CONFIG_SPI_CALLBACK + .registercallback = nrf91_spi1register, /* Provided externally */ +#else + .registercallback = NULL, /* Not implemented */ +#endif +}; + +static struct nrf91_spidev_s g_spi1dev = +{ + .spidev = + { + .ops = &g_spi1ops, + }, + + .base = NRF91_SPIM1_BASE, + .lock = NXMUTEX_INITIALIZER, +#ifdef CONFIG_NRF91_SPI_MASTER_INTERRUPTS + .sem_isr = SEM_INITIALIZER(0), + .irq = NRF91_IRQ_SERIAL1, +#endif + .sck_pin = BOARD_SPI1_SCK_PIN, + .frequency = 0, + .mode = 0 +}; +#endif + +/* SPI2 */ + +#ifdef CONFIG_NRF91_SPI2_MASTER +static const struct spi_ops_s g_spi2ops = +{ + .lock = nrf91_spi_lock, + .select = nrf91_spi2select, + .setfrequency = nrf91_spi_setfrequency, + .setmode = nrf91_spi_setmode, + .setbits = nrf91_spi_setbits, +# ifdef CONFIG_SPI_HWFEATURES + .hwfeatures = nrf91_spi_hwfeatures, +# endif + .status = nrf91_spi2status, +# ifdef CONFIG_SPI_CMDDATA + .cmddata = nrf91_spi2cmddata, +# endif + .send = nrf91_spi_send, +# ifdef CONFIG_SPI_EXCHANGE + .exchange = nrf91_spi_exchange, +# else + .sndlock = nrf91_spi_sndblock, + .recvblock = nrf91_spi_recvblock, +# endif +#ifdef CONFIG_SPI_TRIGGER + .trigger = nrf91_spi_trigger, +#endif +#ifdef CONFIG_SPI_CALLBACK + .registercallback = nrf91_spi2register, /* Provided externally */ +#else + .registercallback = NULL, /* Not implemented */ +#endif +}; + +static struct nrf91_spidev_s g_spi2dev = +{ + .spidev = + { + .ops = &g_spi2ops, + }, + + .base = NRF91_SPIM2_BASE, + .lock = NXMUTEX_INITIALIZER, +#ifdef CONFIG_NRF91_SPI_MASTER_INTERRUPTS + .sem_isr = SEM_INITIALIZER(0), + .irq = NRF91_IRQ_SERIAL2, +#endif + .sck_pin = BOARD_SPI2_SCK_PIN, + .frequency = 0, + .mode = 0 +}; +#endif + +/* SPI3 */ + +#ifdef CONFIG_NRF91_SPI3_MASTER +static const struct spi_ops_s g_spi3ops = +{ + .lock = nrf91_spi_lock, + .select = nrf91_spi3select, + .setfrequency = nrf91_spi_setfrequency, + .setmode = nrf91_spi_setmode, + .setbits = nrf91_spi_setbits, +# ifdef CONFIG_SPI_HWFEATURES + .hwfeatures = nrf91_spi_hwfeatures, +# endif + .status = nrf91_spi3status, +# ifdef CONFIG_SPI_CMDDATA + .cmddata = nrf91_spi3cmddata, +# endif + .send = nrf91_spi_send, +# ifdef CONFIG_SPI_EXCHANGE + .exchange = nrf91_spi_exchange, +# else + .sndlock = nrf91_spi_sndblock, + .recvblock = nrf91_spi_recvblock, +# endif +#ifdef CONFIG_SPI_TRIGGER + .trigger = nrf91_spi_trigger, +#endif +#ifdef CONFIG_SPI_CALLBACK + .registercallback = nrf91_spi3register, /* Provided externally */ +#else + .registercallback = NULL, /* Not implemented */ +#endif +}; + +static struct nrf91_spidev_s g_spi3dev = +{ + .spidev = + { + .ops = &g_spi3ops, + }, + + .base = NRF91_SPIM3_BASE, + .lock = NXMUTEX_INITIALIZER, +#ifdef CONFIG_NRF91_SPI_MASTER_INTERRUPTS + .sem_isr = SEM_INITIALIZER(0), + .irq = NRF91_IRQ_SERIAL3, +#endif + .sck_pin = BOARD_SPI3_SCK_PIN, + .frequency = 0, + .mode = 0 +}; +#endif + +/* SPI4 */ + +#ifdef CONFIG_NRF91_SPI4_MASTER +static const struct spi_ops_s g_spi4ops = +{ + .lock = nrf91_spi_lock, + .select = nrf91_spi4select, + .setfrequency = nrf91_spi_setfrequency, + .setmode = nrf91_spi_setmode, + .setbits = nrf91_spi_setbits, +# ifdef CONFIG_SPI_HWFEATURES + .hwfeatures = nrf91_spi_hwfeatures, +# endif + .status = nrf91_spi4status, +# ifdef CONFIG_SPI_CMDDATA + .cmddata = nrf91_spi4cmddata, +# endif + .send = nrf91_spi_send, +# ifdef CONFIG_SPI_EXCHANGE + .exchange = nrf91_spi_exchange, +# else + .sndlock = nrf91_spi_sndblock, + .recvblock = nrf91_spi_recvblock, +# endif +#ifdef CONFIG_SPI_TRIGGER + .trigger = nrf91_spi_trigger, +#endif +#ifdef CONFIG_SPI_CALLBACK + .registercallback = nrf91_spi4register, /* Provided externally */ +#else + .registercallback = NULL, /* Not implemented */ +#endif +}; + +static struct nrf91_spidev_s g_spi4dev = +{ + .spidev = + { + .ops = &g_spi4ops, + }, + + .base = NRF91_SPIM4_BASE, + .lock = NXMUTEX_INITIALIZER, +#ifdef CONFIG_NRF91_SPI_MASTER_INTERRUPTS + .sem_isr = SEM_INITIALIZER(0), + .irq = NRF91_IRQ_SPI4, +#endif + .sck_pin = BOARD_SPI4_SCK_PIN, + .frequency = 0, + .mode = 0 +}; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nrf91_spi_putreg + * + * Description: + * Put a 32-bit register value by offset + * + ****************************************************************************/ + +static inline void nrf91_spi_putreg(struct nrf91_spidev_s *priv, + uint32_t offset, + uint32_t value) +{ + putreg32(value, priv->base + offset); +} + +/**************************************************************************** + * Name: nrf91_spi_getreg + * + * Description: + * Get a 32-bit register value by offset + * + ****************************************************************************/ + +static inline uint32_t nrf91_spi_getreg(struct nrf91_spidev_s *priv, + uint32_t offset) +{ + return getreg32(priv->base + offset); +} + +/**************************************************************************** + * Name: nrf91_spi_isr + * + * Description: + * Common SPI interrupt service routine + * + ****************************************************************************/ + +#ifdef CONFIG_NRF91_SPI_MASTER_INTERRUPTS +static int nrf91_spi_isr(int irq, void *context, void *arg) +{ + struct nrf91_spidev_s *priv = (struct nrf91_spidev_s *)arg; + + /* Get interrupt event */ + + if (nrf91_spi_getreg(priv, NRF91_SPIM_EVENTS_END_OFFSET) == 1) + { + /* Transfer is complete */ + + nxsem_post(&priv->sem_isr); + + /* Clear event */ + + nrf91_spi_putreg(priv, NRF91_SPIM_EVENTS_END_OFFSET, 0); + } + + return OK; +} +#endif + +/**************************************************************************** + * Name: nrf91_spi_init + * + * Description: + * Configure SPI + * + ****************************************************************************/ + +static int nrf91_spi_init(struct nrf91_spidev_s *priv) +{ + /* Disable SPI */ + + nrf91_spi_putreg(priv, NRF91_SPIM_ENABLE_OFFSET, SPIM_ENABLE_DIS); + + /* Configure SPI pins */ + + nrf91_spi_gpioinit(priv); + + /* NOTE: Chip select pin must be configured by board-specific logic */ + +#ifdef CONFIG_NRF91_SPI_MASTER_INTERRUPTS + /* Enable interrupts for RX and TX done */ + + nrf91_spi_putreg(priv, NRF91_SPIM_INTENSET_OFFSET, SPIM_INT_END); +#endif + + /* Enable SPI */ + + nrf91_spi_putreg(priv, NRF91_SPIM_ENABLE_OFFSET, SPIM_ENABLE_EN); + + return OK; +} + +#ifdef CONFIG_PM +/**************************************************************************** + * Name: nrf91_spi_deinit + * + * Description: + * Configure SPI + * + ****************************************************************************/ + +static int nrf91_spi_deinit(struct nrf91_spidev_s *priv) +{ + /* Disable SPI */ + + nrf91_spi_putreg(priv, NRF91_SPIM_ENABLE_OFFSET, SPIM_ENABLE_DIS); + + /* Unconfigure SPI pins */ + + nrf91_spi_gpiodeinit(priv); + + return OK; +} +#endif + +/**************************************************************************** + * Name: nrf91_spi_pselinit + * + * Description: + * Configure PSEL for SPI devices + * + ****************************************************************************/ + +static void nrf91_spi_pselinit(struct nrf91_spidev_s *priv, + uint32_t offset, nrf91_pinset_t pinset) +{ + uint32_t regval; + int pin = GPIO_PIN_DECODE(pinset); + int port = GPIO_PORT_DECODE(pinset); + + regval = (pin << SPIM_PSEL_PIN_SHIFT); + regval |= (port << SPIM_PSEL_PORT_SHIFT); + nrf91_spi_putreg(priv, offset, regval); +} + +/**************************************************************************** + * Name: nrf91_spi_gpioinit + * + * Description: + * Configure GPIO for SPI pins + * + ****************************************************************************/ + +static void nrf91_spi_gpioinit(struct nrf91_spidev_s *priv) +{ + nrf91_gpio_config(priv->sck_pin); + nrf91_spi_pselinit(priv, NRF91_SPIM_PSELSCK_OFFSET, priv->sck_pin); + +#ifdef CONFIG_NRF91_SPI0_MASTER + if (priv == &g_spi0dev) + { +#ifdef BOARD_SPI0_MISO_PIN + nrf91_gpio_config(BOARD_SPI0_MISO_PIN); + nrf91_spi_pselinit(priv, NRF91_SPIM_PSELMISO_OFFSET, + BOARD_SPI0_MISO_PIN); +#endif +#ifdef BOARD_SPI0_MOSI_PIN + nrf91_gpio_config(BOARD_SPI0_MOSI_PIN); + nrf91_spi_pselinit(priv, NRF91_SPIM_PSELMOSI_OFFSET, + BOARD_SPI0_MOSI_PIN); + nrf91_gpio_write(BOARD_SPI0_MOSI_PIN, false); +#endif + } +#endif + +#ifdef CONFIG_NRF91_SPI1_MASTER + if (priv == &g_spi1dev) + { +#ifdef BOARD_SPI1_MISO_PIN + nrf91_gpio_config(BOARD_SPI1_MISO_PIN); + nrf91_spi_pselinit(priv, NRF91_SPIM_PSELMISO_OFFSET, + BOARD_SPI1_MISO_PIN); +#endif +#ifdef BOARD_SPI1_MOSI_PIN + nrf91_gpio_config(BOARD_SPI1_MOSI_PIN); + nrf91_spi_pselinit(priv, NRF91_SPIM_PSELMOSI_OFFSET, + BOARD_SPI1_MOSI_PIN); + nrf91_gpio_write(BOARD_SPI1_MOSI_PIN, false); +#endif + } +#endif + +#ifdef CONFIG_NRF91_SPI2_MASTER + if (priv == &g_spi2dev) + { +#ifdef BOARD_SPI2_MISO_PIN + nrf91_gpio_config(BOARD_SPI2_MISO_PIN); + nrf91_spi_pselinit(priv, NRF91_SPIM_PSELMISO_OFFSET, + BOARD_SPI2_MISO_PIN); +#endif +#ifdef BOARD_SPI2_MOSI_PIN + nrf91_gpio_config(BOARD_SPI2_MOSI_PIN); + nrf91_spi_pselinit(priv, NRF91_SPIM_PSELMOSI_OFFSET, + BOARD_SPI2_MOSI_PIN); + nrf91_gpio_write(BOARD_SPI2_MOSI_PIN, false); +#endif + } +#endif + +#ifdef CONFIG_NRF91_SPI3_MASTER + if (priv == &g_spi3dev) + { +#ifdef BOARD_SPI3_MISO_PIN + nrf91_gpio_config(BOARD_SPI3_MISO_PIN); + nrf91_spi_pselinit(priv, NRF91_SPIM_PSELMISO_OFFSET, + BOARD_SPI3_MISO_PIN); +#endif +#ifdef BOARD_SPI3_MOSI_PIN + nrf91_gpio_config(BOARD_SPI3_MOSI_PIN); + nrf91_spi_pselinit(priv, NRF91_SPIM_PSELMOSI_OFFSET, + BOARD_SPI3_MOSI_PIN); + nrf91_gpio_write(BOARD_SPI3_MOSI_PIN, false); +#endif + } +#endif + +#ifdef CONFIG_NRF91_SPI4_MASTER + if (priv == &g_spi4dev) + { +#ifdef BOARD_SPI4_MISO_PIN + nrf91_gpio_config(BOARD_SPI4_MISO_PIN); + nrf91_spi_pselinit(priv, NRF91_SPIM_PSELMISO_OFFSET, + BOARD_SPI4_MISO_PIN); +#endif +#ifdef BOARD_SPI4_MOSI_PIN + nrf91_gpio_config(BOARD_SPI4_MOSI_PIN); + nrf91_spi_pselinit(priv, NRF91_SPIM_PSELMOSI_OFFSET, + BOARD_SPI4_MOSI_PIN); + nrf91_gpio_write(BOARD_SPI4_MOSI_PIN, false); +#endif + } +#endif +} + +#ifdef CONFIG_PM +/**************************************************************************** + * Name: nrf91_spi_gpioinit + * + * Description: + * Configure GPIO for SPI pins + * + ****************************************************************************/ + +static void nrf91_spi_gpiodeinit(struct nrf91_spidev_s *priv) +{ + nrf91_gpio_unconfig(priv->sck_pin); + +#ifdef CONFIG_NRF91_SPI0_MASTER + if (priv == &g_spi0dev) + { +#ifdef BOARD_SPI0_MISO_PIN + nrf91_gpio_unconfig(BOARD_SPI0_MISO_PIN); +#endif +#ifdef BOARD_SPI0_MOSI_PIN + nrf91_gpio_unconfig(BOARD_SPI0_MOSI_PIN); +#endif + } +#endif + +#ifdef CONFIG_NRF91_SPI1_MASTER + if (priv == &g_spi1dev) + { +#ifdef BOARD_SPI1_MISO_PIN + nrf91_gpio_unconfig(BOARD_SPI1_MISO_PIN); +#endif +#ifdef BOARD_SPI1_MOSI_PIN + nrf91_gpio_unconfig(BOARD_SPI1_MOSI_PIN); +#endif + } +#endif + +#ifdef CONFIG_NRF91_SPI2_MASTER + if (priv == &g_spi2dev) + { +#ifdef BOARD_SPI2_MISO_PIN + nrf91_gpio_unconfig(BOARD_SPI2_MISO_PIN); +#endif +#ifdef BOARD_SPI2_MOSI_PIN + nrf91_gpio_unconfig(BOARD_SPI2_MOSI_PIN); +#endif + } +#endif + +#ifdef CONFIG_NRF91_SPI3_MASTER + if (priv == &g_spi3dev) + { +#ifdef BOARD_SPI3_MISO_PIN + nrf91_gpio_unconfig(BOARD_SPI3_MISO_PIN); +#endif +#ifdef BOARD_SPI3_MOSI_PIN + nrf91_gpio_unconfig(BOARD_SPI3_MOSI_PIN); +#endif + } +#endif + +#ifdef CONFIG_NRF91_SPI4_MASTER + if (priv == &g_spi4dev) + { +#ifdef BOARD_SPI4_MISO_PIN + nrf91_gpio_unconfig(BOARD_SPI4_MISO_PIN); +#endif +#ifdef BOARD_SPI4_MOSI_PIN + nrf91_gpio_unconfig(BOARD_SPI4_MOSI_PIN); +#endif + } +#endif +} +#endif + +/**************************************************************************** + * Name: nrf91_spi_lock + * + * Description: + * On SPI buses where there are multiple devices, it will be necessary to + * lock SPI to have exclusive access to the buses for a sequence of + * transfers. The bus should be locked before the chip is selected. After + * locking the SPI bus, the caller should then also call the setfrequency, + * setbits, and setmode methods to make sure that the SPI is properly + * configured for the device. If the SPI bus is being shared, then it + * may have been left in an incompatible state. + * + * Input Parameters: + * dev - Device-specific state data + * lock - true: Lock spi bus, false: unlock SPI bus + * + * Returned Value: + * None + * + ****************************************************************************/ + +static int nrf91_spi_lock(struct spi_dev_s *dev, bool lock) +{ + struct nrf91_spidev_s *priv = (struct nrf91_spidev_s *)dev; + int ret = OK; + + if (lock) + { + ret = nxmutex_lock(&priv->lock); + } + else + { + ret = nxmutex_unlock(&priv->lock); + } + + return ret; +} + +/**************************************************************************** + * Name: nrf91_spi_setfrequency + * + * Description: + * Set the SPI frequency. + * + * Input Parameters: + * dev - Device-specific state data + * frequency - The SPI frequency requested + * + * Returned Value: + * Returns the actual frequency selected + * + ****************************************************************************/ + +static uint32_t nrf91_spi_setfrequency(struct spi_dev_s *dev, + uint32_t frequency) +{ + struct nrf91_spidev_s *priv = (struct nrf91_spidev_s *)dev; + uint32_t regval = 0; + + if (priv->frequency == frequency) + { + /* We are already at this frequency */ + + return priv->frequency; + } + + /* Frequency > 8MHz available only for SPIM4 */ + + if (frequency > 8000000 && priv->base != NRF91_SPIM4_BASE) + { + frequency = 8000000; + spiwarn("Reduce freq to %" PRId32 "\n", frequency); + } + + /* Frequencies are hardcoded */ + + switch (frequency) + { + case 125000: + { + regval = SPIM_FREQUENCY_125KBPS; + break; + } + + case 250000: + { + regval = SPIM_FREQUENCY_250KBPS; + break; + } + + case 500000: + { + regval = SPIM_FREQUENCY_500KBPS; + break; + } + + case 1000000: + { + regval = SPIM_FREQUENCY_1MBPS; + break; + } + + case 2000000: + { + regval = SPIM_FREQUENCY_2MBPS; + break; + } + + case 4000000: + { + regval = SPIM_FREQUENCY_4MBPS; + break; + } + + case 8000000: + { + regval = SPIM_FREQUENCY_8MBPS; + break; + } + + case 16000000: + { + regval = SPIM_FREQUENCY_16MBPS; + break; + } + + case 32000000: + { + regval = SPIM_FREQUENCY_32MBPS; + break; + } + + default: + { + spierr("Frequency unsupported %" PRId32 "\n", frequency); + goto errout; + } + } + + /* Write register */ + + nrf91_spi_putreg(priv, NRF91_SPIM_FREQUENCY_OFFSET, regval); + + /* Save the frequency setting */ + + priv->frequency = frequency; + + spiinfo("Frequency %" PRId32 "\n", frequency); + +errout: + return priv->frequency; +} + +/**************************************************************************** + * Name: nrf91_spi_setmode + * + * Description: + * Set the SPI mode. see enum spi_mode_e for mode definitions + * + * Input Parameters: + * dev - Device-specific state data + * mode - The SPI mode requested + * + * Returned Value: + * Returns the actual frequency selected + * + ****************************************************************************/ + +static void nrf91_spi_setmode(struct spi_dev_s *dev, + enum spi_mode_e mode) +{ + struct nrf91_spidev_s *priv = (struct nrf91_spidev_s *)dev; + uint32_t regval = 0; + + spiinfo("mode=%d\n", mode); + + /* Has the mode changed? */ + + if (mode != priv->mode) + { + regval = nrf91_spi_getreg(priv, NRF91_SPIM_CONFIG_OFFSET); + regval &= ~(SPIM_CONFIG_CPHA | SPIM_CONFIG_CPOL); + + switch (mode) + { + case SPIDEV_MODE0: /* CPOL=0; CPHA=0 */ + { + break; + } + + case SPIDEV_MODE1: /* CPOL=0; CPHA=1 */ + { + regval |= SPIM_CONFIG_CPHA; + break; + } + + case SPIDEV_MODE2: /* CPOL=1; CPHA=0 */ + { + regval |= SPIM_CONFIG_CPOL; + break; + } + + case SPIDEV_MODE3: /* CPOL=1; CPHA=1 */ + { + regval |= SPIM_CONFIG_CPHA; + regval |= SPIM_CONFIG_CPOL; + break; + } + + default: + { + DEBUGPANIC(); + return; + } + } + + nrf91_spi_putreg(priv, NRF91_SPIM_CONFIG_OFFSET, regval); + + /* According to manual we have to set SCK pin output + * value the same as CPOL value + */ + + if (mode == SPIDEV_MODE2 || mode == SPIDEV_MODE3) + { + nrf91_gpio_write(priv->sck_pin, true); + } + else + { + nrf91_gpio_write(priv->sck_pin, false); + } + + priv->mode = mode; + } +} + +/**************************************************************************** + * Name: nrf91_spi_setbits + * + * Description: + * Set the number of bits per word. + * + * Input Parameters: + * dev - Device-specific state data + * nbits - The number of bits requested + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void nrf91_spi_setbits(struct spi_dev_s *dev, int nbits) +{ + if (nbits != 8) + { + spierr("ERROR: nbits not supported: %d\n", nbits); + } +} + +/**************************************************************************** + * Name: nrf91_spi_hwfeatures + * + * Description: + * Set hardware-specific feature flags. + * + * Input Parameters: + * dev - Device-specific state data + * features - H/W feature flags + * + * Returned Value: + * Zero (OK) if the selected H/W features are enabled; A negated errno + * value if any H/W feature is not supportable. + * + ****************************************************************************/ + +#ifdef CONFIG_SPI_HWFEATURES +static int nrf91_spi_hwfeatures(struct spi_dev_s *dev, + spi_hwfeatures_t features) +{ +#ifdef CONFIG_SPI_BITORDER + struct nrf91_spidev_s *priv = (struct nrf91_spidev_s *)dev; + uint32_t setbits = 0; + uint32_t clrbits = 0; + uint32_t regval; + + spiinfo("features=%08x\n", features); + + /* Transfer data LSB first? */ + + if ((features & HWFEAT_LSBFIRST) != 0) + { + setbits = SPIM_CONFIG_ORDER; + clrbits = 0; + } + else + { + setbits = 0; + clrbits = SPIM_CONFIG_ORDER; + } + + regval = nrf91_spi_getreg(priv, NRF91_SPIM_CONFIG_OFFSET); + regval &= ~clrbits; + regval |= setbits; + nrf91_spi_putreg(priv, NRF91_SPIM_CONFIG_OFFSET, regval); + +#endif + /* Other H/W features are not supported */ + + return ((features & ~HWFEAT_LSBFIRST) == 0) ? OK : -ENOSYS; +} +#endif + +/**************************************************************************** + * Name: n4f52_spi_send + * + * Description: + * Exchange one word on SPI + * + * Input Parameters: + * dev - Device-specific state data + * wd - The word to send. the size of the data is determined by the + * number of bits selected for the SPI interface. + * + * Returned Value: + * response + * + ****************************************************************************/ + +static uint32_t nrf91_spi_send(struct spi_dev_s *dev, uint32_t wd) +{ + uint32_t ret = 0; + + /* Exchange one word on SPI */ + + nrf91_spi_exchange(dev, &wd, &ret, 1); + + return ret; +} + +/**************************************************************************** + * Name: nrf91_spi_exchange + * + * Description: + * Exchange a block of data on SPI without using DMA + * + * Input Parameters: + * dev - Device-specific state data + * txbuffer - A pointer to the buffer of data to be sent + * rxbuffer - A pointer to a buffer in which to receive data + * nwords - the length of data to be exchanged in units of words. + * The wordsize is determined by the number of bits-per-word + * selected for the SPI interface. + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void nrf91_spi_exchange(struct spi_dev_s *dev, + const void *txbuffer, + void *rxbuffer, size_t nwords) +{ + struct nrf91_spidev_s *priv = (struct nrf91_spidev_s *)dev; + uint32_t regval = 0; + size_t nwords_left = nwords; + + if (rxbuffer != NULL) + { + /* Write RXD data pointer */ + + regval = (uint32_t)rxbuffer; + DEBUGASSERT(nrf91_easydma_valid(regval)); + nrf91_spi_putreg(priv, NRF91_SPIM_RXDPTR_OFFSET, regval); + } + else + { + nrf91_spi_putreg(priv, NRF91_SPIM_RXDMAXCNT_OFFSET, 0); + } + + if (txbuffer != NULL) + { + /* Write TXD data pointer */ + + regval = (uint32_t)txbuffer; + DEBUGASSERT(nrf91_easydma_valid(regval)); + nrf91_spi_putreg(priv, NRF91_SPIM_TXDPTR_OFFSET, regval); + } + else + { + nrf91_spi_putreg(priv, NRF91_SPIM_TXDMAXCNT_OFFSET, 0); + } + + /* If more than 255 bytes, enable list mode to send data + * in batches + */ + + if (nwords > 0xff) + { + if (rxbuffer != NULL) + { + nrf91_spi_putreg(priv, NRF91_SPIM_RXDLIST_OFFSET, 1); + } + + if (txbuffer != NULL) + { + nrf91_spi_putreg(priv, NRF91_SPIM_TXDLIST_OFFSET, 1); + } + } + + while (nwords_left > 0) + { + size_t transfer_size = (nwords_left > 255 ? 255 : nwords_left); + + if (rxbuffer != NULL) + { + /* Write number of bytes in RXD buffer */ + + nrf91_spi_putreg(priv, NRF91_SPIM_RXDMAXCNT_OFFSET, transfer_size); + } + + if (txbuffer != NULL) + { + /* Write number of bytes in TXD buffer */ + + nrf91_spi_putreg(priv, NRF91_SPIM_TXDMAXCNT_OFFSET, transfer_size); + } + + /* SPI start */ + + nrf91_spi_putreg(priv, NRF91_SPIM_TASK_START_OFFSET, SPIM_TASKS_START); + +#ifndef CONFIG_NRF91_SPI_MASTER_INTERRUPTS + /* Wait for RX done and TX done */ + + while (nrf91_spi_getreg(priv, NRF91_SPIM_EVENTS_END_OFFSET) != 1); + + /* Clear event */ + + nrf91_spi_putreg(priv, NRF91_SPIM_EVENTS_END_OFFSET, 0); +#else + /* Wait for transfer complete */ + + nxsem_wait_uninterruptible(&priv->sem_isr); +#endif + + if (nrf91_spi_getreg(priv, NRF91_SPIM_TXDAMOUNT_OFFSET) != + transfer_size) + { + spierr("Incomplete transfer wrote %" PRId32 " expected %zu\n", + regval, nwords); + } + + /* SPI stop */ + + nrf91_spi_putreg(priv, NRF91_SPIM_TASK_STOP_OFFSET, SPIM_TASKS_STOP); + + /* Wait for STOP event */ + + while (nrf91_spi_getreg(priv, NRF91_SPIM_EVENTS_STOPPED_OFFSET) != 1); + + /* Clear event */ + + nrf91_spi_putreg(priv, NRF91_SPIM_EVENTS_STOPPED_OFFSET, 0); + + nwords_left -= transfer_size; + } + + /* Clear RX/TX DMA after transfer */ + + nrf91_spi_putreg(priv, NRF91_SPIM_RXDPTR_OFFSET, 0); + nrf91_spi_putreg(priv, NRF91_SPIM_RXDMAXCNT_OFFSET, 0); + nrf91_spi_putreg(priv, NRF91_SPIM_TXDPTR_OFFSET, 0); + nrf91_spi_putreg(priv, NRF91_SPIM_TXDMAXCNT_OFFSET, 0); + + /* Clear list mode */ + + if (nwords > 0xff) + { + nrf91_spi_putreg(priv, NRF91_SPIM_RXDLIST_OFFSET, 0); + nrf91_spi_putreg(priv, NRF91_SPIM_TXDLIST_OFFSET, 0); + } +} + +#ifndef CONFIG_SPI_EXCHANGE + +/**************************************************************************** + * Name: nrf91_spi_sndblock + * + * Description: + * Send a block of data on SPI + * + * Input Parameters: + * dev - Device-specific state data + * txbuffer - A pointer to the buffer of data to be sent + * nwords - the length of data to send from the buffer in number of + * words. The wordsize is determined by the number of + * bits-per-word selected for the SPI interface. + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void nrf91_spi_sndblock(struct spi_dev_s *dev, + const void *txbuffer, + size_t nwords) +{ + spiinfo("txbuffer=%p nwords=%zu\n", txbuffer, nwords); + return nrf91_spi_exchange(dev, txbuffer, NULL, nwords); +} + +/**************************************************************************** + * Name: nrf91_spi_recvblock + * + * Description: + * Receive a block of data from SPI + * + * Input Parameters: + * dev - Device-specific state data + * rxbuffer - A pointer to the buffer in which to receive data + * nwords - the length of data that can be received in the buffer in + * number of words. The wordsize is determined by the number of + * bits-per-word selected for the SPI interface. + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void nrf91_spi_recvblock(struct spi_dev_s *dev, + void *rxbuffer, + size_t nwords) +{ + spiinfo("txbuffer=%p nwords=%zu\n", rxbuffer, nwords); + return nrf91_spi_exchange(dev, NULL, rxbuffer, nwords); +} +#endif /* CONFIG_SPI_EXCHANGE */ + +/**************************************************************************** + * Name: nrf91_spi_trigger + * + * Description: + * Trigger a previously configured DMA transfer. + * + * Input Parameters: + * dev - Device-specific state data + * + * Returned Value: + * OK - Trigger was fired + * -ENOSYS - Trigger not fired due to lack of DMA or low level support + * -EIO - Trigger not fired because not previously primed + * + ****************************************************************************/ + +#ifdef CONFIG_SPI_TRIGGER +static int nrf91_spi_trigger(struct spi_dev_s *dev) +{ + return -ENOSYS; +} +#endif + +#ifdef CONFIG_PM +/**************************************************************************** + * Name: nrf91_spi_pm_prepare + ****************************************************************************/ + +static int nrf91_spi_pm_prepare(struct pm_callback_s *cb, int domain, + enum pm_state_e pmstate) +{ + if (pmstate == PM_STANDBY || pmstate == PM_SLEEP) + { + bool active = false; + +#ifdef CONFIG_NRF91_SPI0_MASTER + active |= nrf91_spi_getreg(&g_spi0dev, SPIM_EVENTS_STARTED); +#endif +#ifdef CONFIG_NRF91_SPI1_MASTER + active |= nrf91_spi_getreg(&g_spi1dev, SPIM_EVENTS_STARTED); +#endif +#ifdef CONFIG_NRF91_SPI2_MASTER + active |= nrf91_spi_getreg(&g_spi2dev, SPIM_EVENTS_STARTED); +#endif +#ifdef CONFIG_NRF91_SPI3_MASTER + active |= nrf91_spi_getreg(&g_spi3dev, SPIM_EVENTS_STARTED); +#endif +#ifdef CONFIG_NRF91_SPI4_MASTER + active |= nrf91_spi_getreg(&g_spi4dev, SPIM_EVENTS_STARTED); +#endif + + if (active) + { + /* SPI is being used, cannot disable */ + + return -1; + } + else + { + /* SPI is inactive, can go to sleep */ + + return 0; + } + } + else + { + /* We can always go to any other state */ + + return 0; + } +} + +/**************************************************************************** + * Name: nrf91_spi_pm_notify + ****************************************************************************/ + +static void nrf91_spi_pm_notify(struct pm_callback_s *cb, int domain, + enum pm_state_e pmstate) +{ + if (pmstate == PM_SLEEP || pmstate == PM_STANDBY) + { + /* Deinit SPI peripheral on each initialized device */ + +#ifdef CONFIG_NRF91_SPI0_MASTER + if (g_spi0dev.initialized) + { + nrf91_spi_deinit(&g_spi0dev); + } +#endif + +#ifdef CONFIG_NRF91_SPI1_MASTER + if (g_spi1dev.initialized) + { + nrf91_spi_deinit(&g_spi1dev); + } +#endif + +#ifdef CONFIG_NRF91_SPI2_MASTER + if (g_spi2dev.initialized) + { + nrf91_spi_deinit(&g_spi2dev); + } +#endif + +#ifdef CONFIG_NRF91_SPI3_MASTER + if (g_spi3dev.initialized) + { + nrf91_spi_deinit(&g_spi3dev); + } +#endif + +#ifdef CONFIG_NRF91_SPI4_MASTER + if (g_spi4dev.initialized) + { + nrf91_spi_deinit(&g_spi4dev); + } +#endif + } + else + { + /* Reinit SPI peripheral on each initialized device */ + +#ifdef CONFIG_NRF91_SPI0_MASTER + if (g_spi0dev.initialized) + { + nrf91_spi_init(&g_spi0dev); + } +#endif + +#ifdef CONFIG_NRF91_SPI1_MASTER + if (g_spi1dev.initialized) + { + nrf91_spi_init(&g_spi1dev); + } +#endif + +#ifdef CONFIG_NRF91_SPI2_MASTER + if (g_spi2dev.initialized) + { + nrf91_spi_init(&g_spi2dev); + } +#endif + +#ifdef CONFIG_NRF91_SPI3_MASTER + if (g_spi3dev.initialized) + { + nrf91_spi_init(&g_spi3dev); + } +#endif + +#ifdef CONFIG_NRF91_SPI4_MASTER + if (g_spi4dev.initialized) + { + nrf91_spi_init(&g_spi4dev); + } +#endif + } +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nrf91_spibus_initialize + * + * Description: + * Initialize the selected SPI port. + * + * Input Parameters: + * Port number (for hardware that has multiple SPI interfaces) + * + * Returned Value: + * Valid SPI device structure reference on success; a NULL on failure + * + ****************************************************************************/ + +struct spi_dev_s *nrf91_spibus_initialize(int port) +{ + struct nrf91_spidev_s *priv = NULL; + + /* Get SPI driver data */ + + switch (port) + { +#ifdef CONFIG_NRF91_SPI0_MASTER + case 0: + { + priv = &g_spi0dev; + break; + } +#endif + +#ifdef CONFIG_NRF91_SPI1_MASTER + case 1: + { + priv = &g_spi1dev; + break; + } +#endif + +#ifdef CONFIG_NRF91_SPI2_MASTER + case 2: + { + priv = &g_spi2dev; + break; + } +#endif + +#ifdef CONFIG_NRF91_SPI3_MASTER + case 3: + { + priv = &g_spi3dev; + break; + } +#endif + +#ifdef CONFIG_NRF91_SPI4_MASTER + case 4: + { + priv = &g_spi4dev; + break; + } +#endif + + default: + { + goto errout; + } + } + + /* Initialize the SPI */ + + nrf91_spi_init(priv); + + /* Mark device as initialized */ + + priv->initialized = true; + +#ifdef CONFIG_NRF91_SPI_MASTER_INTERRUPTS + /* Attach SPI interrupt */ + + irq_attach(priv->irq, nrf91_spi_isr, priv); + up_enable_irq(priv->irq); +#endif + +errout: + return (struct spi_dev_s *)priv; +} diff --git a/arch/arm/src/nrf91/nrf91_spi.h b/arch/arm/src/nrf91/nrf91_spi.h new file mode 100644 index 0000000000..e2acc3e5bd --- /dev/null +++ b/arch/arm/src/nrf91/nrf91_spi.h @@ -0,0 +1,165 @@ +/**************************************************************************** + * arch/arm/src/nrf91/nrf91_spi.h + * + * 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. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_NRF91_NRF91_SPI_H +#define __ARCH_ARM_SRC_NRF91_NRF91_SPI_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include "chip.h" + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: nrf91_spibus_initialize + * + * Description: + * Initialize the selected SPI port. + * + * Input Parameters: + * Port number (for hardware that has multiple SPI interfaces) + * + * Returned Value: + * Valid SPI device structure reference on success; a NULL on failure + * + ****************************************************************************/ + +struct spi_dev_s *nrf91_spibus_initialize(int port); + +/**************************************************************************** + * Name: nrf91_spi0/1/...select and nrf91_spi0/1/...status + * + * Description: + * The external functions, nrf91_spi0/1/...select, nrf91_spi0/1/...status, + * and nrf91_spi0/1/...cmddata must be provided by board-specific logic. + * These are implementations of the select, status, and cmddata methods of + * the SPI interface defined by struct spi_ops_s (include/nuttx/spi/spi.h). + * All other methods (including nrf91_spibus_initialize()) are provided by + * common NRF91 logic. To use this common SPI logic on your board: + * + * 1. Provide logic in nrf91_boardinitialize() to configure SPI chip select + * pins. + * 2. Provide nrf91_spi0/1/...select() and nrf91_spi0/1/...status() + * functions in your board-specific logic. These functions will perform + * chip selection and status operations using GPIOs in the way your + * board is configured. + * 3. If CONFIG_SPI_CMDDATA is defined in your NuttX configuration file, + * then provide nrf91_spi0/1/...cmddata() functions in your + * board-specific logic. These functions will perform cmd/data selection + * operations using GPIOs in the way your board is configured. + * 4. Add a calls to nrf91_spibus_initialize() in your low level + * application initialization logic. + * 5. The handle returned by nrf91_spibus_initialize() may then be used to + * bind the SPI driver to higher level logic (e.g., calling + * mmcsd_spislotinitialize(), for example, will bind the SPI driver to + * the SPI MMC/SD driver). + * + ****************************************************************************/ + +#ifdef CONFIG_NRF91_SPI0_MASTER +void nrf91_spi0select(struct spi_dev_s *dev, uint32_t devid, + bool selected); +uint8_t nrf91_spi0status(struct spi_dev_s *dev, uint32_t devid); +int nrf91_spi0cmddata(struct spi_dev_s *dev, uint32_t devid, bool cmd); +#endif + +#ifdef CONFIG_NRF91_SPI1_MASTER +void nrf91_spi1select(struct spi_dev_s *dev, uint32_t devid, + bool selected); +uint8_t nrf91_spi1status(struct spi_dev_s *dev, uint32_t devid); +int nrf91_spi1cmddata(struct spi_dev_s *dev, uint32_t devid, bool cmd); +#endif + +#ifdef CONFIG_NRF91_SPI2_MASTER +void nrf91_spi2select(struct spi_dev_s *dev, uint32_t devid, + bool selected); +uint8_t nrf91_spi2status(struct spi_dev_s *dev, uint32_t devid); +int nrf91_spi2cmddata(struct spi_dev_s *dev, uint32_t devid, bool cmd); +#endif + +#ifdef CONFIG_NRF91_SPI3_MASTER +void nrf91_spi3select(struct spi_dev_s *dev, uint32_t devid, + bool selected); +uint8_t nrf91_spi3status(struct spi_dev_s *dev, uint32_t devid); +int nrf91_spi3cmddata(struct spi_dev_s *dev, uint32_t devid, bool cmd); +#endif + +#ifdef CONFIG_NRF91_SPI4_MASTER +void nrf91_spi4select(struct spi_dev_s *dev, uint32_t devid, + bool selected); +uint8_t nrf91_spi4status(struct spi_dev_s *dev, uint32_t devid); +int nrf91_spi4cmddata(struct spi_dev_s *dev, uint32_t devid, bool cmd); +#endif + +/**************************************************************************** + * Name: nrf91_spi0/1/2/3register + * + * Description: + * If the board supports a card detect callback to inform the SPI-based + * MMC/SD driver when an SD card is inserted or removed, then + * CONFIG_SPI_CALLBACK should be defined and the following function(s) must + * be implemented. These functions implements the registercallback method + * of the SPI interface (see include/nuttx/spi/spi.h for details) + * + * Input Parameters: + * dev - Device-specific state data + * callback - The function to call on the media change + * arg - A caller provided value to return with the callback + * + * Returned Value: + * 0 on success; negated errno on failure. + * + ****************************************************************************/ + +#ifdef CONFIG_SPI_CALLBACK +#ifdef CONFIG_NRF91_SPI0_MASTER +int nrf91_spi0register(struct spi_dev_s *dev, spi_mediachange_t callback, + void *arg); +#endif + +#ifdef CONFIG_NRF91_SPI1_MASTER +int nrf91_spi1register(struct spi_dev_s *dev, spi_mediachange_t callback, + void *arg); +#endif + +#ifdef CONFIG_NRF91_SPI2_MASTER +int nrf91_spi2register(struct spi_dev_s *dev, spi_mediachange_t callback, + void *arg); +#endif + +#ifdef CONFIG_NRF91_SPI3_MASTER +int nrf91_spi3register(struct spi_dev_s *dev, spi_mediachange_t callback, + void *arg); +#endif + +#ifdef CONFIG_NRF91_SPI4_MASTER +int nrf91_spi4register(struct spi_dev_s *dev, spi_mediachange_t callback, + void *arg); +#endif +#endif + +#endif /* __ARCH_ARM_SRC_NRF91_NRF91_SPI_H */ diff --git a/arch/arm/src/nrf91/nrf91_spu.c b/arch/arm/src/nrf91/nrf91_spu.c new file mode 100644 index 0000000000..89f974d794 --- /dev/null +++ b/arch/arm/src/nrf91/nrf91_spu.c @@ -0,0 +1,190 @@ +/**************************************************************************** + * arch/arm/src/nrf91/nrf91_spu.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 "arm_internal.h" + +#include "hardware/nrf91_spu.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +#if defined(NRF91_SPU_NONSECURE) +/**************************************************************************** + * Name: nrf91_spu_mem_default + ****************************************************************************/ + +static void nrf91_spu_mem_default(void) +{ + int i = 0; + + /* Security attribute for FLASH */ + + for (i = CONFIG_NRF91_FLASH_NS_START; i < SPU_FLASH_REGIONS; i++) + { + modifyreg32(NRF91_SPU_FLASHREGIONPERM(i), + SPU_FLASHREGION_PERM_SECATTR, SPU_PERM_SECATTR); + } + + /* Security attribute for RAM */ + + for (i = CONFIG_NRF91_FLASH_NS_START; i < SPU_RAM_REGIONS; i++) + { + modifyreg32(NRF91_SPU_RAMREGIONPERM(i), + SPU_RAMREGION_PERM_SECATTR, SPU_PERM_SECATTR); + } +} + +/**************************************************************************** + * Name: nrf91_spu_periph + ****************************************************************************/ + +static void nrf91_spu_periph(void) +{ +#ifdef CONFIG_NRF91_POWERCLOCK_NS + modifyreg32(NRF91_SPU_PERIPHIDPERM(NRF91_POWER_CLOCK_ID), + SPU_PERIPHID_PERM_SECATTR, SPU_PERM_SECATTR); +#endif + +#ifdef CONFIG_NRF91_GPIO0_NS + modifyreg32(NRF91_SPU_PERIPHIDPERM(NRF91_GPIO0_ID), + SPU_PERIPHID_PERM_SECATTR, SPU_PERM_SECATTR); +#endif + +#ifdef CONFIG_NRF91_NVMC_NS + modifyreg32(NRF91_SPU_PERIPHIDPERM(NRF91_NVMC_ID), + SPU_PERIPHID_PERM_SECATTR, SPU_PERM_SECATTR); +#endif + +#ifdef CONFIG_NRF91_SERIAL0_NS + modifyreg32(NRF91_SPU_PERIPHIDPERM(NRF91_SERIAL0_ID), + SPU_PERIPHID_PERM_SECATTR, SPU_PERM_SECATTR); +#endif + +#ifdef CONFIG_NRF91_SERIAL1_NS + modifyreg32(NRF91_SPU_PERIPHIDPERM(NRF91_SERIAL1_ID), + SPU_PERIPHID_PERM_SECATTR, SPU_PERM_SECATTR); +#endif + +#ifdef CONFIG_NRF91_SERIAL2_NS + modifyreg32(NRF91_SPU_PERIPHIDPERM(NRF91_SERIAL2_ID), + SPU_PERIPHID_PERM_SECATTR, SPU_PERM_SECATTR); +#endif + +#ifdef CONFIG_NRF91_SERIAL3_NS + modifyreg32(NRF91_SPU_PERIPHIDPERM(NRF91_SERIAL3_ID), + SPU_PERIPHID_PERM_SECATTR, SPU_PERM_SECATTR); +#endif + +#ifdef CONFIG_NRF91_TIMER0_NS + modifyreg32(NRF91_SPU_PERIPHIDPERM(NRF91_TIMER0_ID), + SPU_PERIPHID_PERM_SECATTR, SPU_PERM_SECATTR); +#endif + +#ifdef CONFIG_NRF91_TIMER1_NS + modifyreg32(NRF91_SPU_PERIPHIDPERM(NRF91_TIMER1_ID), + SPU_PERIPHID_PERM_SECATTR, SPU_PERM_SECATTR); +#endif + +#ifdef CONFIG_NRF91_TIMER2_NS + modifyreg32(NRF91_SPU_PERIPHIDPERM(NRF91_TIMER2_ID), + SPU_PERIPHID_PERM_SECATTR, SPU_PERM_SECATTR); +#endif + +#ifdef CONFIG_NRF91_RTC0_NS + modifyreg32(NRF91_SPU_PERIPHIDPERM(NRF91_RTC0_ID), + SPU_PERIPHID_PERM_SECATTR, SPU_PERM_SECATTR); +#endif + +#ifdef CONFIG_NRF91_RTC1_NS + modifyreg32(NRF91_SPU_PERIPHIDPERM(NRF91_RTC1_ID), + SPU_PERIPHID_PERM_SECATTR, SPU_PERM_SECATTR); +#endif + +#ifdef CONFIG_NRF91_WDT0_NS + modifyreg32(NRF91_SPU_PERIPHIDPERM(NRF91_WDT0_ID), + SPU_PERIPHID_PERM_SECATTR, SPU_PERM_SECATTR); +#endif + +#ifdef CONFIG_NRF91_WDT1_NS + modifyreg32(NRF91_SPU_PERIPHIDPERM(NRF91_WDT1_ID), + SPU_PERIPHID_PERM_SECATTR, SPU_PERM_SECATTR); +#endif + +#ifdef CONFIG_NRF91_PWM0_NS + modifyreg32(NRF91_SPU_PERIPHIDPERM(NRF91_PWM0_ID), + SPU_PERIPHID_PERM_SECATTR, SPU_PERM_SECATTR); +#endif + +#ifdef CONFIG_NRF91_PWM1_NS + modifyreg32(NRF91_SPU_PERIPHIDPERM(NRF91_PWM1_ID), + SPU_PERIPHID_PERM_SECATTR, SPU_PERM_SECATTR); +#endif + +#ifdef CONFIG_NRF91_PWM2_NS + modifyreg32(NRF91_SPU_PERIPHIDPERM(NRF91_PWM2_ID), + SPU_PERIPHID_PERM_SECATTR, SPU_PERM_SECATTR); +#endif + +#ifdef CONFIG_NRF91_IPC_NS + modifyreg32(NRF91_SPU_PERIPHIDPERM(NRF91_IPC_ID), + SPU_PERIPHID_PERM_SECATTR, SPU_PERM_SECATTR); +#endif + + /* Make all GPIO non-secure */ + + modifyreg32(NRF91_SPU_GPIOPORTPERM(0), 0xffffffff, 0); +} +#endif /* NRF91_CONFIG_NONSECURE */ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nrf91_spu_configure + ****************************************************************************/ + +void nrf91_spu_configure(void) +{ +#if defined(NRF91_SPU_NONSECURE) + /* Peripheral configuration */ + + nrf91_spu_periph(); + + /* Memory SPU configuration */ + + nrf91_spu_mem_default(); +#elif defined(CONFIG_NRF91_SPU_CUSTOM) + /* User-specific SPU configuration */ + + board_spu_configure(); +#endif +} diff --git a/arch/arm/src/nrf91/nrf91_spu.h b/arch/arm/src/nrf91/nrf91_spu.h new file mode 100644 index 0000000000..010d7a0d71 --- /dev/null +++ b/arch/arm/src/nrf91/nrf91_spu.h @@ -0,0 +1,43 @@ +/**************************************************************************** + * arch/arm/src/nrf91/nrf91_spu.h + * + * 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 + +/**************************************************************************** + * Public Functions Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: nrf91_spu_configure + ****************************************************************************/ + +void nrf91_spu_configure(void); + +#ifdef CONFIG_NRF91_SPU_CUSTOM +/**************************************************************************** + * Name: board_spu_configure + ****************************************************************************/ + +void board_spu_configure(void); +#endif diff --git a/arch/arm/src/nrf91/nrf91_start.c b/arch/arm/src/nrf91/nrf91_start.c new file mode 100644 index 0000000000..2572ece771 --- /dev/null +++ b/arch/arm/src/nrf91/nrf91_start.c @@ -0,0 +1,260 @@ +/**************************************************************************** + * arch/arm/src/nrf91/nrf91_start.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 "arm_internal.h" +#include "nvic.h" + +#include "nrf91_clockconfig.h" +#include "hardware/nrf91_nvmc.h" +#include "hardware/nrf91_utils.h" +#include "hardware/nrf91_uicr.h" +#include "nrf91_lowputc.h" +#include "nrf91_start.h" +#include "nrf91_gpio.h" +#include "nrf91_serial.h" +#ifndef CONFIG_ARCH_TRUSTZONE_NONSECURE +# include "nrf91_spu.h" +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Name: showprogress + * + * Description: + * Print a character on the UART to show boot status. + * + ****************************************************************************/ + +#ifdef CONFIG_DEBUG_FEATURES +# define showprogress(c) arm_lowputc(c) +#else +# define showprogress(c) +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +#ifdef CONFIG_ARMV8M_STACKCHECK +/* we need to get r10 set before we can allow instrumentation calls */ + +void __start(void) noinstrument_function; +#endif + +/**************************************************************************** + * Name: nrf91_approtect + ****************************************************************************/ + +static void nrf91_approtect(void) +{ + /* TODO: missing logic */ +} + +#ifdef CONFIG_NRF91_FLASH_PREFETCH +/**************************************************************************** + * Name: nrf91_enable_icache + * + * Description: + * Enable I-Cache for Flash + * + * Input Parameter: + * enable - enable or disable I-Cache + * + * Returned Values: + * None + * + ****************************************************************************/ + +static void nrf91_enable_icache(bool enable) +{ + if (enable) + { + modifyreg32(NRF91_NVMC_ICACHECNF, 0, NVMC_ICACHECNF_CACHEEN); + } + else + { + modifyreg32(NRF91_NVMC_ICACHECNF, NVMC_ICACHECNF_CACHEEN, 0); + } +} + +/**************************************************************************** + * Name: nrf91_enable_profile + * + * Description: + * Enable profiling I-Cache for flash + * + * Input Parameter: + * enable - enable or disable profiling for I-Cache + * + * Returned Values: + * None + * + ****************************************************************************/ + +static void nrf91_enable_profile(bool enable) +{ + if (enable) + { + modifyreg32(NRF91_NVMC_ICACHECNF, 0, NVMC_ICACHECNF_CACHEPROFEN); + } + else + { + modifyreg32(NRF91_NVMC_ICACHECNF, NVMC_ICACHECNF_CACHEPROFEN, 0); + } +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: __start + * + * Description: + * This is the reset entry point. + * + ****************************************************************************/ + +void __start(void) +{ + const uint32_t *src; + uint32_t *dest; + +#ifdef CONFIG_ARMV8M_STACKCHECK + /* Set the stack limit before we attempt to call any functions */ + + __asm__ volatile("sub r10, sp, %0" : : + "r"(CONFIG_IDLETHREAD_STACKSIZE - 64) :); +#endif + + /* Make sure that interrupts are disabled */ + + __asm__ __volatile__ ("\tcpsid i\n"); + +#ifndef CONFIG_ARCH_TRUSTZONE_NONSECURE + /* Handle APPROTECT configuration */ + + nrf91_approtect(); + + /* Configure SPU */ + + nrf91_spu_configure(); +#endif + + /* Configure the clocking and the console uart so that we can get debug + * output as soon as possible. NOTE: That this logic must not assume that + * .bss or .data have beeninitialized. + */ + + nrf91_clockconfig(); + nrf91_lowsetup(); + showprogress('A'); + + /* Clear .bss. We'll do this inline (vs. calling memset) just to be + * certain that there are no issues with the state of global variables. + */ + + for (dest = (uint32_t *)_sbss; dest < (uint32_t *)_ebss; ) + { + *dest++ = 0; + } + + showprogress('B'); + + /* Move the initialized data section from his temporary holding spot in + * FLASH into the correct place in SRAM. The correct place in SRAM is + * give by _sdata and _edata. The temporary location is in FLASH at the + * end of all of the other read-only data (.text, .rodata) at _eronly. + */ + + for (src = (const uint32_t *)_eronly, + dest = (uint32_t *)_sdata; dest < (uint32_t *)_edata; + ) + { + *dest++ = *src++; + } + + showprogress('C'); + +#ifdef CONFIG_ARCH_HAVE_FPU + /* Initialize the FPU (if available) */ + + arm_fpuconfig(); +#endif + +#ifdef CONFIG_NRF91_FLASH_PREFETCH + nrf91_enable_icache(true); + nrf91_enable_profile(true); +#endif + + showprogress('D'); + +#ifdef USE_EARLYSERIALINIT + /* Perform early serial initialization */ + + nrf91_earlyserialinit(); +#endif + showprogress('E'); + +#ifdef CONFIG_BUILD_PROTECTED + /* For the case of the separate user-/kernel-space build, perform whatever + * platform specific initialization of the user memory is required. + * Normally this just means initializing the user space .data and .bss + * segments. + */ + + nrf91_userspace(); + showprogress('F'); +#endif + + /* Initialize onboard resources */ + + nrf91_board_initialize(); + showprogress('G'); + + /* Then start NuttX */ + + showprogress('\r'); + showprogress('\n'); + + nx_start(); + + /* Shouldn't get here */ + + for (; ; ); +} diff --git a/arch/arm/src/nrf91/nrf91_start.h b/arch/arm/src/nrf91/nrf91_start.h new file mode 100644 index 0000000000..deef288418 --- /dev/null +++ b/arch/arm/src/nrf91/nrf91_start.h @@ -0,0 +1,58 @@ +/**************************************************************************** + * arch/arm/src/nrf91/nrf91_start.h + * + * 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. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_NRF91_NRF91_START_H +#define __ARCH_ARM_SRC_NRF91_NRF91_START_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include +#include +#include + +#include "arm_internal.h" +#include "chip.h" + +#ifndef __ASSEMBLY__ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: nrf91_board_initialize + * + * Description: + * All NRF91xxx architectures must provide the following entry point. + * This entry point is called early in the initialization -- after clocking + * and memory have been configured but before caches have been enabled and + * before any devices have been initialized. + * + ****************************************************************************/ + +void nrf91_board_initialize(void); + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_SRC_NRF91_NRF91_START_H */ diff --git a/arch/arm/src/nrf91/nrf91_systick.c b/arch/arm/src/nrf91/nrf91_systick.c new file mode 100644 index 0000000000..bf6816693d --- /dev/null +++ b/arch/arm/src/nrf91/nrf91_systick.c @@ -0,0 +1,63 @@ +/**************************************************************************** + * arch/arm/src/nrf91/nrf91_systick.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 "systick.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: up_timer_initialize + * + * Description: + * This function is called during start-up to initialize + * the timer interrupt. + * + ****************************************************************************/ + +void up_timer_initialize(void) +{ + /* Use SysTick to drive system timer */ + + up_timer_set_lowerhalf(systick_initialize(true, BOARD_SYSTICK_CLOCK, -1)); +} diff --git a/arch/arm/src/nrf91/nrf91_tickless_rtc.c b/arch/arm/src/nrf91/nrf91_tickless_rtc.c new file mode 100644 index 0000000000..eb9a40738e --- /dev/null +++ b/arch/arm/src/nrf91/nrf91_tickless_rtc.c @@ -0,0 +1,342 @@ +/**************************************************************************** + * arch/arm/src/nrf91/nrf91_tickless_rtc.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 "arm_internal.h" +#include "hardware/nrf91_rtc.h" +#include "nrf91_rtc.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Check configuration */ + +#ifdef CONFIG_TIMER_ARCH +# error CONFIG_TIMER_ARCH must be not set +#endif + +/* Check corresponding RTC support */ + +#if (CONFIG_NRF91_SYSTIMER_RTC_INSTANCE == 0) && !defined(CONFIG_NRF91_RTC0) +# error "Support for RTC0 is not enabled" +#elif (CONFIG_NRF91_SYSTIMER_RTC_INSTANCE == 1) && !defined(CONFIG_NRF91_RTC1) +# error "Support for RTC1 is not enabled" +#endif + +#define NRF91_RTC_PERIOD (512) +#define NRF91_RTC_MAX (0x00ffffff) +#define NRF91_RTC_MAX_TIME (NRF91_RTC_MAX * 31) + +/* Convert uS to timer count for f = 32768Hz, using more precision + * when possible: + * (1 / 32768) s ~ 30.51 uS ~ 31 uS + * 512 * (1 / 32768) s = 0.015625 s = 15625 uS + * So, instead of always dividing by 31, if t * 512 < (2**32 - 1), we can do: + * (t * 512) / 15625 ~ t / 30.51 + */ + +#define USEC_TO_COUNTER(t) (t > 0x7fffff ? (t / 31) : ((t * 512) / 15625)) + +/* To convert from counter to uS we split the counter into one second worth + * of counts (32768) and a fractional part we can safely multiply first + * by (USEC_PER_SEC/8) and still be within 32 bit value + */ + +#define COUNTER_TO_USEC(c) ((c / 32768) * USEC_PER_SEC) + \ + (((c % 32768) * (USEC_PER_SEC / 8)) / (32768 / 8)) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct nrf91_tickless_dev_s +{ + struct nrf91_rtc_dev_s *rtc; /* nrf91 RTC driver */ + uint32_t periods; /* how many times the timer overflowed */ + bool alarm_set; /* is the alarm set? */ + struct timespec alarm; /* absolute time of alarm */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int rtc_handler(int irq, void *context, void *arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +struct nrf91_tickless_dev_s g_tickless_dev; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static inline void rtc_counter_to_ts(uint32_t counter, struct timespec *now) +{ + uint32_t usec; + + usec = COUNTER_TO_USEC(counter); + now->tv_sec = usec / USEC_PER_SEC; + now->tv_nsec = (usec % USEC_PER_SEC) * NSEC_PER_USEC; + + now->tv_sec += g_tickless_dev.periods * NRF91_RTC_PERIOD; +} + +static void rtc_prepare_alarm(void) +{ + struct timespec now; + struct timespec delta; + uint32_t usec; + uint32_t counter; + uint32_t target_counter; + const uint32_t rtc_base = NRF91_RTC_GETBASE(g_tickless_dev.rtc); + + /* Get current absolute time */ + + counter = NRF91_RTC_GETCOUNTER_REG(rtc_base); + rtc_counter_to_ts(counter, &now); + + /* Obtain relative time to alarm */ + + clock_timespec_subtract(&g_tickless_dev.alarm, &now, &delta); + usec = delta.tv_sec * USEC_PER_SEC + delta.tv_nsec / NSEC_PER_USEC; + + /* Check if the alarm is to expire within one RTC period, if so we can set + * the CC. + */ + + if (usec < NRF91_RTC_PERIOD * USEC_PER_SEC) + { + /* Obtain absolute number of microseconds of alarm within current + * RTC period. + */ + + usec = (g_tickless_dev.alarm.tv_sec % NRF91_RTC_PERIOD) * + USEC_PER_SEC + g_tickless_dev.alarm.tv_nsec / NSEC_PER_USEC; + + /* Compute counter value for that point in time */ + + target_counter = USEC_TO_COUNTER(usec); + + /* Enable interrupt. First set CC to distant value to ensure + * no match will be generated. Doing things this way we now that + * once we write a CC value it should be ready to match. + */ + + NRF91_RTC_SETCC_REG(rtc_base, 0, counter - 1); + NRF91_RTC_ENABLEINT(g_tickless_dev.rtc, NRF91_RTC_EVT_COMPARE0); + + /* Set CC to desired value */ + + NRF91_RTC_SETCC_REG(rtc_base, 0, target_counter); + + /* Ensure counter fires: from nrf91832_PS_v1.4 (p. 245) we know that + * "If the COUNTER is N, writing N+2 to a CC register is + * guaranteed to trigger a COMPARE event at N+2.", so anything + * less than that is not guaranteed and it may not ever match. + * + * To ensure this, we check if CC < N + 2, and if so we set CC = N+2. + * We repeat this until this is satisfied (as the counter may change + * in between calculations). + */ + + while (NRF91_RTC_GETCC_REG(rtc_base, 0) < + NRF91_RTC_GETCOUNTER_REG(rtc_base) + 2) + { + NRF91_RTC_SETCC_REG(rtc_base, 0, + NRF91_RTC_GETCOUNTER_REG(rtc_base) + 2); + } + } +} + +/**************************************************************************** + * Name: rtc_handler + ****************************************************************************/ + +static int rtc_handler(int irq, void *context, void *arg) +{ + irqstate_t flags; + + flags = enter_critical_section(); + + /* if the timer wrapped-around */ + + if (NRF91_RTC_CHECKINT(g_tickless_dev.rtc, NRF91_RTC_EVT_OVRFLW)) + { + /* ack interrupt */ + + NRF91_RTC_ACKINT(g_tickless_dev.rtc, NRF91_RTC_EVT_OVRFLW); + + /* count one more period */ + + g_tickless_dev.periods++; + + /* check if the currently set alarm is to fire in this new period */ + + if (g_tickless_dev.alarm_set) + { + rtc_prepare_alarm(); + } + } + + /* if the compare event fired */ + + if (NRF91_RTC_CHECKINT(g_tickless_dev.rtc, NRF91_RTC_EVT_COMPARE0)) + { + struct timespec now; + + /* cancel alarm and get current time */ + + up_alarm_cancel(&now); + + /* let scheduler now of alarm firing */ + + nxsched_alarm_expiration(&now); + } + + leave_critical_section(flags); + + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_alarm_cancel + ****************************************************************************/ + +int up_alarm_cancel(struct timespec *ts) +{ + uint32_t counter; + irqstate_t flags; + + flags = enter_critical_section(); + + NRF91_RTC_DISABLEINT(g_tickless_dev.rtc, NRF91_RTC_EVT_COMPARE0); + NRF91_RTC_GETCOUNTER(g_tickless_dev.rtc, &counter); + rtc_counter_to_ts(counter, ts); + + NRF91_RTC_ACKINT(g_tickless_dev.rtc, NRF91_RTC_EVT_COMPARE0); + g_tickless_dev.alarm_set = false; + + leave_critical_section(flags); + + return OK; +} + +/**************************************************************************** + * Name: up_alarm_start + ****************************************************************************/ + +int up_alarm_start(const struct timespec *ts) +{ + irqstate_t flags; + flags = enter_critical_section(); + + /* remember the alarm time */ + + g_tickless_dev.alarm_set = true; + g_tickless_dev.alarm = *ts; + + rtc_prepare_alarm(); + + leave_critical_section(flags); + + return OK; +} + +/**************************************************************************** + * Name: up_timer_gettime + ****************************************************************************/ + +int up_timer_gettime(struct timespec *ts) +{ + uint32_t counter; + irqstate_t flags; + + flags = enter_critical_section(); + + NRF91_RTC_GETCOUNTER(g_tickless_dev.rtc, &counter); + rtc_counter_to_ts(counter, ts); + + leave_critical_section(flags); + + return OK; +} + +/**************************************************************************** + * Name: up_timer_initialize + ****************************************************************************/ + +void up_timer_initialize(void) +{ + struct timespec ts; + + memset(&g_tickless_dev, 0, sizeof(struct nrf91_tickless_dev_s)); + + g_tickless_dev.rtc = nrf91_rtc_init(CONFIG_NRF91_SYSTIMER_RTC_INSTANCE); + + /* Ensure we have support for the selected RTC instance */ + + ASSERT(g_tickless_dev.rtc); + + /* Configure prescaler */ + + NRF91_RTC_SETPRE(g_tickless_dev.rtc, 0); + + /* Configure ISR */ + + NRF91_RTC_SETISR(g_tickless_dev.rtc, rtc_handler, NULL); + + /* Enable overflow interrupt */ + + NRF91_RTC_ENABLEINT(g_tickless_dev.rtc, NRF91_RTC_EVT_OVRFLW); + + /* Start counting */ + + NRF91_RTC_CLEAR(g_tickless_dev.rtc); + NRF91_RTC_ACKINT(g_tickless_dev.rtc, NRF91_RTC_EVT_OVRFLW); + NRF91_RTC_ACKINT(g_tickless_dev.rtc, NRF91_RTC_EVT_COMPARE0); + NRF91_RTC_START(g_tickless_dev.rtc); + + /* kick off alarm scheduling */ + + ts.tv_sec = ts.tv_nsec = 0; + nxsched_alarm_expiration(&ts); +} diff --git a/arch/arm/src/nrf91/nrf91_tim.c b/arch/arm/src/nrf91/nrf91_tim.c new file mode 100644 index 0000000000..c6e4684925 --- /dev/null +++ b/arch/arm/src/nrf91/nrf91_tim.c @@ -0,0 +1,857 @@ +/**************************************************************************** + * arch/arm/src/nrf91/nrf91_tim.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 "arm_internal.h" +#include "hardware/nrf91_tim.h" + +#include "nrf91_tim.h" + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct nrf91_tim_priv_s +{ + struct nrf91_tim_ops_s *ops; + uint32_t base; + uint32_t irq; + uint8_t chan; + bool inuse; +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* TIM registers access *****************************************************/ + +static uint32_t nrf91_tim_getreg(struct nrf91_tim_dev_s *dev, + uint32_t offset); +static void nrf91_tim_putreg(struct nrf91_tim_dev_s *dev, + uint32_t offset, + uint32_t value); + +/* TIM helpers **************************************************************/ + +static uint32_t nrf91_tim_irq2reg(struct nrf91_tim_dev_s *dev, + uint8_t s); + +/* TIM operations ***********************************************************/ + +static int nrf91_tim_start(struct nrf91_tim_dev_s *dev); +static int nrf91_tim_stop(struct nrf91_tim_dev_s *dev); +static int nrf91_tim_clear(struct nrf91_tim_dev_s *dev); +static int nrf91_tim_configure(struct nrf91_tim_dev_s *dev, uint8_t mode, + uint8_t width); +static int nrf91_tim_shorts(struct nrf91_tim_dev_s *dev, uint8_t s, + uint8_t i, bool en); +static int nrf91_tim_count(struct nrf91_tim_dev_s *dev); +static int nrf91_tim_setcc(struct nrf91_tim_dev_s *dev, uint8_t i, + uint32_t cc); +static int nrf91_tim_getcc(struct nrf91_tim_dev_s *dev, uint8_t i, + uint32_t *cc); +static int nrf91_tim_setpre(struct nrf91_tim_dev_s *dev, uint8_t pre); +static int nrf91_tim_setisr(struct nrf91_tim_dev_s *dev, xcpt_t handler, + void * arg); +static int nrf91_tim_enableint(struct nrf91_tim_dev_s *dev, uint8_t s); +static int nrf91_tim_disableint(struct nrf91_tim_dev_s *dev, uint8_t s); +static int nrf91_tim_checkint(struct nrf91_tim_dev_s *dev, uint8_t s); +static int nrf91_tim_ackint(struct nrf91_tim_dev_s *dev, uint8_t s); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* NRF91 TIM ops */ + +struct nrf91_tim_ops_s nrf91_tim_ops = +{ + .start = nrf91_tim_start, + .stop = nrf91_tim_stop, + .clear = nrf91_tim_clear, + .configure = nrf91_tim_configure, + .shorts = nrf91_tim_shorts, + .count = nrf91_tim_count, + .setcc = nrf91_tim_setcc, + .getcc = nrf91_tim_getcc, + .setpre = nrf91_tim_setpre, + .setisr = nrf91_tim_setisr, + .enableint = nrf91_tim_enableint, + .disableint = nrf91_tim_disableint, + .checkint = nrf91_tim_checkint, + .ackint = nrf91_tim_ackint +}; + +#ifdef CONFIG_NRF91_TIMER0 +/* TIMER0 */ + +struct nrf91_tim_priv_s g_nrf91_tim0_priv = +{ + .ops = &nrf91_tim_ops, + .base = NRF91_TIMER0_BASE, + .irq = NRF91_IRQ_TIMER0, + .chan = 4, + .inuse = false, +}; +#endif + +#ifdef CONFIG_NRF91_TIMER1 +/* TIMER1 */ + +struct nrf91_tim_priv_s g_nrf91_tim1_priv = +{ + .ops = &nrf91_tim_ops, + .base = NRF91_TIMER1_BASE, + .irq = NRF91_IRQ_TIMER1, + .chan = 4, + .inuse = false, +}; +#endif + +#ifdef CONFIG_NRF91_TIMER2 +/* TIMER2 */ + +struct nrf91_tim_priv_s g_nrf91_tim2_priv = +{ + .ops = &nrf91_tim_ops, + .base = NRF91_TIMER2_BASE, + .irq = NRF91_IRQ_TIMER2, + .chan = 4, + .inuse = false, +}; +#endif + +#ifdef CONFIG_NRF91_TIMER3 +/* TIMER3 */ + +struct nrf91_tim_priv_s g_nrf91_tim3_priv = +{ + .ops = &nrf91_tim_ops, + .base = NRF91_TIMER3_BASE, + .irq = NRF91_IRQ_TIMER3, + .chan = 6, + .inuse = false, +}; +#endif + +#ifdef CONFIG_NRF91_TIMER4 +/* TIMER4 */ + +struct nrf91_tim_priv_s g_nrf91_tim4_priv = +{ + .ops = &nrf91_tim_ops, + .base = NRF91_TIMER4_BASE, + .irq = NRF91_IRQ_TIMER4, + .chan = 6, + .inuse = false, +}; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nrf91_tim_getreg + * + * Description: + * Get a 32-bit register value by offset + * + ****************************************************************************/ + +static uint32_t nrf91_tim_getreg(struct nrf91_tim_dev_s *dev, + uint32_t offset) +{ + DEBUGASSERT(dev); + + return getreg32(((struct nrf91_tim_priv_s *)dev)->base + offset); +} + +/**************************************************************************** + * Name: nrf91_tim_putreg + * + * Description: + * Put a 32-bit register value by offset + * + ****************************************************************************/ + +static void nrf91_tim_putreg(struct nrf91_tim_dev_s *dev, + uint32_t offset, + uint32_t value) +{ + DEBUGASSERT(dev); + + putreg32(value, ((struct nrf91_tim_priv_s *)dev)->base + offset); +} + +/**************************************************************************** + * Name: nrf91_tim_irq2reg + * + * Description: + * Get the value of the interrupt register corresponding to the given + * interrupt source + * + ****************************************************************************/ + +static uint32_t nrf91_tim_irq2reg(struct nrf91_tim_dev_s *dev, uint8_t s) +{ + uint32_t regval = 0; + + switch (s) + { + case NRF91_TIM_INT_COMPARE0: + { + regval = TIM_INT_COMPARE(0); + break; + } + + case NRF91_TIM_INT_COMPARE1: + { + regval = TIM_INT_COMPARE(1); + break; + } + + case NRF91_TIM_INT_COMPARE2: + { + regval = TIM_INT_COMPARE(2); + break; + } + + case NRF91_TIM_INT_COMPARE3: + { + regval = TIM_INT_COMPARE(3); + break; + } + + case NRF91_TIM_INT_COMPARE4: + { + regval = TIM_INT_COMPARE(4); + break; + } + + case NRF91_TIM_INT_COMPARE5: + { + regval = TIM_INT_COMPARE(5); + break; + } + + default: + { + tmrerr("ERROR: unsupported IRQ source %d\n", s); + regval = 0; + goto errout; + } + } + +errout: + return regval; +} + +/**************************************************************************** + * Name: nrf91_tim_start + ****************************************************************************/ + +static int nrf91_tim_start(struct nrf91_tim_dev_s *dev) +{ + DEBUGASSERT(dev); + + nrf91_tim_putreg(dev, NRF91_TIM_TASKS_START_OFFSET, TIM_TASKS_START); + + return OK; +} + +/**************************************************************************** + * Name: nrf91_tim_stop + ****************************************************************************/ + +static int nrf91_tim_stop(struct nrf91_tim_dev_s *dev) +{ + DEBUGASSERT(dev); + + nrf91_tim_putreg(dev, NRF91_TIM_TASKS_STOP_OFFSET, TIM_TASKS_STOP); + + return OK; +} + +/**************************************************************************** + * Name: nrf91_tim_clear + ****************************************************************************/ + +static int nrf91_tim_clear(struct nrf91_tim_dev_s *dev) +{ + DEBUGASSERT(dev); + + nrf91_tim_putreg(dev, NRF91_TIM_TASKS_CLEAR_OFFSET, TIM_TASKS_CLEAR); + + return OK; +} + +/**************************************************************************** + * Name: nrf91_tim_configure + ****************************************************************************/ + +static int nrf91_tim_configure(struct nrf91_tim_dev_s *dev, uint8_t mode, + uint8_t width) +{ + uint32_t regval = 0; + int ret = OK; + + DEBUGASSERT(dev); + + /* Configure TIMER mode */ + + switch (mode) + { + case NRF91_TIM_MODE_UNUSED: + { + regval = 0; + break; + } + + case NRF91_TIM_MODE_TIMER: + { + regval = TIM_MODE_TIMER; + break; + } + + case NRF91_TIM_MODE_COUNTER: + { + regval = TIM_MODE_COUNTER; + break; + } + + case NRF91_TIM_MODE_LOWPOWER: + { + regval = TIM_MODE_LPCOUNTER; + break; + } + + default: + { + tmrerr("ERROR: unsupported TIMER mode %d\n", mode); + ret = -EINVAL; + goto errout; + } + } + + nrf91_tim_putreg(dev, NRF91_TIM_MODE_OFFSET, regval); + + /* Configure TIMER width */ + + switch (width) + { + case NRF91_TIM_WIDTH_16B: + { + regval = TIM_BITMODE_16B; + break; + } + + case NRF91_TIM_WIDTH_8B: + { + regval = TIM_BITMODE_8B; + break; + } + + case NRF91_TIM_WIDTH_24B: + { + regval = TIM_BITMODE_24B; + break; + } + + case NRF91_TIM_WIDTH_32B: + { + regval = TIM_BITMODE_32B; + break; + } + + default: + { + tmrerr("ERROR: unsupported TIMER width %d\n", width); + ret = -EINVAL; + goto errout; + } + } + + nrf91_tim_putreg(dev, NRF91_TIM_BITMODE_OFFSET, regval); + +errout: + return ret; +} + +/**************************************************************************** + * Name: nrf91_tim_shorts + ****************************************************************************/ + +static int nrf91_tim_shorts(struct nrf91_tim_dev_s *dev, uint8_t s, + uint8_t i, bool en) +{ + uint32_t regval = 0; + uint32_t val = 0; + int ret = OK; + + regval = nrf91_tim_getreg(dev, NRF91_TIM_SHORTS_OFFSET); + + switch (s) + { + case NRF91_TIM_SHORT_COMPARE_CLEAR: + { + val = TIM_SHORTS_COMPARE_CLEAR(i); + break; + } + + case NRF91_TIM_SHORT_COMPARE_STOP: + { + val = TIM_SHORTS_COMPARE_STOP(i); + break; + } + + default: + { + tmrerr("ERROR: unsupported SHORT %d\n", s); + ret = -EINVAL; + goto errout; + } + } + + if (en == true) + { + regval |= val; + } + else + { + regval &= ~val; + } + + nrf91_tim_putreg(dev, NRF91_TIM_SHORTS_OFFSET, regval); + +errout: + return ret; +} + +/**************************************************************************** + * Name: nrf91_tim_count + ****************************************************************************/ + +static int nrf91_tim_count(struct nrf91_tim_dev_s *dev) +{ + DEBUGASSERT(dev); + + nrf91_tim_putreg(dev, NRF91_TIM_TASKS_COUNT_OFFSET, TIM_TASKS_COUNT); + + return OK; +} + +/**************************************************************************** + * Name: nrf91_tim_setcc + ****************************************************************************/ + +static int nrf91_tim_setcc(struct nrf91_tim_dev_s *dev, uint8_t i, + uint32_t cc) +{ + struct nrf91_tim_priv_s *tim = NULL; + int ret = OK; + + DEBUGASSERT(dev); + + tim = (struct nrf91_tim_priv_s *)dev; + + /* Is the channel supported? */ + + if (i > tim->chan) + { + tmrerr("ERROR: unsupported TIMER channel %d\n", i); + ret = -EINVAL; + goto errout; + } + + nrf91_tim_putreg(dev, NRF91_TIM_CC_OFFSET(i), cc); + +errout: + return ret; +} + +/**************************************************************************** + * Name: nrf91_tim_getcc + ****************************************************************************/ + +static int nrf91_tim_getcc(struct nrf91_tim_dev_s *dev, uint8_t i, + uint32_t *cc) +{ + struct nrf91_tim_priv_s *tim = NULL; + int ret = OK; + + DEBUGASSERT(dev); + DEBUGASSERT(cc); + + tim = (struct nrf91_tim_priv_s *)dev; + + /* Is the channel supported? */ + + if (i > tim->chan) + { + tmrerr("ERROR: unsupported TIMER channel %d\n", i); + ret = -EINVAL; + goto errout; + } + + *cc = nrf91_tim_getreg(dev, NRF91_TIM_CC_OFFSET(i)); + +errout: + return ret; +} + +/**************************************************************************** + * Name: nrf91_tim_setpre + ****************************************************************************/ + +static int nrf91_tim_setpre(struct nrf91_tim_dev_s *dev, uint8_t pre) +{ + int ret = OK; + + DEBUGASSERT(dev); + + if (pre < NRF91_TIM_PRE_16000000 || pre > NRF91_TIM_PRE_31250) + { + tmrerr("ERROR: unsupported TIMER prescaler %d\n", pre); + ret = -EINVAL; + goto errout; + } + + nrf91_tim_putreg(dev, NRF91_TIM_PRESCALER_OFFSET, pre); + +errout: + return ret; +} + +/**************************************************************************** + * Name: nrf91_tim_setisr + ****************************************************************************/ + +static int nrf91_tim_setisr(struct nrf91_tim_dev_s *dev, xcpt_t handler, + void *arg) +{ + struct nrf91_tim_priv_s *tim = NULL; + int ret = OK; + + DEBUGASSERT(dev); + + tim = (struct nrf91_tim_priv_s *)dev; + + /* Disable interrupt when callback is removed */ + + if (!handler) + { + up_disable_irq(tim->irq); + irq_detach(tim->irq); + ret = OK; + goto errout; + } + + /* Otherwise set callback and enable interrupt */ + + irq_attach(tim->irq, handler, arg); + up_enable_irq(tim->irq); + +errout: + return ret; +} + +/**************************************************************************** + * Name: nrf91_tim_enableint + ****************************************************************************/ + +static int nrf91_tim_enableint(struct nrf91_tim_dev_s *dev, uint8_t s) +{ + uint32_t regval = 0; + int ret = OK; + + DEBUGASSERT(dev); + + /* Get register value for given interrupt source */ + + regval = nrf91_tim_irq2reg(dev, s); + if (regval == 0) + { + ret = -EINVAL; + goto errout; + } + + nrf91_tim_putreg(dev, NRF91_TIM_INTENSET_OFFSET, regval); + +errout: + return ret; +} + +/**************************************************************************** + * Name: nrf91_tim_disableint + ****************************************************************************/ + +static int nrf91_tim_disableint(struct nrf91_tim_dev_s *dev, uint8_t s) +{ + uint32_t regval = 0; + int ret = OK; + + DEBUGASSERT(dev); + + /* Get register value for given interrupt source */ + + regval = nrf91_tim_irq2reg(dev, s); + if (regval == 0) + { + ret = -EINVAL; + goto errout; + } + + nrf91_tim_putreg(dev, NRF91_TIM_INTCLR_OFFSET, regval); + +errout: + return ret; +} + +/**************************************************************************** + * Name: nrf91_tim_checkint + ****************************************************************************/ + +static int nrf91_tim_checkint(struct nrf91_tim_dev_s *dev, uint8_t s) +{ + int ret = 0; + + DEBUGASSERT(dev); + + switch (s) + { + case NRF91_TIM_INT_COMPARE0: + { + ret = nrf91_tim_getreg(dev, NRF91_TIM_EVENTS_COMPARE_OFFSET(0)); + break; + } + + case NRF91_TIM_INT_COMPARE1: + { + ret = nrf91_tim_getreg(dev, NRF91_TIM_EVENTS_COMPARE_OFFSET(0)); + break; + } + + case NRF91_TIM_INT_COMPARE2: + { + ret = nrf91_tim_getreg(dev, NRF91_TIM_EVENTS_COMPARE_OFFSET(2)); + break; + } + + case NRF91_TIM_INT_COMPARE3: + { + ret = nrf91_tim_getreg(dev, NRF91_TIM_EVENTS_COMPARE_OFFSET(3)); + break; + } + + case NRF91_TIM_INT_COMPARE4: + { + ret = nrf91_tim_getreg(dev, NRF91_TIM_EVENTS_COMPARE_OFFSET(4)); + break; + } + + case NRF91_TIM_INT_COMPARE5: + { + ret = nrf91_tim_getreg(dev, NRF91_TIM_EVENTS_COMPARE_OFFSET(5)); + break; + } + + default: + { + tmrerr("ERROR: unsupported IRQ source %d\n", s); + ret = -EINVAL; + goto errout; + } + } + +errout: + return ret; +} + +/**************************************************************************** + * Name: nrf91_tim_ackint + ****************************************************************************/ + +static int nrf91_tim_ackint(struct nrf91_tim_dev_s *dev, uint8_t s) +{ + int ret = 0; + + DEBUGASSERT(dev); + + switch (s) + { + case NRF91_TIM_INT_COMPARE0: + { + nrf91_tim_putreg(dev, NRF91_TIM_EVENTS_COMPARE_OFFSET(0), 0); + break; + } + + case NRF91_TIM_INT_COMPARE1: + { + nrf91_tim_putreg(dev, NRF91_TIM_EVENTS_COMPARE_OFFSET(1), 0); + break; + } + + case NRF91_TIM_INT_COMPARE2: + { + nrf91_tim_putreg(dev, NRF91_TIM_EVENTS_COMPARE_OFFSET(2), 0); + break; + } + + case NRF91_TIM_INT_COMPARE3: + { + nrf91_tim_putreg(dev, NRF91_TIM_EVENTS_COMPARE_OFFSET(3), 0); + break; + } + + case NRF91_TIM_INT_COMPARE4: + { + nrf91_tim_putreg(dev, NRF91_TIM_EVENTS_COMPARE_OFFSET(4), 0); + break; + } + + case NRF91_TIM_INT_COMPARE5: + { + nrf91_tim_putreg(dev, NRF91_TIM_EVENTS_COMPARE_OFFSET(5), 0); + break; + } + + default: + { + tmrerr("ERROR: unsupported IRQ source %d\n", s); + ret = -EINVAL; + goto errout; + } + } + +errout: + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nrf91_tim_init + * + * Description: + * Initialize TIMER device + * + ****************************************************************************/ + +struct nrf91_tim_dev_s *nrf91_tim_init(int timer) +{ + struct nrf91_tim_priv_s *tim = NULL; + + /* Get timer instance */ + + switch (timer) + { +#ifdef CONFIG_NRF91_TIMER0 + case 0: + { + tim = &g_nrf91_tim0_priv; + break; + } +#endif + +#ifdef CONFIG_NRF91_TIMER1 + case 1: + { + tim = &g_nrf91_tim1_priv; + break; + } +#endif + +#ifdef CONFIG_NRF91_TIMER2 + case 2: + { + tim = &g_nrf91_tim2_priv; + break; + } +#endif + +#ifdef CONFIG_NRF91_TIMER3 + case 3: + { + tim = &g_nrf91_tim3_priv; + break; + } +#endif + +#ifdef CONFIG_NRF91_TIMER4 + case 4: + { + tim = &g_nrf91_tim4_priv; + break; + } +#endif + + default: + { + tmrerr("ERROR: unsupported TIMER %d\n", timer); + goto errout; + } + } + + if (tim->inuse != false) + { + /* Timer already in use */ + + tim = NULL; + } + +errout: + return (struct nrf91_tim_dev_s *)tim; +} + +/**************************************************************************** + * Name: nrf91_tim_deinit + * + * Description: + * Deinit TIMER device + * + ****************************************************************************/ + +int nrf91_tim_deinit(struct nrf91_tim_dev_s *dev) +{ + struct nrf91_tim_priv_s *tim = NULL; + + DEBUGASSERT(dev); + + tim = (struct nrf91_tim_priv_s *)dev; + + tim->inuse = false; + + return OK; +} diff --git a/arch/arm/src/nrf91/nrf91_tim.h b/arch/arm/src/nrf91/nrf91_tim.h new file mode 100644 index 0000000000..4365e55a85 --- /dev/null +++ b/arch/arm/src/nrf91/nrf91_tim.h @@ -0,0 +1,172 @@ +/**************************************************************************** + * arch/arm/src/nrf91/nrf91_tim.h + * + * 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. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_NRF91_NRF91_TIM_H +#define __ARCH_ARM_SRC_NRF91_NRF91_TIM_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Helpers ******************************************************************/ + +#define NRF91_TIM_START(d) ((d)->ops->start(d)) +#define NRF91_TIM_STOP(d) ((d)->ops->stop(d)) +#define NRF91_TIM_CLEAR(d) ((d)->ops->clear(d)) +#define NRF91_TIM_CONFIGURE(d, m, w) ((d)->ops->configure(d, m, w)) +#define NRF91_TIM_SHORTS(d, s, i, e) ((d)->ops->shorts(d, s, i, e)) +#define NRF91_TIM_COUNT(d) ((d)->ops->count(d)) +#define NRF91_TIM_SETCC(d, i, cc) ((d)->ops->setcc(d, i, cc)) +#define NRF91_TIM_GETCC(d, i, cc) ((d)->ops->getcc(d, i, cc)) +#define NRF91_TIM_SETPRE(d, pre) ((d)->ops->setpre(d, pre)) +#define NRF91_TIM_SETISR(d, hnd, arg) ((d)->ops->setisr(d, hnd, arg)) +#define NRF91_TIM_ENABLEINT(d, s) ((d)->ops->enableint(d, s)) +#define NRF91_TIM_DISABLEINT(d, s) ((d)->ops->disableint(d, s)) +#define NRF91_TIM_CHECKINT(d, s) ((d)->ops->checkint(d, s)) +#define NRF91_TIM_ACKINT(d, s) ((d)->ops->ackint(d, s)) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* Timer mode */ + +enum nrf91_tim_mode_e +{ + NRF91_TIM_MODE_UNUSED = 0, + NRF91_TIM_MODE_TIMER = 1, + NRF91_TIM_MODE_COUNTER = 2, + NRF91_TIM_MODE_LOWPOWER = 3, +}; + +/* Timer bit width */ + +enum nrf91_tim_width_e +{ + NRF91_TIM_WIDTH_16B = 0, + NRF91_TIM_WIDTH_8B = 1, + NRF91_TIM_WIDTH_24B = 2, + NRF91_TIM_WIDTH_32B = 3, +}; + +/* Timer CC index */ + +enum nrf91_tim_cc_e +{ + NRF91_TIM_CC0 = 0, + NRF91_TIM_CC1 = 1, + NRF91_TIM_CC2 = 2, + NRF91_TIM_CC3 = 3, + NRF91_TIM_CC4 = 4, + NRF91_TIM_CC5 = 5 +}; + +/* Timer IRQ source */ + +enum nrf91_tim_irq_e +{ + NRF91_TIM_INT_COMPARE0 = 0, + NRF91_TIM_INT_COMPARE1 = 1, + NRF91_TIM_INT_COMPARE2 = 2, + NRF91_TIM_INT_COMPARE3 = 3, + NRF91_TIM_INT_COMPARE4 = 4, + NRF91_TIM_INT_COMPARE5 = 5, +}; + +/* Timer shorts type */ + +enum nrf91_tim_shorts_e +{ + NRF91_TIM_SHORT_COMPARE_CLEAR = 1, + NRF91_TIM_SHORT_COMPARE_STOP = 2 +}; + +/* Timer frequency prescaler */ + +enum nrf91_tim_pre_e +{ + NRF91_TIM_PRE_16000000 = 0, + NRF91_TIM_PRE_8000000 = 1, + NRF91_TIM_PRE_4000000 = 2, + NRF91_TIM_PRE_2000000 = 3, + NRF91_TIM_PRE_1000000 = 4, + NRF91_TIM_PRE_500000 = 5, + NRF91_TIM_PRE_250000 = 6, + NRF91_TIM_PRE_125000 = 7, + NRF91_TIM_PRE_62500 = 8, + NRF91_TIM_PRE_31250 = 9 +}; + +/* NRF91 TIM device */ + +struct nrf91_tim_dev_s +{ + struct nrf91_tim_ops_s *ops; +}; + +/* NRF91 TIM ops */ + +struct nrf91_tim_ops_s +{ + /* Timer tasks */ + + int (*start)(struct nrf91_tim_dev_s *dev); + int (*stop)(struct nrf91_tim_dev_s *dev); + int (*clear)(struct nrf91_tim_dev_s *dev); + + /* Timer configuration */ + + int (*configure)(struct nrf91_tim_dev_s *dev, uint8_t mode, uint8_t width); + int (*shorts)(struct nrf91_tim_dev_s *dev, uint8_t s, uint8_t i, bool en); + + /* Timer operations */ + + int (*count)(struct nrf91_tim_dev_s *dev); + int (*setcc)(struct nrf91_tim_dev_s *dev, uint8_t i, uint32_t cc); + int (*getcc)(struct nrf91_tim_dev_s *dev, uint8_t i, uint32_t *cc); + int (*setpre)(struct nrf91_tim_dev_s *dev, uint8_t pre); + + /* Timer interrupts */ + + int (*setisr)(struct nrf91_tim_dev_s *dev, xcpt_t handler, void *arg); + int (*enableint)(struct nrf91_tim_dev_s *dev, uint8_t source); + int (*disableint)(struct nrf91_tim_dev_s *dev, uint8_t source); + int (*checkint)(struct nrf91_tim_dev_s *dev, uint8_t source); + int (*ackint)(struct nrf91_tim_dev_s *dev, uint8_t source); +}; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +struct nrf91_tim_dev_s *nrf91_tim_init(int timer); +int nrf91_tim_deinit(struct nrf91_tim_dev_s *dev); + +#endif /* __ARCH_ARM_SRC_NRF91_NRF91_TIM_H */ diff --git a/arch/arm/src/nrf91/nrf91_tim_lowerhalf.c b/arch/arm/src/nrf91/nrf91_tim_lowerhalf.c new file mode 100644 index 0000000000..2ce6d31e82 --- /dev/null +++ b/arch/arm/src/nrf91/nrf91_tim_lowerhalf.c @@ -0,0 +1,538 @@ +/**************************************************************************** + * arch/arm/src/nrf91/nrf91_tim_lowerhalf.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 "nrf91_tim.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* TIMER configuration */ + +#define NRF91_TIMER_CC (NRF91_TIM_CC0) +#define NRF91_TIMER_INT (NRF91_TIM_INT_COMPARE0) +#define NRF91_TIMER_RES (NRF91_TIM_WIDTH_32B) +#define NRF91_TIMER_MAX (0xffffffff) +#define NRF91_TIMER_PRE (NRF91_TIM_PRE_1000000) +#define NRF91_TIMER_PER (1000000) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct nrf91_timer_lowerhalf_s +{ + const struct timer_ops_s *ops; /* Lower half operations */ + struct nrf91_tim_dev_s *tim; /* nrf91 timer driver */ + tccb_t callback; /* Current user interrupt callback */ + void *arg; /* Argument passed to upper half callback */ + bool started; /* True: Timer has been started */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int nrf91_timer_handler(int irq, void *context, void *arg); + +/* "Lower half" driver methods **********************************************/ + +static int nrf91_timer_start(struct timer_lowerhalf_s *lower); +static int nrf91_timer_stop(struct timer_lowerhalf_s *lower); +static int nrf91_timer_getstatus(struct timer_lowerhalf_s *lower, + struct timer_status_s *status); +static int nrf91_timer_settimeout(struct timer_lowerhalf_s *lower, + uint32_t timeout); +static void nrf91_timer_setcallback(struct timer_lowerhalf_s *lower, + tccb_t callback, void *arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* "Lower half" driver methods */ + +static const struct timer_ops_s g_nrf91_timer_ops = +{ + .start = nrf91_timer_start, + .stop = nrf91_timer_stop, + .getstatus = nrf91_timer_getstatus, + .settimeout = nrf91_timer_settimeout, + .setcallback = nrf91_timer_setcallback, + .ioctl = NULL, +}; + +#ifdef CONFIG_NRF91_TIMER0 +/* TIMER0 lower-half */ + +static struct nrf91_timer_lowerhalf_s g_nrf91_timer0_lowerhalf = +{ + .ops = &g_nrf91_timer_ops, +}; +#endif + +#ifdef CONFIG_NRF91_TIMER1 +/* TIMER1 lower-half */ + +static struct nrf91_timer_lowerhalf_s g_nrf91_timer1_lowerhalf = +{ + .ops = &g_nrf91_timer_ops, +}; +#endif + +#ifdef CONFIG_NRF91_TIMER2 +/* TIMER2 lower-half */ + +static struct nrf91_timer_lowerhalf_s g_nrf91_timer2_lowerhalf = +{ + .ops = &g_nrf91_timer_ops, +}; +#endif + +#ifdef CONFIG_NRF91_TIMER3 +/* TIMER3 lower-half */ + +static struct nrf91_timer_lowerhalf_s g_nrf91_timer3_lowerhalf = +{ + .ops = &g_nrf91_timer_ops, +}; +#endif + +#ifdef CONFIG_NRF91_TIMER4 +/* TIMER4 lower-half */ + +static struct nrf91_timer_lowerhalf_s g_nrf91_timer4_lowerhalf = +{ + .ops = &g_nrf91_timer_ops, +}; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nrf91_timer_handler + * + * Description: + * Timer interrupt handler + * + * Input Parameters: + * + * Returned Value: + * + ****************************************************************************/ + +static int nrf91_timer_handler(int irq, void *context, void *arg) +{ + struct nrf91_timer_lowerhalf_s *priv = + (struct nrf91_timer_lowerhalf_s *)arg; + uint32_t next_interval_us = 0; + + NRF91_TIM_ACKINT(priv->tim, NRF91_TIMER_INT); + + if (priv->callback(&next_interval_us, priv->arg)) + { + if (next_interval_us > 0) + { + NRF91_TIM_SETCC(priv->tim, NRF91_TIMER_CC, next_interval_us); + } + } + else + { + nrf91_timer_stop((struct timer_lowerhalf_s *)priv); + } + + return OK; +} + +/**************************************************************************** + * Name: nrf91_timer_start + * + * Description: + * Start the timer, resetting the time to the current timeout, + * + * Input Parameters: + * lower - A pointer the publicly visible representation of + * the "lower-half" driver state structure. + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int nrf91_timer_start(struct timer_lowerhalf_s *lower) +{ + struct nrf91_timer_lowerhalf_s *priv = + (struct nrf91_timer_lowerhalf_s *)lower; + int ret = OK; + + DEBUGASSERT(priv); + + if (priv->started == true) + { + /* Return EBUSY to indicate that the timer was already running */ + + ret = -EBUSY; + goto errout; + } + + /* Configure TIMER mode and resolution */ + + NRF91_TIM_CONFIGURE(priv->tim, NRF91_TIM_MODE_TIMER, NRF91_TIMER_RES); + + /* Clear counter on COMPARE event */ + + NRF91_TIM_SHORTS(priv->tim, NRF91_TIM_SHORT_COMPARE_CLEAR, + NRF91_TIMER_INT, true); + + /* Configure prescaler */ + + NRF91_TIM_SETPRE(priv->tim, NRF91_TIMER_PRE); + + /* Configure callback */ + + if (priv->callback != NULL) + { + NRF91_TIM_SETISR(priv->tim, nrf91_timer_handler, priv); + NRF91_TIM_ENABLEINT(priv->tim, NRF91_TIMER_INT); + } + + NRF91_TIM_CLEAR(priv->tim); + NRF91_TIM_START(priv->tim); + + priv->started = true; + +errout: + return ret; +} + +/**************************************************************************** + * Name: nrf91_timer_stop + * + * Description: + * Stop the timer + * + * Input Parameters: + * lower - A pointer the publicly visible representation of + * the "lower-half" driver state structure. + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int nrf91_timer_stop(struct timer_lowerhalf_s *lower) +{ + struct nrf91_timer_lowerhalf_s *priv = + (struct nrf91_timer_lowerhalf_s *)lower; + int ret = OK; + + DEBUGASSERT(priv); + + if (priv->started == false) + { + /* Return ENODEV to indicate that the timer was not running */ + + ret = -ENODEV; + goto errout; + } + + NRF91_TIM_DISABLEINT(priv->tim, NRF91_TIMER_INT); + NRF91_TIM_SETISR(priv->tim, NULL, NULL); + NRF91_TIM_STOP(priv->tim); + + priv->started = false; + +errout: + return ret; +} + +/**************************************************************************** + * Name: nrf91_timer_getstatus + * + * Description: + * get timer status + * + * Input Parameters: + * lower - A pointer the publicly visible representation of the "lower- + * half" driver state structure. + * status - The location to return the status information. + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int nrf91_timer_getstatus(struct timer_lowerhalf_s *lower, + struct timer_status_s *status) +{ + struct nrf91_timer_lowerhalf_s *priv = + (struct nrf91_timer_lowerhalf_s *)lower; + + DEBUGASSERT(priv); + DEBUGASSERT(status); + + /* Return the status bit */ + + status->flags = 0; + + if (priv->started == true) + { + status->flags |= TCFLAGS_ACTIVE; + } + + if (priv->callback) + { + status->flags |= TCFLAGS_HANDLER; + } + + /* TODO: timeout and time left */ + + status->timeout = 0; + status->timeleft = 0; + + return OK; +} + +/**************************************************************************** + * Name: nrf91_timer_settimeout + * + * Description: + * Set a new timeout value (and reset the timer) + * + * Input Parameters: + * lower - A pointer the publicly visible representation of + * the "lower-half" driver state structure. + * timeout - The new timeout value in microseconds. + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int nrf91_timer_settimeout(struct timer_lowerhalf_s *lower, + uint32_t timeout) +{ + struct nrf91_timer_lowerhalf_s *priv = + (struct nrf91_timer_lowerhalf_s *)lower; + uint64_t cc = 0; + int ret = OK; + + DEBUGASSERT(priv); + + if (priv->started == true) + { + ret = -EPERM; + goto errout; + } + + if (timeout > NRF91_TIMER_MAX) + { + ret = -EINVAL; + goto errout; + } + + cc = (timeout / 1000000) * NRF91_TIMER_PER; + NRF91_TIM_SETCC(priv->tim, NRF91_TIMER_CC, cc); + +errout: + return ret; +} + +/**************************************************************************** + * Name: nrf91_setcallback + * + * Description: + * Call this user provided timeout handler. + * + * Input Parameters: + * lower - A pointer the publicly visible representation of + * the "lower-half" driver state structure. + * callback - The new timer expiration function pointer. If this + * function pointer is NULL, then the reset-on-expiration + * behavior is restored, + * arg - Argument that will be provided in the callback + * + * Returned Value: + * The previous timer expiration function pointer or NULL is there was + * no previous function pointer. + * + ****************************************************************************/ + +static void nrf91_timer_setcallback(struct timer_lowerhalf_s *lower, + tccb_t callback, void *arg) +{ + struct nrf91_timer_lowerhalf_s *priv = + (struct nrf91_timer_lowerhalf_s *)lower; + irqstate_t flags; + + DEBUGASSERT(priv); + + flags = enter_critical_section(); + + /* Save the new callback */ + + priv->callback = callback; + priv->arg = arg; + + if (callback != NULL && priv->started == true) + { + NRF91_TIM_SETISR(priv->tim, nrf91_timer_handler, priv); + NRF91_TIM_ENABLEINT(priv->tim, NRF91_TIMER_INT); + } + else + { + NRF91_TIM_DISABLEINT(priv->tim, NRF91_TIMER_INT); + NRF91_TIM_SETISR(priv->tim, NULL, NULL); + } + + leave_critical_section(flags); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nrf91_timer_initialize + * + * Description: + * Bind the configuration timer to a timer lower half instance and + * register the timer drivers at 'devpath' + * + * Input Parameters: + * devpath - The full path to the timer device. This should be of the + * form /dev/timer0 + * timer - the timer's number. + * + * Returned Value: + * Zero (OK) is returned on success; A negated errno value is returned + * to indicate the nature of any failure. + * + ****************************************************************************/ + +int nrf91_timer_initialize(const char *devpath, uint8_t timer) +{ + struct nrf91_timer_lowerhalf_s *lower = NULL; + void *drvr = NULL; + int ret = OK; + + DEBUGASSERT(devpath); + + switch (timer) + { +#ifdef CONFIG_NRF91_TIMER0 + case 0: + { + lower = &g_nrf91_timer0_lowerhalf; + break; + } +#endif + +#ifdef CONFIG_NRF91_TIMER1 + case 1: + { + lower = &g_nrf91_timer1_lowerhalf; + break; + } +#endif + +#ifdef CONFIG_NRF91_TIMER2 + case 2: + { + lower = &g_nrf91_timer2_lowerhalf; + break; + } +#endif + +#ifdef CONFIG_NRF91_TIMER3 + case 3: + { + lower = &g_nrf91_timer3_lowerhalf; + break; + } +#endif + +#ifdef CONFIG_NRF91_TIMER4 + case 4: + { + lower = &g_nrf91_timer4_lowerhalf; + break; + } +#endif + + default: + { + ret = -ENODEV; + goto errout; + } + } + + /* Initialize the elements of lower half state structure */ + + lower->started = false; + lower->callback = NULL; + lower->tim = nrf91_tim_init(timer); + + if (lower->tim == NULL) + { + ret = -EINVAL; + goto errout; + } + + /* Register the timer driver as /dev/timerX. The returned value from + * timer_register is a handle that could be used with timer_unregister(). + * REVISIT: The returned handle is discard here. + */ + + drvr = timer_register(devpath, (struct timer_lowerhalf_s *)lower); + if (drvr == NULL) + { + /* The actual cause of the failure may have been a failure to allocate + * perhaps a failure to register the timer driver (such as if the + * 'depath' were not unique). We know here but we return EEXIST to + * indicate the failure (implying the non-unique devpath). + */ + + ret = -EEXIST; + goto errout; + } + +errout: + return ret; +} diff --git a/arch/arm/src/nrf91/nrf91_tim_lowerhalf.h b/arch/arm/src/nrf91/nrf91_tim_lowerhalf.h new file mode 100644 index 0000000000..9c206a2241 --- /dev/null +++ b/arch/arm/src/nrf91/nrf91_tim_lowerhalf.h @@ -0,0 +1,42 @@ +/**************************************************************************** + * arch/arm/src/nrf91/nrf91_tim_lowerhalf.h + * + * 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. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_NRF91_NRF91_TIM_LOWERHALF_H +#define __ARCH_ARM_SRC_NRF91_NRF91_TIM_LOWERHALF_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: nrf91_timer_initialize + ****************************************************************************/ + +int nrf91_timer_initialize(const char *devpath, uint8_t timer); + +#endif /* __ARCH_ARM_SRC_NRF91_NRF91_TIM_LOWERHALF_H */ diff --git a/arch/arm/src/nrf91/nrf91_uid.c b/arch/arm/src/nrf91/nrf91_uid.c new file mode 100644 index 0000000000..f8ef4670eb --- /dev/null +++ b/arch/arm/src/nrf91/nrf91_uid.c @@ -0,0 +1,51 @@ +/**************************************************************************** + * arch/arm/src/nrf91/nrf91_uid.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 "arm_internal.h" +#include "nrf91_uid.h" + +#include "hardware/nrf91_ficr.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +void nrf91_get_uniqueid(uint8_t uniqueid[8]) +{ + uint32_t uid0 = getreg32(NRF91_FICR_BASE + + NRF91_FICR_INFO_DEVICEID0_OFFSET); + uint32_t uid1 = getreg32(NRF91_FICR_BASE + + NRF91_FICR_INFO_DEVICEID1_OFFSET); + + uniqueid[0] = (uint8_t)((uid0 >> 0) & 0xff); + uniqueid[1] = (uint8_t)((uid0 >> 8) & 0xff); + uniqueid[2] = (uint8_t)((uid0 >> 16) & 0xff); + uniqueid[3] = (uint8_t)((uid0 >> 24) & 0xff); + uniqueid[4] = (uint8_t)((uid1 >> 0) & 0xff); + uniqueid[5] = (uint8_t)((uid1 >> 8) & 0xff); + uniqueid[6] = (uint8_t)((uid1 >> 16) & 0xff); + uniqueid[7] = (uint8_t)((uid1 >> 24) & 0xff); +} diff --git a/arch/arm/src/nrf91/nrf91_uid.h b/arch/arm/src/nrf91/nrf91_uid.h new file mode 100644 index 0000000000..93d70408f6 --- /dev/null +++ b/arch/arm/src/nrf91/nrf91_uid.h @@ -0,0 +1,36 @@ +/**************************************************************************** + * arch/arm/src/nrf91/nrf91_uid.h + * + * 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. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_NRF91_NRF91_UID_H +#define __ARCH_ARM_SRC_NRF91_NRF91_UID_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +void nrf91_get_uniqueid(uint8_t uniqueid[8]); + +#endif /* __ARCH_ARM_SRC_NRF91_NRF91_UID_H */ diff --git a/arch/arm/src/nrf91/nrf91_utils.c b/arch/arm/src/nrf91/nrf91_utils.c new file mode 100644 index 0000000000..17bee3480b --- /dev/null +++ b/arch/arm/src/nrf91/nrf91_utils.c @@ -0,0 +1,90 @@ +/**************************************************************************** + * arch/arm/src/nrf91/nrf91_utils.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 "nvic.h" +#include "arm_internal.h" +#include "nrf91_irq.h" +#include "hardware/nrf91_utils.h" +#include "hardware/nrf91_memorymap.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nrf91_clrpend + * + * Description: + * Clear a pending interrupt at the NVIC. This does not seem to be + * required for most interrupts. + * + * This function is logically a part of nrf91_irq.c, but I will keep it in + * a separate file so that it will not increase the footprint on NRF91 + * platforms that do not need this function. + * + ****************************************************************************/ + +void nrf91_clrpend(int irq) +{ + /* Check for external interrupt */ + + if (irq >= NRF91_IRQ_EXTINT) + { + if (irq < (NRF91_IRQ_EXTINT + 32)) + { + putreg32(1 << (irq - NRF91_IRQ_EXTINT), NVIC_IRQ0_31_CLRPEND); + } + else if (irq < NRF91_IRQ_NIRQS) + { + putreg32(1 << (irq - NRF91_IRQ_EXTINT - 32), + NVIC_IRQ32_63_CLRPEND); + } + } +} + +/**************************************************************************** + * Name: nrf91_easydma_valid + * + * Description: + * Validate if easyDMA transfer is possible. + * + ****************************************************************************/ + +bool nrf91_easydma_valid(uint32_t addr) +{ +#ifdef CONFIG_DEBUG_FEATURES + /* EasyDMA cannot access flash memory */ + + if (addr >= NRF91_FLASH_BASE && addr < NRF91_SRAM_BASE) + { + return false; + } +#endif + + return true; +}