1065fc9a3SMatthias Ringwald /*
2065fc9a3SMatthias Ringwald * Copyright (C) 2022 BlueKitchen GmbH
3065fc9a3SMatthias Ringwald *
4065fc9a3SMatthias Ringwald * Redistribution and use in source and binary forms, with or without
5065fc9a3SMatthias Ringwald * modification, are permitted provided that the following conditions
6065fc9a3SMatthias Ringwald * are met:
7065fc9a3SMatthias Ringwald *
8065fc9a3SMatthias Ringwald * 1. Redistributions of source code must retain the above copyright
9065fc9a3SMatthias Ringwald * notice, this list of conditions and the following disclaimer.
10065fc9a3SMatthias Ringwald * 2. Redistributions in binary form must reproduce the above copyright
11065fc9a3SMatthias Ringwald * notice, this list of conditions and the following disclaimer in the
12065fc9a3SMatthias Ringwald * documentation and/or other materials provided with the distribution.
13065fc9a3SMatthias Ringwald * 3. Neither the name of the copyright holders nor the names of
14065fc9a3SMatthias Ringwald * contributors may be used to endorse or promote products derived
15065fc9a3SMatthias Ringwald * from this software without specific prior written permission.
16065fc9a3SMatthias Ringwald *
17065fc9a3SMatthias Ringwald * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
18065fc9a3SMatthias Ringwald * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19065fc9a3SMatthias Ringwald * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
20065fc9a3SMatthias Ringwald * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN
21065fc9a3SMatthias Ringwald * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22065fc9a3SMatthias Ringwald * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23065fc9a3SMatthias Ringwald * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
24065fc9a3SMatthias Ringwald * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
25065fc9a3SMatthias Ringwald * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26065fc9a3SMatthias Ringwald * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
27065fc9a3SMatthias Ringwald * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28065fc9a3SMatthias Ringwald * SUCH DAMAGE.
29065fc9a3SMatthias Ringwald *
30065fc9a3SMatthias Ringwald */
31065fc9a3SMatthias Ringwald
32065fc9a3SMatthias Ringwald /*
33065fc9a3SMatthias Ringwald * hal_flash_bank_chbios.c
34065fc9a3SMatthias Ringwald *
35065fc9a3SMatthias Ringwald * HAL abstraction for Flash memory using hal_flash and hal_efl.h on ELFD1
36065fc9a3SMatthias Ringwald */
37065fc9a3SMatthias Ringwald
38065fc9a3SMatthias Ringwald #define BTSTACK_FILE__ "hal_flash_bank_chibios.c"
39065fc9a3SMatthias Ringwald
40065fc9a3SMatthias Ringwald #include "hal_flash_bank.h"
41065fc9a3SMatthias Ringwald #include "btstack_debug.h"
42065fc9a3SMatthias Ringwald #include "btstack_util.h"
43065fc9a3SMatthias Ringwald
44065fc9a3SMatthias Ringwald #include "hal_flash_bank_chibios.h"
45065fc9a3SMatthias Ringwald #include "hal.h"
46065fc9a3SMatthias Ringwald
47065fc9a3SMatthias Ringwald #include <inttypes.h>
48065fc9a3SMatthias Ringwald #include <string.h> // memcpy
49065fc9a3SMatthias Ringwald
hal_flash_bank_chibios_get_size(void * context)50065fc9a3SMatthias Ringwald uint32_t hal_flash_bank_chibios_get_size(void * context){
51065fc9a3SMatthias Ringwald hal_flash_bank_chbios_t * self = (hal_flash_bank_chbios_t *) context;
52065fc9a3SMatthias Ringwald return self->sector_size;
53065fc9a3SMatthias Ringwald }
54065fc9a3SMatthias Ringwald
hal_flash_bank_chibios_get_alignment(void * context)55065fc9a3SMatthias Ringwald uint32_t hal_flash_bank_chibios_get_alignment(void * context){
56065fc9a3SMatthias Ringwald UNUSED(context);
57065fc9a3SMatthias Ringwald return 4;
58065fc9a3SMatthias Ringwald }
59065fc9a3SMatthias Ringwald
hal_flash_bank_chibios_erase(void * context,int bank)60065fc9a3SMatthias Ringwald void hal_flash_bank_chibios_erase(void * context, int bank){
61065fc9a3SMatthias Ringwald hal_flash_bank_chbios_t * self = (hal_flash_bank_chbios_t *) context;
62065fc9a3SMatthias Ringwald if (bank > 1) return;
63065fc9a3SMatthias Ringwald flashStartEraseSector(&EFLD1, self->sectors[bank]);
64065fc9a3SMatthias Ringwald // poll until done
65065fc9a3SMatthias Ringwald bool done = false;
66065fc9a3SMatthias Ringwald while (!done){
67065fc9a3SMatthias Ringwald uint32_t retry_delay_ms;
68065fc9a3SMatthias Ringwald flash_error_t result = flashQueryErase(&EFLD1, &retry_delay_ms);
69065fc9a3SMatthias Ringwald switch (result){
70065fc9a3SMatthias Ringwald case FLASH_BUSY_ERASING:
71065fc9a3SMatthias Ringwald chThdSleepMilliseconds( retry_delay_ms );
72065fc9a3SMatthias Ringwald break;
73065fc9a3SMatthias Ringwald case FLASH_NO_ERROR:
74065fc9a3SMatthias Ringwald done = true;
75065fc9a3SMatthias Ringwald break;
76065fc9a3SMatthias Ringwald default:
77065fc9a3SMatthias Ringwald btstack_assert(false);
78065fc9a3SMatthias Ringwald break;
79065fc9a3SMatthias Ringwald }
80065fc9a3SMatthias Ringwald }
81065fc9a3SMatthias Ringwald }
82065fc9a3SMatthias Ringwald
hal_flash_bank_chibios_read(void * context,int bank,uint32_t offset,uint8_t * buffer,uint32_t size)83065fc9a3SMatthias Ringwald void hal_flash_bank_chibios_read(void * context, int bank, uint32_t offset, uint8_t * buffer, uint32_t size){
84065fc9a3SMatthias Ringwald hal_flash_bank_chbios_t * self = (hal_flash_bank_chbios_t *) context;
85065fc9a3SMatthias Ringwald
86065fc9a3SMatthias Ringwald if (bank > 1) return;
87065fc9a3SMatthias Ringwald if (offset > self->sector_size) return;
88065fc9a3SMatthias Ringwald if ((offset + size) > self->sector_size) return;
89065fc9a3SMatthias Ringwald
90065fc9a3SMatthias Ringwald flashRead(&EFLD1, self->banks[bank] + offset, size, buffer);
91065fc9a3SMatthias Ringwald }
92065fc9a3SMatthias Ringwald
hal_flash_bank_chibios_write(void * context,int bank,uint32_t offset,const uint8_t * data,uint32_t size)93065fc9a3SMatthias Ringwald void hal_flash_bank_chibios_write(void * context, int bank, uint32_t offset, const uint8_t * data, uint32_t size){
94065fc9a3SMatthias Ringwald hal_flash_bank_chbios_t * self = (hal_flash_bank_chbios_t *) context;
95065fc9a3SMatthias Ringwald
96065fc9a3SMatthias Ringwald if (bank > 1) return;
97065fc9a3SMatthias Ringwald if (offset > self->sector_size) return;
98065fc9a3SMatthias Ringwald if ((offset + size) > self->sector_size) return;
99065fc9a3SMatthias Ringwald
100065fc9a3SMatthias Ringwald flashProgram(&EFLD1, self->banks[bank] + offset, size, data);
101065fc9a3SMatthias Ringwald }
102065fc9a3SMatthias Ringwald
103065fc9a3SMatthias Ringwald static const hal_flash_bank_t hal_flash_bank_chibios = {
104065fc9a3SMatthias Ringwald &hal_flash_bank_chibios_get_size,
105065fc9a3SMatthias Ringwald &hal_flash_bank_chibios_get_alignment,
106065fc9a3SMatthias Ringwald &hal_flash_bank_chibios_erase,
107065fc9a3SMatthias Ringwald &hal_flash_bank_chibios_read,
108065fc9a3SMatthias Ringwald &hal_flash_bank_chibios_write
109065fc9a3SMatthias Ringwald };
110065fc9a3SMatthias Ringwald
hal_flash_bank_chibios_init_instance(hal_flash_bank_chbios_t * context,uint16_t bank_0_sector,uint16_t bank_1_sector)111065fc9a3SMatthias Ringwald const hal_flash_bank_t * hal_flash_bank_chibios_init_instance(hal_flash_bank_chbios_t * context,
112065fc9a3SMatthias Ringwald uint16_t bank_0_sector, uint16_t bank_1_sector){
113065fc9a3SMatthias Ringwald
114*f508b0b1SMatthias Ringwald // start EFL driver
115*f508b0b1SMatthias Ringwald eflStart(&EFLD1, NULL);
116*f508b0b1SMatthias Ringwald
117065fc9a3SMatthias Ringwald const flash_descriptor_t * descriptor = flashGetDescriptor(&EFLD1);
118065fc9a3SMatthias Ringwald btstack_assert(bank_0_sector < descriptor->sectors_count);
119065fc9a3SMatthias Ringwald btstack_assert(bank_1_sector < descriptor->sectors_count);
120065fc9a3SMatthias Ringwald
121065fc9a3SMatthias Ringwald // get bank size and offsets from chibios flash descriptor
122065fc9a3SMatthias Ringwald uint32_t bank_0_offset = descriptor->sectors[bank_0_sector].offset;
123065fc9a3SMatthias Ringwald uint32_t bank_1_offset = descriptor->sectors[bank_1_sector].offset;
124065fc9a3SMatthias Ringwald uint32_t sector_size = btstack_min(descriptor->sectors[bank_0_sector].size, descriptor->sectors[bank_1_sector].size);
125065fc9a3SMatthias Ringwald
126065fc9a3SMatthias Ringwald context->sector_size = sector_size;
127065fc9a3SMatthias Ringwald context->sectors[0] = bank_0_sector;
128065fc9a3SMatthias Ringwald context->sectors[1] = bank_1_sector;
129065fc9a3SMatthias Ringwald context->banks[0] = bank_0_offset;
130065fc9a3SMatthias Ringwald context->banks[1] = bank_1_offset;
131*f508b0b1SMatthias Ringwald
132065fc9a3SMatthias Ringwald log_info("Bank size %" PRIu32 " bytes", sector_size);
133065fc9a3SMatthias Ringwald log_info("Bank 0 uses sector %u, offset %" PRIx32, bank_0_sector, bank_0_offset);
134065fc9a3SMatthias Ringwald log_info("Bank 1 uses sector %u, offset %" PRIx32, bank_1_sector, bank_1_offset);
135*f508b0b1SMatthias Ringwald
136065fc9a3SMatthias Ringwald return &hal_flash_bank_chibios;
137065fc9a3SMatthias Ringwald }
138