1 // Copyright 2015-2017 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
15 #include <string.h>
16 #include "diskio_impl.h"
17 #include "ffconf.h"
18 #include "ff.h"
19 #include "esp_log.h"
20 #include "diskio_wl.h"
21 #include "wear_levelling.h"
22 #include "esp_compiler.h"
23
24 static const char* TAG = "ff_diskio_spiflash";
25
26 wl_handle_t ff_wl_handles[FF_VOLUMES] = {
27 WL_INVALID_HANDLE,
28 WL_INVALID_HANDLE,
29 };
30
ff_wl_initialize(BYTE pdrv)31 DSTATUS ff_wl_initialize (BYTE pdrv)
32 {
33 return 0;
34 }
35
ff_wl_status(BYTE pdrv)36 DSTATUS ff_wl_status (BYTE pdrv)
37 {
38 return 0;
39 }
40
ff_wl_read(BYTE pdrv,BYTE * buff,DWORD sector,UINT count)41 DRESULT ff_wl_read (BYTE pdrv, BYTE *buff, DWORD sector, UINT count)
42 {
43 ESP_LOGV(TAG, "ff_wl_read - pdrv=%i, sector=%i, count=%i\n", (unsigned int)pdrv, (unsigned int)sector, (unsigned int)count);
44 wl_handle_t wl_handle = ff_wl_handles[pdrv];
45 assert(wl_handle + 1);
46 esp_err_t err = wl_read(wl_handle, sector * wl_sector_size(wl_handle), buff, count * wl_sector_size(wl_handle));
47 if (unlikely(err != ESP_OK)) {
48 ESP_LOGE(TAG, "wl_read failed (%d)", err);
49 return RES_ERROR;
50 }
51 return RES_OK;
52 }
53
ff_wl_write(BYTE pdrv,const BYTE * buff,DWORD sector,UINT count)54 DRESULT ff_wl_write (BYTE pdrv, const BYTE *buff, DWORD sector, UINT count)
55 {
56 ESP_LOGV(TAG, "ff_wl_write - pdrv=%i, sector=%i, count=%i\n", (unsigned int)pdrv, (unsigned int)sector, (unsigned int)count);
57 wl_handle_t wl_handle = ff_wl_handles[pdrv];
58 assert(wl_handle + 1);
59 esp_err_t err = wl_erase_range(wl_handle, sector * wl_sector_size(wl_handle), count * wl_sector_size(wl_handle));
60 if (unlikely(err != ESP_OK)) {
61 ESP_LOGE(TAG, "wl_erase_range failed (%d)", err);
62 return RES_ERROR;
63 }
64 err = wl_write(wl_handle, sector * wl_sector_size(wl_handle), buff, count * wl_sector_size(wl_handle));
65 if (unlikely(err != ESP_OK)) {
66 ESP_LOGE(TAG, "wl_write failed (%d)", err);
67 return RES_ERROR;
68 }
69 return RES_OK;
70 }
71
ff_wl_ioctl(BYTE pdrv,BYTE cmd,void * buff)72 DRESULT ff_wl_ioctl (BYTE pdrv, BYTE cmd, void *buff)
73 {
74 wl_handle_t wl_handle = ff_wl_handles[pdrv];
75 ESP_LOGV(TAG, "ff_wl_ioctl: cmd=%i\n", cmd);
76 assert(wl_handle + 1);
77 switch (cmd) {
78 case CTRL_SYNC:
79 return RES_OK;
80 case GET_SECTOR_COUNT:
81 *((DWORD *) buff) = wl_size(wl_handle) / wl_sector_size(wl_handle);
82 return RES_OK;
83 case GET_SECTOR_SIZE:
84 *((WORD *) buff) = wl_sector_size(wl_handle);
85 return RES_OK;
86 case GET_BLOCK_SIZE:
87 return RES_ERROR;
88 }
89 return RES_ERROR;
90 }
91
92
ff_diskio_register_wl_partition(BYTE pdrv,wl_handle_t flash_handle)93 esp_err_t ff_diskio_register_wl_partition(BYTE pdrv, wl_handle_t flash_handle)
94 {
95 if (pdrv >= FF_VOLUMES) {
96 return ESP_ERR_INVALID_ARG;
97 }
98 static const ff_diskio_impl_t wl_impl = {
99 .init = &ff_wl_initialize,
100 .status = &ff_wl_status,
101 .read = &ff_wl_read,
102 .write = &ff_wl_write,
103 .ioctl = &ff_wl_ioctl
104 };
105 ff_wl_handles[pdrv] = flash_handle;
106 ff_diskio_register(pdrv, &wl_impl);
107 return ESP_OK;
108 }
109
ff_diskio_get_pdrv_wl(wl_handle_t flash_handle)110 BYTE ff_diskio_get_pdrv_wl(wl_handle_t flash_handle)
111 {
112 for (int i = 0; i < FF_VOLUMES; i++) {
113 if (flash_handle == ff_wl_handles[i]) {
114 return i;
115 }
116 }
117 return 0xff;
118 }
119
ff_diskio_clear_pdrv_wl(wl_handle_t flash_handle)120 void ff_diskio_clear_pdrv_wl(wl_handle_t flash_handle)
121 {
122 for (int i = 0; i < FF_VOLUMES; i++) {
123 if (flash_handle == ff_wl_handles[i]) {
124 ff_wl_handles[i] = WL_INVALID_HANDLE;
125 }
126 }
127 }
128