main.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. /**
  2. * Copyright (c) 2014 - 2020, Nordic Semiconductor ASA
  3. *
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without modification,
  7. * are permitted provided that the following conditions are met:
  8. *
  9. * 1. Redistributions of source code must retain the above copyright notice, this
  10. * list of conditions and the following disclaimer.
  11. *
  12. * 2. Redistributions in binary form, except as embedded into a Nordic
  13. * Semiconductor ASA integrated circuit in a product or a software update for
  14. * such product, must reproduce the above copyright notice, this list of
  15. * conditions and the following disclaimer in the documentation and/or other
  16. * materials provided with the distribution.
  17. *
  18. * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
  19. * contributors may be used to endorse or promote products derived from this
  20. * software without specific prior written permission.
  21. *
  22. * 4. This software, with or without modification, must only be used with a
  23. * Nordic Semiconductor ASA integrated circuit.
  24. *
  25. * 5. Any software provided in binary form under this license must not be reverse
  26. * engineered, decompiled, modified and/or disassembled.
  27. *
  28. * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
  29. * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  30. * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
  31. * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
  32. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  33. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
  34. * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  35. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  36. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  37. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  38. *
  39. */
  40. /** @file
  41. * @defgroup ram_retention_example_main main.c
  42. * @{
  43. * @ingroup ram_retention_example
  44. * @brief RAM Retention Example Application main file.
  45. *
  46. * This file contains the source code for a sample application using RAM retention.
  47. *
  48. */
  49. #include <stdbool.h>
  50. #include <stdint.h>
  51. #include "bsp.h"
  52. #include "nrf_delay.h"
  53. #include "nrf_gpio.h"
  54. #include "nrf_log.h"
  55. #include "nrf_log_ctrl.h"
  56. #include "nrf_log_default_backends.h"
  57. #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.*/
  58. #define RAM_MEMORY_TEST_WORD (0xFEEDBEEFUL) /**< Test word that is written to RAM address RAM_MEMORY_TEST_ADDRESS. */
  59. #define RESET_MEMORY_TEST_BYTE (0x0DUL) /**< Known sequence written to a special register to check if this wake up is from System OFF. */
  60. #define MAX_TEST_ITERATIONS (1) /**< Maximum number of iterations this example will run. */
  61. #define SUCCESS_OUTPUT_VALUE (0xAB) /**< If RAM retention is tested for MAX_TEST_ITERATIONS, this value will be given as output.*/
  62. #ifdef BSP_BUTTON_0
  63. #define PIN_GPIO_WAKEUP BSP_BUTTON_0 /**< Wake up pin number. */
  64. #endif
  65. #ifndef PIN_GPIO_WAKEUP
  66. #error "Please indicate wake up pin"
  67. #endif
  68. #ifdef BSP_LED_0
  69. #define READY_PIN_NUMBER BSP_BOARD_LED_0 /**< Pin number for output. */
  70. #endif
  71. #ifndef READY_PIN_NUMBER
  72. #error "Please indicate output pin"
  73. #endif
  74. #ifdef BSP_LED_1
  75. #define SUCCESS_PIN_NUMBER BSP_BOARD_LED_1 /**< Pin number for output. */
  76. #endif
  77. #ifndef SUCCESS_PIN_NUMBER
  78. #error "Please indicate output pin"
  79. #endif
  80. /** @brief Function for handling HardFaults. In case something went wrong
  81. * or System OFF did not work and reached the end of the program.
  82. */
  83. void HardFault_Handler()
  84. {
  85. bsp_board_leds_on();
  86. // Loop forever.
  87. while (true)
  88. {
  89. // Do nothing.
  90. }
  91. }
  92. /** @brief Function for indicating failure.
  93. */
  94. static void display_failure(void)
  95. {
  96. bsp_board_leds_on();
  97. // Loop forever.
  98. while (true)
  99. {
  100. // Do nothing.
  101. }
  102. }
  103. /**
  104. * @brief Function for application main entry.
  105. */
  106. int main(void)
  107. {
  108. uint32_t * volatile p_ram_test = (uint32_t *)RAM_MEMORY_TEST_ADDRESS;
  109. uint32_t loop_count = 0;
  110. bsp_board_init(BSP_INIT_LEDS);
  111. APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
  112. NRF_LOG_DEFAULT_BACKENDS_INIT();
  113. // This pin is used for waking up from System OFF and is active low, enabling sense capabilities.
  114. nrf_gpio_cfg_sense_input(PIN_GPIO_WAKEUP, BUTTON_PULL, NRF_GPIO_PIN_SENSE_LOW);
  115. // Workaround for PAN_028 rev1.1 anomaly 22 - System: Issues with disable System OFF mechanism
  116. nrf_delay_ms(1);
  117. // Check if the system woke up from System OFF mode by reading the NRF_POWER->GPREGRET register which has
  118. // retained the value written before going to System OFF. Below is the layout for usage for
  119. // NRF_POWER->GPREGRET register.
  120. // BITS | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
  121. // --------------------------------------------------------------------
  122. // | SPECIAL_SEQUENCE | LOOP_COUNT
  123. // --------------------------------------------------------------------
  124. ///
  125. if ((NRF_POWER->GPREGRET >> 4) == RESET_MEMORY_TEST_BYTE)
  126. {
  127. // Take the loop_count value.
  128. loop_count = (uint8_t)(NRF_POWER->GPREGRET & 0xFUL);
  129. NRF_POWER->GPREGRET = 0;
  130. if (loop_count >= (uint8_t)MAX_TEST_ITERATIONS)
  131. {
  132. // clear GPREGRET register before exit.
  133. NRF_POWER->GPREGRET = 0;
  134. bsp_board_led_on(SUCCESS_PIN_NUMBER);
  135. while (true)
  136. {
  137. // Do nothing.
  138. }
  139. }
  140. if (*p_ram_test != RAM_MEMORY_TEST_WORD)
  141. {
  142. display_failure();
  143. }
  144. *p_ram_test = 0;
  145. }
  146. // Write the known sequence + loop_count to the GPREGRET register.
  147. loop_count++;
  148. NRF_POWER->GPREGRET = ( (RESET_MEMORY_TEST_BYTE << 4) | loop_count);
  149. // Write the known value to the known address in RAM, enable RAM retention, set System OFF, and wait
  150. // for GPIO wakeup from external source.
  151. bsp_board_led_on(READY_PIN_NUMBER);
  152. nrf_delay_ms(1000);
  153. // Switch on both RAM banks when in System OFF mode.
  154. #if defined(NRF52832_XXAA) || defined(NRF51422) || defined(NRF51822)
  155. NRF_POWER->RAMON |= (POWER_RAMON_OFFRAM0_RAM0On << POWER_RAMON_OFFRAM0_Pos) |
  156. (POWER_RAMON_OFFRAM1_RAM1On << POWER_RAMON_OFFRAM1_Pos);
  157. #elif defined(NRF52840_XXAA) || defined(NRF52833_XXAA)
  158. NRF_POWER->RAM[0].POWERSET = (POWER_RAM_POWER_S0POWER_On << POWER_RAM_POWER_S0POWER_Pos) |
  159. (POWER_RAM_POWER_S1POWER_On << POWER_RAM_POWER_S1POWER_Pos) |
  160. (POWER_RAM_POWER_S2POWER_On << POWER_RAM_POWER_S2POWER_Pos) |
  161. (POWER_RAM_POWER_S3POWER_On << POWER_RAM_POWER_S3POWER_Pos) |
  162. (POWER_RAM_POWER_S4POWER_On << POWER_RAM_POWER_S4POWER_Pos) |
  163. (POWER_RAM_POWER_S5POWER_On << POWER_RAM_POWER_S5POWER_Pos) |
  164. (POWER_RAM_POWER_S6POWER_On << POWER_RAM_POWER_S6POWER_Pos) |
  165. (POWER_RAM_POWER_S7POWER_On << POWER_RAM_POWER_S7POWER_Pos) |
  166. (POWER_RAM_POWER_S8POWER_On << POWER_RAM_POWER_S8POWER_Pos) |
  167. (POWER_RAM_POWER_S9POWER_On << POWER_RAM_POWER_S9POWER_Pos) |
  168. (POWER_RAM_POWER_S10POWER_On << POWER_RAM_POWER_S10POWER_Pos) |
  169. (POWER_RAM_POWER_S11POWER_On << POWER_RAM_POWER_S11POWER_Pos) |
  170. (POWER_RAM_POWER_S12POWER_On << POWER_RAM_POWER_S12POWER_Pos) |
  171. (POWER_RAM_POWER_S13POWER_On << POWER_RAM_POWER_S13POWER_Pos) |
  172. (POWER_RAM_POWER_S14POWER_On << POWER_RAM_POWER_S14POWER_Pos) |
  173. (POWER_RAM_POWER_S15POWER_On << POWER_RAM_POWER_S15POWER_Pos) |
  174. (POWER_RAM_POWER_S0RETENTION_On << POWER_RAM_POWER_S0RETENTION_Pos) |
  175. (POWER_RAM_POWER_S1RETENTION_On << POWER_RAM_POWER_S1RETENTION_Pos) |
  176. (POWER_RAM_POWER_S2RETENTION_On << POWER_RAM_POWER_S2RETENTION_Pos) |
  177. (POWER_RAM_POWER_S3RETENTION_On << POWER_RAM_POWER_S3RETENTION_Pos) |
  178. (POWER_RAM_POWER_S4RETENTION_On << POWER_RAM_POWER_S4RETENTION_Pos) |
  179. (POWER_RAM_POWER_S5RETENTION_On << POWER_RAM_POWER_S5RETENTION_Pos) |
  180. (POWER_RAM_POWER_S6RETENTION_On << POWER_RAM_POWER_S6RETENTION_Pos) |
  181. (POWER_RAM_POWER_S7RETENTION_On << POWER_RAM_POWER_S7RETENTION_Pos) |
  182. (POWER_RAM_POWER_S8RETENTION_On << POWER_RAM_POWER_S8RETENTION_Pos) |
  183. (POWER_RAM_POWER_S9RETENTION_On << POWER_RAM_POWER_S9RETENTION_Pos) |
  184. (POWER_RAM_POWER_S10RETENTION_On << POWER_RAM_POWER_S10RETENTION_Pos) |
  185. (POWER_RAM_POWER_S11RETENTION_On << POWER_RAM_POWER_S11RETENTION_Pos) |
  186. (POWER_RAM_POWER_S12RETENTION_On << POWER_RAM_POWER_S12RETENTION_Pos) |
  187. (POWER_RAM_POWER_S13RETENTION_On << POWER_RAM_POWER_S13RETENTION_Pos) |
  188. (POWER_RAM_POWER_S14RETENTION_On << POWER_RAM_POWER_S14RETENTION_Pos) |
  189. (POWER_RAM_POWER_S15RETENTION_On << POWER_RAM_POWER_S15RETENTION_Pos);
  190. #else
  191. #error 'Unsupported MCU'
  192. #endif
  193. // Write test word to RAM memory.
  194. *p_ram_test = RAM_MEMORY_TEST_WORD;
  195. bsp_board_leds_off();
  196. // Enter System OFF and wait for wake up from GPIO detect signal.
  197. NRF_POWER->SYSTEMOFF = 0x1;
  198. // Use data synchronization barrier and a delay to ensure that no failure
  199. // indication occurs before System OFF is actually entered.
  200. __DSB();
  201. __NOP();
  202. // This code will only be reached if System OFF did not work and will trigger a hard-fault which will
  203. // be handled in HardFault_Handler(). If wake the up condition is already active while System OFF is triggered,
  204. // then the system will go to System OFF and wake up immediately with a System RESET.
  205. display_failure();
  206. }
  207. /** @} */