1 /* 2 * Copyright (C) 2022 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 * 17 * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 20 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN 21 * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 24 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 25 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 27 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 * 30 */ 31 32 /* 33 * hal_flash_bank_chbios.c 34 * 35 * HAL abstraction for Flash memory using hal_flash and hal_efl.h on ELFD1 36 */ 37 38 #define BTSTACK_FILE__ "hal_flash_bank_chibios.c" 39 40 #include "hal_flash_bank.h" 41 #include "btstack_debug.h" 42 #include "btstack_util.h" 43 44 #include "hal_flash_bank_chibios.h" 45 #include "hal.h" 46 47 #include <inttypes.h> 48 #include <string.h> // memcpy 49 50 uint32_t hal_flash_bank_chibios_get_size(void * context){ 51 hal_flash_bank_chbios_t * self = (hal_flash_bank_chbios_t *) context; 52 return self->sector_size; 53 } 54 55 uint32_t hal_flash_bank_chibios_get_alignment(void * context){ 56 UNUSED(context); 57 return 4; 58 } 59 60 void hal_flash_bank_chibios_erase(void * context, int bank){ 61 hal_flash_bank_chbios_t * self = (hal_flash_bank_chbios_t *) context; 62 if (bank > 1) return; 63 flashStartEraseSector(&EFLD1, self->sectors[bank]); 64 // poll until done 65 bool done = false; 66 while (!done){ 67 uint32_t retry_delay_ms; 68 flash_error_t result = flashQueryErase(&EFLD1, &retry_delay_ms); 69 switch (result){ 70 case FLASH_BUSY_ERASING: 71 chThdSleepMilliseconds( retry_delay_ms ); 72 break; 73 case FLASH_NO_ERROR: 74 done = true; 75 break; 76 default: 77 btstack_assert(false); 78 break; 79 } 80 } 81 } 82 83 void hal_flash_bank_chibios_read(void * context, int bank, uint32_t offset, uint8_t * buffer, uint32_t size){ 84 hal_flash_bank_chbios_t * self = (hal_flash_bank_chbios_t *) context; 85 86 if (bank > 1) return; 87 if (offset > self->sector_size) return; 88 if ((offset + size) > self->sector_size) return; 89 90 flashRead(&EFLD1, self->banks[bank] + offset, size, buffer); 91 } 92 93 void hal_flash_bank_chibios_write(void * context, int bank, uint32_t offset, const uint8_t * data, uint32_t size){ 94 hal_flash_bank_chbios_t * self = (hal_flash_bank_chbios_t *) context; 95 96 if (bank > 1) return; 97 if (offset > self->sector_size) return; 98 if ((offset + size) > self->sector_size) return; 99 100 flashProgram(&EFLD1, self->banks[bank] + offset, size, data); 101 } 102 103 static const hal_flash_bank_t hal_flash_bank_chibios = { 104 &hal_flash_bank_chibios_get_size, 105 &hal_flash_bank_chibios_get_alignment, 106 &hal_flash_bank_chibios_erase, 107 &hal_flash_bank_chibios_read, 108 &hal_flash_bank_chibios_write 109 }; 110 111 const hal_flash_bank_t * hal_flash_bank_chibios_init_instance(hal_flash_bank_chbios_t * context, 112 uint16_t bank_0_sector, uint16_t bank_1_sector){ 113 114 // start EFL driver 115 eflStart(&EFLD1, NULL); 116 117 const flash_descriptor_t * descriptor = flashGetDescriptor(&EFLD1); 118 btstack_assert(bank_0_sector < descriptor->sectors_count); 119 btstack_assert(bank_1_sector < descriptor->sectors_count); 120 121 // get bank size and offsets from chibios flash descriptor 122 uint32_t bank_0_offset = descriptor->sectors[bank_0_sector].offset; 123 uint32_t bank_1_offset = descriptor->sectors[bank_1_sector].offset; 124 uint32_t sector_size = btstack_min(descriptor->sectors[bank_0_sector].size, descriptor->sectors[bank_1_sector].size); 125 126 context->sector_size = sector_size; 127 context->sectors[0] = bank_0_sector; 128 context->sectors[1] = bank_1_sector; 129 context->banks[0] = bank_0_offset; 130 context->banks[1] = bank_1_offset; 131 132 log_info("Bank size %" PRIu32 " bytes", sector_size); 133 log_info("Bank 0 uses sector %u, offset %" PRIx32, bank_0_sector, bank_0_offset); 134 log_info("Bank 1 uses sector %u, offset %" PRIx32, bank_1_sector, bank_1_offset); 135 136 return &hal_flash_bank_chibios; 137 } 138