Software APIs
retention_sram_functest.c
1 // Copyright lowRISC contributors (OpenTitan project).
2 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
3 // SPDX-License-Identifier: Apache-2.0
4 
5 #include <stdbool.h>
6 #include <stdint.h>
7 
12 #include "sw/device/silicon_creator/lib/drivers/retention_sram.h"
13 #include "sw/device/silicon_creator/lib/error.h"
14 
16 
17 // Variables of type `retention_sram_t` are static to reduce stack usage.
18 static retention_sram_t ret;
19 static uint64_t raw[sizeof(retention_sram_t) / sizeof(uint64_t)];
20 
21 static rom_error_t retention_sram_clear_test(void) {
22  retention_sram_t *ret = retention_sram_get();
23 
24  // Set every bit in the retention SRAM to one.
25  memset(ret, 0xff, sizeof(retention_sram_t));
26 
27  // Clear the retention SRAM (set every bit to zero).
28  retention_sram_clear();
29 
30  // Check that the retention SRAM was fully cleared.
31  char *buf = (char *)ret;
32  for (size_t i = 0; i < sizeof(retention_sram_t); i += 4, buf += 4) {
33  if (read_32(buf) != 0) {
34  LOG_ERROR("Retention SRAM not cleared.");
35  return kErrorUnknown; // Unreachable.
36  }
37  }
38  return kErrorOk;
39 }
40 
41 rom_error_t retention_sram_scramble_test(void) {
42  // Clear the retention SRAM (set every bit to zero).
43  retention_sram_clear();
44 
45  // Scramble the retention SRAM.
46  LOG_INFO("Scrambling retention SRAM.");
47  retention_sram_scramble();
48 
49  // Copy the contents of the retention SRAM into an array of 64-bit integers.
50  // We use 64-bit integers rather than 32-bit integers to reduce the
51  // probability of an individual value staying the same after scrambling.
52  // Retention SRAM accesses will stall until scrambling is complete.
53  LOG_INFO(
54  "Checking retention SRAM is scrambled (will stall for a short time).");
55  ret = *retention_sram_get();
56  memcpy(raw, &ret, sizeof(retention_sram_t));
57 
58  // Check that every entry in the retention SRAM has changed.
59  uint32_t matches = 0;
60  for (size_t i = 0; i < ARRAYSIZE(raw); ++i) {
61  if (raw[i] == 0) {
62  LOG_ERROR("Retention SRAM unchanged at offset %u.", i);
63  matches += 1;
64  }
65  }
66 
67  // It is possible, albeit extremely unlikely, that scrambling executed
68  // correctly but one or more double words are still zero. If this occurs
69  // in practice it may be necessary to increase the number of matches that
70  // are tolerated.
71  LOG_INFO("Finishing retention SRAM scrambling test (matches=%u).", matches);
72  return matches != 0 ? kErrorUnknown : kErrorOk;
73 }
74 
75 OTTF_DEFINE_TEST_CONFIG();
76 
77 bool test_main(void) {
78  status_t result = OK_STATUS();
79  EXECUTE_TEST(result, retention_sram_clear_test);
80  EXECUTE_TEST(result, retention_sram_scramble_test);
81  return status_ok(result);
82 }