1 /*
2 * Copyright (C) 2020 BlueKitchen GmbH
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the copyright holders nor the names of
14 * contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 * 4. Any redistribution, use, or modification is done solely for
17 * personal benefit and not for any commercial purpose or for
18 * monetary gain.
19 *
20 * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN
24 * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * Please inquire about commercial licensing options at
34 * [email protected]
35 *
36 */
37
38 #define BTSTACK_FILE__ "hal_flash_bank_fsp.c"
39
40 #include <stdint.h>
41 #include <string.h> // memcpy
42 #include <btstack_util.h>
43
44 #include "hal_flash_bank_fsp.h"
45 #include "btstack_debug.h"
46 #include "hal_data.h"
47
hal_flash_bank_fsp_get_size(void * context)48 static uint32_t hal_flash_bank_fsp_get_size(void * context){
49 hal_flash_bank_fsp_t * self = (hal_flash_bank_fsp_t *) context;
50 return self->bank_size;
51 }
52
hal_flash_bank_fsp_get_alignment(void * context)53 static uint32_t hal_flash_bank_fsp_get_alignment(void * context){
54 UNUSED(context);
55 return 1;
56 }
57
58 // returns offset of first blank data in bank
hal_flash_bank_fsp_detect_blank_start(uint32_t bank_start,uint32_t bank_size)59 static uint32_t hal_flash_bank_fsp_detect_blank_start(uint32_t bank_start, uint32_t bank_size){
60 // binary search. right points to start of blank or at end of bank
61 uint32_t left = 0;
62 uint32_t right = bank_size;
63 while (left < right){
64 uint32_t middle = (left + right) / 2;
65 flash_result_t blank_check_result;
66 fsp_err_t err = R_FLASH_HP_BlankCheck(&g_flash0_ctrl, (uint32_t) (bank_start + middle), bank_size - middle, &blank_check_result);
67 btstack_assert(FSP_SUCCESS == err);
68 if (FLASH_RESULT_BLANK == blank_check_result){
69 // blank from middle..right
70 right = middle;
71 } else {
72 // middle is not blank, blank starts at least one byte higher
73 left = middle + 1;
74 }
75 }
76 return right;
77 }
78
hal_flash_bank_fsp_erase(void * context,int bank)79 static void hal_flash_bank_fsp_erase(void * context, int bank){
80 hal_flash_bank_fsp_t * self = (hal_flash_bank_fsp_t *) context;
81 if (bank > 1) return;
82 fsp_err_t err = R_FLASH_HP_Erase(&g_flash0_ctrl, self->bank_addr[bank], self->bank_size / self->block_size);
83 btstack_assert(err == FSP_SUCCESS);
84 }
85
hal_flash_bank_fsp_read(void * context,int bank,uint32_t offset,uint8_t * buffer,uint32_t size)86 static void hal_flash_bank_fsp_read(void * context, int bank, uint32_t offset, uint8_t * buffer, uint32_t size){
87 hal_flash_bank_fsp_t * self = (hal_flash_bank_fsp_t *) context;
88 uint32_t end_addr_read = offset + size;
89
90 if (bank > 1) return;
91 if (offset > self->bank_size) return;
92 if (end_addr_read > self->bank_size) return;
93
94 // first copy valid bytes
95 uint32_t bytes_to_copy = 0;
96 uint32_t end_addr_copy = btstack_min(end_addr_read, self->blank_start[bank]);
97 if (end_addr_copy > offset){
98 bytes_to_copy = end_addr_copy - offset;
99 memcpy(buffer, (uint8_t *) (self->bank_addr[bank] + offset), bytes_to_copy);
100 buffer += bytes_to_copy;
101 }
102 // fill rest with 0xff
103 uint32_t bytes_to_fill = size - bytes_to_copy;
104 if (bytes_to_fill > 0){
105 memset(buffer, 0xff, bytes_to_fill);
106 }
107 }
108
hal_flash_bank_fsp_write(void * context,int bank,uint32_t offset,const uint8_t * data,uint32_t size)109 static void hal_flash_bank_fsp_write(void * context, int bank, uint32_t offset, const uint8_t * data, uint32_t size){
110 hal_flash_bank_fsp_t * self = (hal_flash_bank_fsp_t *) context;
111
112 if (bank > 1) return;
113 if (offset > self->bank_size) return;
114 if ((offset + size) > self->bank_size) return;
115
116 // update blank start
117 self->blank_start[bank] = btstack_max(self->blank_start[bank], offset + size);
118
119 fsp_err_t err = R_FLASH_HP_Write(&g_flash0_ctrl, (uint32_t) data, offset, size);
120 btstack_assert(err == FSP_SUCCESS);
121 }
122
123 static const hal_flash_bank_t hal_flash_bank_fsp_impl = {
124 /* uint32_t (*get_size)() */ &hal_flash_bank_fsp_get_size,
125 /* uint32_t (*get_alignment)(..); */ &hal_flash_bank_fsp_get_alignment,
126 /* void (*erase)(..); */ &hal_flash_bank_fsp_erase,
127 /* void (*read)(..); */ &hal_flash_bank_fsp_read,
128 /* void (*write)(..); */ &hal_flash_bank_fsp_write,
129 };
130
hal_flash_bank_fsp_init_instance(hal_flash_bank_fsp_t * context,uint32_t bank_size,uint32_t bank_0_addr,uint32_t bank_1_addr)131 const hal_flash_bank_t * hal_flash_bank_fsp_init_instance(hal_flash_bank_fsp_t * context, uint32_t bank_size,
132 uint32_t bank_0_addr, uint32_t bank_1_addr){
133 // get info
134 flash_info_t p_info;
135 R_FLASH_HP_InfoGet(&g_flash0_ctrl, &p_info);
136 // assume first region of data flash is used
137 btstack_assert(bank_0_addr >= p_info.data_flash.p_block_array[0].block_section_st_addr);
138 btstack_assert((bank_0_addr + bank_size - 1) <= p_info.data_flash.p_block_array[0].block_section_end_addr);
139 btstack_assert(bank_1_addr >= p_info.data_flash.p_block_array[0].block_section_st_addr);
140 btstack_assert((bank_1_addr + bank_size - 1) <= p_info.data_flash.p_block_array[0].block_section_end_addr);
141 context->block_size = p_info.data_flash.p_block_array[0].block_size;
142 context->bank_size = bank_size;
143 context->bank_addr[0] = bank_0_addr;
144 context->bank_addr[1] = bank_1_addr;
145 // get start of blank area
146 context->blank_start[0] = hal_flash_bank_fsp_detect_blank_start(context->bank_addr[0], bank_size);
147 context->blank_start[1] = hal_flash_bank_fsp_detect_blank_start(context->bank_addr[1], bank_size);
148 return &hal_flash_bank_fsp_impl;
149 }
150