xref: /btstack/port/renesas-ek-ra6m4a-da14531/port/hal_flash_bank_fsp.c (revision c30869498fb8e98c1408c9db0e7624f02f483b73)
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