15
15
#include <zephyr/sys/byteorder.h>
16
16
#include <zephyr/sys/crc.h>
17
17
18
- #if CONFIG_APP_USE_NRF_RETENTION
19
- #include <hal/nrf_power.h>
20
-
21
- /* nRF52 RAM (really, RAM AHB slaves) are partitioned as:
22
- * * Up to 8 blocks of two 4 KiBy byte "small" sections
23
- * * A 9th block of with 32 KiBy "large" sections
24
- *
25
- * At time of writing the maximum number of large sections is 6, all
26
- * within the first large block. Theoretically there could be more
27
- * sections in the 9th block, and possibly more blocks.
28
- */
29
-
30
- /* Inclusive address of RAM start */
31
- #define SRAM_BEGIN (uintptr_t)DT_REG_ADDR(DT_NODELABEL(sram0))
32
-
33
- /* Exclusive address of RAM end */
34
- #define SRAM_END (SRAM_BEGIN + (uintptr_t)DT_REG_SIZE(DT_NODELABEL(sram0)))
35
-
36
- /* Size of a controllable RAM section in the small blocks */
37
- #define SMALL_SECTION_SIZE 4096
38
-
39
- /* Number of controllable RAM sections in each of the lower blocks */
40
- #define SMALL_SECTIONS_PER_BLOCK 2
41
-
42
- /* Span of a small block */
43
- #define SMALL_BLOCK_SIZE (SMALL_SECTIONS_PER_BLOCK * SMALL_SECTION_SIZE)
44
-
45
- /* Number of small blocks */
46
- #define SMALL_BLOCK_COUNT 8
47
-
48
- /* Span of the SRAM area covered by small sections */
49
- #define SMALL_SECTION_SPAN (SMALL_BLOCK_COUNT * SMALL_BLOCK_SIZE)
50
-
51
- /* Inclusive address of the RAM range covered by large sections */
52
- #define LARGE_SECTION_BEGIN (SRAM_BEGIN + SMALL_SECTION_SPAN)
53
-
54
- /* Size of a controllable RAM section in large blocks */
55
- #define LARGE_SECTION_SIZE 32768
56
-
57
- #elif CONFIG_APP_USE_RETAINED_MEM
18
+ #if DT_NODE_HAS_STATUS_OKAY (DT_ALIAS (retainedmemdevice ))
58
19
const static struct device * retained_mem_device = DEVICE_DT_GET (DT_ALIAS (retainedmemdevice ));
59
- #endif
60
-
61
- /* Set or clear RAM retention in SYSTEM_OFF for the provided object.
62
- *
63
- * @param ptr pointer to the start of the retainable object
64
- *
65
- * @param len length of the retainable object
66
- *
67
- * @param enable true to enable retention, false to clear retention
68
- */
69
- static int ram_range_retain (const void * ptr ,
70
- size_t len ,
71
- bool enable )
72
- {
73
- int rc = 0 ;
74
-
75
- #if CONFIG_APP_USE_NRF_RETENTION
76
- /* This only works for nRF52 with the POWER module.
77
- * The other Nordic chips use a different low-level API,
78
- * which is not currently used by this variant.
79
- */
80
- uintptr_t addr = (uintptr_t )ptr ;
81
- uintptr_t addr_end = addr + len ;
82
-
83
- /* Error if the provided range is empty or doesn't lie
84
- * entirely within the SRAM address space.
85
- */
86
- if ((len == 0U )
87
- || (addr < SRAM_BEGIN )
88
- || (addr > (SRAM_END - len ))) {
89
- return - EINVAL ;
90
- }
91
-
92
- /* Iterate over each section covered by the range, setting the
93
- * corresponding RAM OFF retention bit in the parent block.
94
- */
95
- do {
96
- uintptr_t block_base = SRAM_BEGIN ;
97
- uint32_t section_size = SMALL_SECTION_SIZE ;
98
- uint32_t sections_per_block = SMALL_SECTIONS_PER_BLOCK ;
99
- bool is_large = (addr >= LARGE_SECTION_BEGIN );
100
- uint8_t block = 0 ;
101
-
102
- if (is_large ) {
103
- block = 8 ;
104
- block_base = LARGE_SECTION_BEGIN ;
105
- section_size = LARGE_SECTION_SIZE ;
106
-
107
- /* RAM[x] supports only 16 sections, each its own bit
108
- * for POWER (0..15) and RETENTION (16..31). We don't
109
- * know directly how many sections are present, so
110
- * assume they all are; the true limit will be
111
- * determined by the SRAM size.
112
- */
113
- sections_per_block = 16 ;
114
- }
115
-
116
- uint32_t section = (addr - block_base ) / section_size ;
117
-
118
- if (section >= sections_per_block ) {
119
- block += section / sections_per_block ;
120
- section %= sections_per_block ;
121
- }
122
-
123
- uint32_t section_mask =
124
- (POWER_RAM_POWERSET_S0RETENTION_On
125
- << (section + POWER_RAM_POWERSET_S0RETENTION_Pos ));
126
-
127
- if (enable ) {
128
- nrf_power_rampower_mask_on (NRF_POWER , block , section_mask );
129
- } else {
130
- nrf_power_rampower_mask_off (NRF_POWER , block , section_mask );
131
- }
132
-
133
- /* Move to the first address in the next section. */
134
- addr += section_size - (addr % section_size );
135
- } while (addr < addr_end );
136
- #elif CONFIG_APP_USE_RETAINED_MEM
137
- /* Retention setting cannot be controlled runtime with retained_mem API */
138
- (void )enable ;
139
- rc = retained_mem_write (retained_mem_device , 0 , ptr , len );
140
20
#else
141
- #error "Unsupported retention setting "
21
+ #error "retained_mem region not defined "
142
22
#endif
143
23
144
- return rc ;
145
- }
146
-
147
- /* Retained data must be defined in a no-init section to prevent the C
148
- * runtime initialization from zeroing it before anybody can see it.
149
- * It is not necesarry when retained_mem driver is utilized
150
- * as in this case retained data is stored in an area not initialized in runtime.
151
- */
152
- __noinit struct retained_data retained ;
24
+ struct retained_data retained ;
153
25
154
26
#define RETAINED_CRC_OFFSET offsetof(struct retained_data, crc)
155
27
#define RETAINED_CHECKED_SIZE (RETAINED_CRC_OFFSET + sizeof(retained.crc))
156
28
157
29
bool retained_validate (void )
158
30
{
31
+ int rc ;
32
+
33
+ rc = retained_mem_read (retained_mem_device , 0 , (uint8_t * )& retained , sizeof (retained ));
34
+ __ASSERT_NO_MSG (rc == 0 );
35
+
159
36
/* The residue of a CRC is what you get from the CRC over the
160
37
* message catenated with its CRC. This is the post-final-xor
161
38
* residue for CRC-32 (CRC-32/ISO-HDLC) which Zephyr calls
@@ -174,19 +51,13 @@ bool retained_validate(void)
174
51
/* Reset to accrue runtime from this session. */
175
52
retained .uptime_latest = 0 ;
176
53
177
- /* Reconfigure to retain the state during system off, regardless of
178
- * whether validation succeeded. Although these values can sometimes
179
- * be observed to be preserved across System OFF, the product
180
- * specification states they are not retained in that situation, and
181
- * that can also be observed.
182
- */
183
- (void )ram_range_retain (& retained , RETAINED_CHECKED_SIZE , true);
184
-
185
54
return valid ;
186
55
}
187
56
188
57
void retained_update (void )
189
58
{
59
+ int rc ;
60
+
190
61
uint64_t now = k_uptime_ticks ();
191
62
192
63
retained .uptime_sum += (now - retained .uptime_latest );
@@ -196,4 +67,7 @@ void retained_update(void)
196
67
RETAINED_CRC_OFFSET );
197
68
198
69
retained .crc = sys_cpu_to_le32 (crc );
70
+
71
+ rc = retained_mem_write (retained_mem_device , 0 , (uint8_t * )& retained , sizeof (retained ));
72
+ __ASSERT_NO_MSG (rc == 0 );
199
73
}
0 commit comments