1 // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 #include "catch.hpp"
15 #include "esp_spi_flash.h"
16 #include "esp_partition.h"
17 #include "spi_flash_emulation.h"
18 #include <functional>
19 
20 using namespace std;
21 
22 template <typename Tit>
range_empty_n(Tit it_begin,size_t n)23 bool range_empty_n(Tit it_begin, size_t n)
24 {
25     return all_of(it_begin, it_begin + n, bind(equal_to<uint32_t>(), placeholders::_1, 0xffffffff));
26 }
27 
28 struct FlashEmuFixture {
FlashEmuFixtureFlashEmuFixture29     FlashEmuFixture(size_t sectors) : esp_part(), emu(sectors) { }
30 
31     esp_partition_t esp_part;
32     SpiFlashEmulator emu;
33 };
34 
35 TEST_CASE("flash starts with all bytes == 0xff", "[spi_flash_emu]")
36 {
37     FlashEmuFixture f(4);
38 
39     uint8_t sector[SPI_FLASH_SEC_SIZE];
40 
41     for (int i = 0; i < 4; ++i) {
42         CHECK(esp_partition_read(&f.esp_part, 0, sector, sizeof(sector)) == ESP_OK);
43         for (auto v: sector) {
44             CHECK(v == 0xff);
45         }
46     }
47 }
48 
49 TEST_CASE("invalid writes are checked", "[spi_flash_emu]")
50 {
51     FlashEmuFixture f(1);
52 
53     uint32_t val = 0;
54     CHECK(esp_partition_write(&f.esp_part, 0, &val, 4) == ESP_OK);
55     val = 1;
56     CHECK(esp_partition_write(&f.esp_part, 0, &val, 4) == ESP_ERR_FLASH_OP_FAIL);
57 }
58 
59 
60 TEST_CASE("out of bounds writes fail", "[spi_flash_emu]")
61 {
62     FlashEmuFixture f(4);
63     uint32_t vals[8];
64     std::fill_n(vals, 8, 0);
65     CHECK(esp_partition_write(&f.esp_part, 0, &vals, sizeof(vals)) == ESP_OK);
66 
67     CHECK(esp_partition_write(&f.esp_part, 4*4096 - sizeof(vals), &vals, sizeof(vals)) == ESP_OK);
68 
69     CHECK(esp_partition_write(&f.esp_part, 4*4096 - sizeof(vals) + 4, &vals, sizeof(vals)) == ESP_ERR_FLASH_OP_FAIL);
70 }
71 
72 TEST_CASE("after erase the sector is set to 0xff", "[spi_flash_emu]")
73 {
74     FlashEmuFixture f(4);
75     uint32_t val1 = 0xab00cd12;
76     CHECK(esp_partition_write(&f.esp_part, 0, &val1, sizeof(val1)) == ESP_OK);
77     uint32_t val2 = 0x5678efab;
78     CHECK(esp_partition_write(&f.esp_part, 4096 - 4, &val2, sizeof(val2)) == ESP_OK);
79 
80     CHECK(f.emu.words()[0] == val1);
81     CHECK(range_empty_n(f.emu.words() + 1, 4096 / 4 - 2));
82     CHECK(f.emu.words()[4096 / 4 - 1] == val2);
83 
84     CHECK(esp_partition_erase_range(&f.esp_part, 0, SPI_FLASH_SEC_SIZE) == ESP_OK);
85 
86     CHECK(f.emu.words()[0] == 0xffffffff);
87     CHECK(range_empty_n(f.emu.words() + 1, 4096 / 4 - 2));
88     CHECK(f.emu.words()[4096 / 4 - 1] == 0xffffffff);
89 }
90 
91 TEST_CASE("EMU raw read function works", "[spi_flash_emu]")
92 {
93     FlashEmuFixture f(4);
94     uint32_t value = 0xdeadbeef;
95     uint32_t read_value = 0;
96     CHECK(esp_partition_write(&f.esp_part, 0, &value, sizeof(value)) == ESP_OK);
97 
98     CHECK(esp_partition_read_raw(&f.esp_part, 0, &read_value, sizeof(&read_value)) == ESP_OK);
99 
100     CHECK(read_value == 0xdeadbeef);
101 }
102 
103 TEST_CASE("EMU raw write function works", "[spi_flash_emu]")
104 {
105     FlashEmuFixture f(4);
106     uint32_t value = 0xdeadbeef;
107     uint32_t read_value = 0;
108     CHECK(esp_partition_write_raw(&f.esp_part, 0, &value, sizeof(value)) == ESP_OK);
109 
110     CHECK(esp_partition_read(&f.esp_part, 0, &read_value, sizeof(&read_value)) == ESP_OK);
111 
112     CHECK(read_value == 0xdeadbeef);
113 }
114 
115 TEST_CASE("read/write/erase operation times are calculated correctly", "[spi_flash_emu]")
116 {
117     FlashEmuFixture f(1);
118     uint8_t data[512];
119     esp_partition_read(&f.esp_part, 0, data, 4);
120     CHECK(f.emu.getTotalTime() == 7);
121     CHECK(f.emu.getReadOps() == 1);
122     CHECK(f.emu.getReadBytes() == 4);
123     f.emu.clearStats();
124     esp_partition_read(&f.esp_part, 0, data, 8);
125     CHECK(f.emu.getTotalTime() == 5);
126     CHECK(f.emu.getReadOps() == 1);
127     CHECK(f.emu.getReadBytes() == 8);
128     f.emu.clearStats();
129     esp_partition_read(&f.esp_part, 0, data, 16);
130     CHECK(f.emu.getTotalTime() == 6);
131     CHECK(f.emu.getReadOps() == 1);
132     CHECK(f.emu.getReadBytes() == 16);
133     f.emu.clearStats();
134     esp_partition_read(&f.esp_part, 0, data, 128);
135     CHECK(f.emu.getTotalTime() == 18);
136     CHECK(f.emu.getReadOps() == 1);
137     CHECK(f.emu.getReadBytes() == 128);
138     f.emu.clearStats();
139     esp_partition_read(&f.esp_part, 0, data, 256);
140     CHECK(f.emu.getTotalTime() == 32);
141     f.emu.clearStats();
142     esp_partition_read(&f.esp_part, 0, data, (128+256)/2);
143     CHECK(f.emu.getTotalTime() == (18+32)/2);
144     f.emu.clearStats();
145 
146     esp_partition_write(&f.esp_part, 0, data, 4);
147     CHECK(f.emu.getTotalTime() == 19);
148     CHECK(f.emu.getWriteOps() == 1);
149     CHECK(f.emu.getWriteBytes() == 4);
150     f.emu.clearStats();
151     CHECK(f.emu.getWriteOps() == 0);
152     CHECK(f.emu.getWriteBytes() == 0);
153     esp_partition_write(&f.esp_part, 0, data, 8);
154     CHECK(f.emu.getTotalTime() == 23);
155     f.emu.clearStats();
156     esp_partition_write(&f.esp_part, 0, data, 16);
157     CHECK(f.emu.getTotalTime() == 35);
158     CHECK(f.emu.getWriteOps() == 1);
159     CHECK(f.emu.getWriteBytes() == 16);
160     f.emu.clearStats();
161     esp_partition_write(&f.esp_part, 0, data, 128);
162     CHECK(f.emu.getTotalTime() == 205);
163     f.emu.clearStats();
164     esp_partition_write(&f.esp_part, 0, data, 256);
165     CHECK(f.emu.getTotalTime() == 417);
166     f.emu.clearStats();
167     esp_partition_write(&f.esp_part, 0, data, (128+256)/2);
168     CHECK(f.emu.getTotalTime() == (205+417)/2);
169     f.emu.clearStats();
170 
171     esp_partition_erase_range(&f.esp_part, 0, SPI_FLASH_SEC_SIZE);
172     CHECK(f.emu.getEraseOps() == 1);
173     CHECK(f.emu.getTotalTime() == 37142);
174 }
175 
176 TEST_CASE("data is randomized predictably", "[spi_flash_emu]")
177 {
178     SpiFlashEmulator emu1(3);
179     emu1.randomize(0x12345678);
180 
181     SpiFlashEmulator emu2(3);
182     emu2.randomize(0x12345678);
183 
184     CHECK(std::equal(emu1.bytes(), emu1.bytes() + emu1.size(), emu2.bytes()));
185 }
186