123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238 |
- /**
- * Copyright (c) 2014 - 2020, Nordic Semiconductor ASA
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form, except as embedded into a Nordic
- * Semiconductor ASA integrated circuit in a product or a software update for
- * such product, must reproduce the above copyright notice, this list of
- * conditions and the following disclaimer in the documentation and/or other
- * materials provided with the distribution.
- *
- * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
- * contributors may be used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * 4. This software, with or without modification, must only be used with a
- * Nordic Semiconductor ASA integrated circuit.
- *
- * 5. Any software provided in binary form under this license must not be reverse
- * engineered, decompiled, modified and/or disassembled.
- *
- * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
- * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
- /** @file
- * @defgroup ram_retention_example_main main.c
- * @{
- * @ingroup ram_retention_example
- * @brief RAM Retention Example Application main file.
- *
- * This file contains the source code for a sample application using RAM retention.
- *
- */
- #include <stdbool.h>
- #include <stdint.h>
- #include "bsp.h"
- #include "nrf_delay.h"
- #include "nrf_gpio.h"
- #include "nrf_log.h"
- #include "nrf_log_ctrl.h"
- #include "nrf_log_default_backends.h"
- #define RAM_MEMORY_TEST_ADDRESS (0x20002000UL) /**< Address in RAM where test word (RAM_MEMORY_TEST_WORD) is written before System OFF and checked after System RESET.*/
- #define RAM_MEMORY_TEST_WORD (0xFEEDBEEFUL) /**< Test word that is written to RAM address RAM_MEMORY_TEST_ADDRESS. */
- #define RESET_MEMORY_TEST_BYTE (0x0DUL) /**< Known sequence written to a special register to check if this wake up is from System OFF. */
- #define MAX_TEST_ITERATIONS (1) /**< Maximum number of iterations this example will run. */
- #define SUCCESS_OUTPUT_VALUE (0xAB) /**< If RAM retention is tested for MAX_TEST_ITERATIONS, this value will be given as output.*/
- #ifdef BSP_BUTTON_0
- #define PIN_GPIO_WAKEUP BSP_BUTTON_0 /**< Wake up pin number. */
- #endif
- #ifndef PIN_GPIO_WAKEUP
- #error "Please indicate wake up pin"
- #endif
- #ifdef BSP_LED_0
- #define READY_PIN_NUMBER BSP_BOARD_LED_0 /**< Pin number for output. */
- #endif
- #ifndef READY_PIN_NUMBER
- #error "Please indicate output pin"
- #endif
- #ifdef BSP_LED_1
- #define SUCCESS_PIN_NUMBER BSP_BOARD_LED_1 /**< Pin number for output. */
- #endif
- #ifndef SUCCESS_PIN_NUMBER
- #error "Please indicate output pin"
- #endif
- /** @brief Function for handling HardFaults. In case something went wrong
- * or System OFF did not work and reached the end of the program.
- */
- void HardFault_Handler()
- {
- bsp_board_leds_on();
- // Loop forever.
- while (true)
- {
- // Do nothing.
- }
- }
- /** @brief Function for indicating failure.
- */
- static void display_failure(void)
- {
- bsp_board_leds_on();
- // Loop forever.
- while (true)
- {
- // Do nothing.
- }
- }
- /**
- * @brief Function for application main entry.
- */
- int main(void)
- {
- uint32_t * volatile p_ram_test = (uint32_t *)RAM_MEMORY_TEST_ADDRESS;
- uint32_t loop_count = 0;
- bsp_board_init(BSP_INIT_LEDS);
- APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
- NRF_LOG_DEFAULT_BACKENDS_INIT();
- // This pin is used for waking up from System OFF and is active low, enabling sense capabilities.
- nrf_gpio_cfg_sense_input(PIN_GPIO_WAKEUP, BUTTON_PULL, NRF_GPIO_PIN_SENSE_LOW);
- // Workaround for PAN_028 rev1.1 anomaly 22 - System: Issues with disable System OFF mechanism
- nrf_delay_ms(1);
- // Check if the system woke up from System OFF mode by reading the NRF_POWER->GPREGRET register which has
- // retained the value written before going to System OFF. Below is the layout for usage for
- // NRF_POWER->GPREGRET register.
- // BITS | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
- // --------------------------------------------------------------------
- // | SPECIAL_SEQUENCE | LOOP_COUNT
- // --------------------------------------------------------------------
- ///
- if ((NRF_POWER->GPREGRET >> 4) == RESET_MEMORY_TEST_BYTE)
- {
- // Take the loop_count value.
- loop_count = (uint8_t)(NRF_POWER->GPREGRET & 0xFUL);
- NRF_POWER->GPREGRET = 0;
- if (loop_count >= (uint8_t)MAX_TEST_ITERATIONS)
- {
- // clear GPREGRET register before exit.
- NRF_POWER->GPREGRET = 0;
- bsp_board_led_on(SUCCESS_PIN_NUMBER);
- while (true)
- {
- // Do nothing.
- }
- }
- if (*p_ram_test != RAM_MEMORY_TEST_WORD)
- {
- display_failure();
- }
- *p_ram_test = 0;
- }
- // Write the known sequence + loop_count to the GPREGRET register.
- loop_count++;
- NRF_POWER->GPREGRET = ( (RESET_MEMORY_TEST_BYTE << 4) | loop_count);
- // Write the known value to the known address in RAM, enable RAM retention, set System OFF, and wait
- // for GPIO wakeup from external source.
- bsp_board_led_on(READY_PIN_NUMBER);
- nrf_delay_ms(1000);
- // Switch on both RAM banks when in System OFF mode.
- #if defined(NRF52832_XXAA) || defined(NRF51422) || defined(NRF51822)
- NRF_POWER->RAMON |= (POWER_RAMON_OFFRAM0_RAM0On << POWER_RAMON_OFFRAM0_Pos) |
- (POWER_RAMON_OFFRAM1_RAM1On << POWER_RAMON_OFFRAM1_Pos);
- #elif defined(NRF52840_XXAA) || defined(NRF52833_XXAA)
- NRF_POWER->RAM[0].POWERSET = (POWER_RAM_POWER_S0POWER_On << POWER_RAM_POWER_S0POWER_Pos) |
- (POWER_RAM_POWER_S1POWER_On << POWER_RAM_POWER_S1POWER_Pos) |
- (POWER_RAM_POWER_S2POWER_On << POWER_RAM_POWER_S2POWER_Pos) |
- (POWER_RAM_POWER_S3POWER_On << POWER_RAM_POWER_S3POWER_Pos) |
- (POWER_RAM_POWER_S4POWER_On << POWER_RAM_POWER_S4POWER_Pos) |
- (POWER_RAM_POWER_S5POWER_On << POWER_RAM_POWER_S5POWER_Pos) |
- (POWER_RAM_POWER_S6POWER_On << POWER_RAM_POWER_S6POWER_Pos) |
- (POWER_RAM_POWER_S7POWER_On << POWER_RAM_POWER_S7POWER_Pos) |
- (POWER_RAM_POWER_S8POWER_On << POWER_RAM_POWER_S8POWER_Pos) |
- (POWER_RAM_POWER_S9POWER_On << POWER_RAM_POWER_S9POWER_Pos) |
- (POWER_RAM_POWER_S10POWER_On << POWER_RAM_POWER_S10POWER_Pos) |
- (POWER_RAM_POWER_S11POWER_On << POWER_RAM_POWER_S11POWER_Pos) |
- (POWER_RAM_POWER_S12POWER_On << POWER_RAM_POWER_S12POWER_Pos) |
- (POWER_RAM_POWER_S13POWER_On << POWER_RAM_POWER_S13POWER_Pos) |
- (POWER_RAM_POWER_S14POWER_On << POWER_RAM_POWER_S14POWER_Pos) |
- (POWER_RAM_POWER_S15POWER_On << POWER_RAM_POWER_S15POWER_Pos) |
- (POWER_RAM_POWER_S0RETENTION_On << POWER_RAM_POWER_S0RETENTION_Pos) |
- (POWER_RAM_POWER_S1RETENTION_On << POWER_RAM_POWER_S1RETENTION_Pos) |
- (POWER_RAM_POWER_S2RETENTION_On << POWER_RAM_POWER_S2RETENTION_Pos) |
- (POWER_RAM_POWER_S3RETENTION_On << POWER_RAM_POWER_S3RETENTION_Pos) |
- (POWER_RAM_POWER_S4RETENTION_On << POWER_RAM_POWER_S4RETENTION_Pos) |
- (POWER_RAM_POWER_S5RETENTION_On << POWER_RAM_POWER_S5RETENTION_Pos) |
- (POWER_RAM_POWER_S6RETENTION_On << POWER_RAM_POWER_S6RETENTION_Pos) |
- (POWER_RAM_POWER_S7RETENTION_On << POWER_RAM_POWER_S7RETENTION_Pos) |
- (POWER_RAM_POWER_S8RETENTION_On << POWER_RAM_POWER_S8RETENTION_Pos) |
- (POWER_RAM_POWER_S9RETENTION_On << POWER_RAM_POWER_S9RETENTION_Pos) |
- (POWER_RAM_POWER_S10RETENTION_On << POWER_RAM_POWER_S10RETENTION_Pos) |
- (POWER_RAM_POWER_S11RETENTION_On << POWER_RAM_POWER_S11RETENTION_Pos) |
- (POWER_RAM_POWER_S12RETENTION_On << POWER_RAM_POWER_S12RETENTION_Pos) |
- (POWER_RAM_POWER_S13RETENTION_On << POWER_RAM_POWER_S13RETENTION_Pos) |
- (POWER_RAM_POWER_S14RETENTION_On << POWER_RAM_POWER_S14RETENTION_Pos) |
- (POWER_RAM_POWER_S15RETENTION_On << POWER_RAM_POWER_S15RETENTION_Pos);
- #else
- #error 'Unsupported MCU'
- #endif
- // Write test word to RAM memory.
- *p_ram_test = RAM_MEMORY_TEST_WORD;
- bsp_board_leds_off();
- // Enter System OFF and wait for wake up from GPIO detect signal.
- NRF_POWER->SYSTEMOFF = 0x1;
- // Use data synchronization barrier and a delay to ensure that no failure
- // indication occurs before System OFF is actually entered.
- __DSB();
- __NOP();
- // This code will only be reached if System OFF did not work and will trigger a hard-fault which will
- // be handled in HardFault_Handler(). If wake the up condition is already active while System OFF is triggered,
- // then the system will go to System OFF and wake up immediately with a System RESET.
- display_failure();
- }
- /** @} */
|