Flash access library for GR-Boards.
FlashAccess.cpp@1:652a093cf264, 2017-11-28 (annotated)
- Committer:
- dkato
- Date:
- Tue Nov 28 06:46:10 2017 +0000
- Revision:
- 1:652a093cf264
- Parent:
- 0:5a74eeaefb5d
Text update
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
dkato | 0:5a74eeaefb5d | 1 | /******************************************************************************* |
dkato | 0:5a74eeaefb5d | 2 | * DISCLAIMER |
dkato | 0:5a74eeaefb5d | 3 | * This software is supplied by Renesas Electronics Corporation and is only |
dkato | 0:5a74eeaefb5d | 4 | * intended for use with Renesas products. No other uses are authorized. This |
dkato | 0:5a74eeaefb5d | 5 | * software is owned by Renesas Electronics Corporation and is protected under |
dkato | 0:5a74eeaefb5d | 6 | * all applicable laws, including copyright laws. |
dkato | 0:5a74eeaefb5d | 7 | * THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS MAKES NO WARRANTIES REGARDING |
dkato | 0:5a74eeaefb5d | 8 | * THIS SOFTWARE, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT |
dkato | 0:5a74eeaefb5d | 9 | * LIMITED TO WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE |
dkato | 0:5a74eeaefb5d | 10 | * AND NON-INFRINGEMENT. ALL SUCH WARRANTIES ARE EXPRESSLY DISCLAIMED. |
dkato | 0:5a74eeaefb5d | 11 | * TO THE MAXIMUM EXTENT PERMITTED NOT PROHIBITED BY LAW, NEITHER RENESAS |
dkato | 0:5a74eeaefb5d | 12 | * ELECTRONICS CORPORATION NOR ANY OF ITS AFFILIATED COMPANIES SHALL BE LIABLE |
dkato | 0:5a74eeaefb5d | 13 | * FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR |
dkato | 0:5a74eeaefb5d | 14 | * ANY REASON RELATED TO THIS SOFTWARE, EVEN IF RENESAS OR ITS AFFILIATES HAVE |
dkato | 0:5a74eeaefb5d | 15 | * BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. |
dkato | 0:5a74eeaefb5d | 16 | * Renesas reserves the right, without notice, to make changes to this software |
dkato | 0:5a74eeaefb5d | 17 | * and to discontinue the availability of this software. By using this software, |
dkato | 0:5a74eeaefb5d | 18 | * you agree to the additional terms and conditions found by accessing the |
dkato | 0:5a74eeaefb5d | 19 | * following link: |
dkato | 0:5a74eeaefb5d | 20 | * http://www.renesas.com/disclaimer |
dkato | 0:5a74eeaefb5d | 21 | * |
dkato | 0:5a74eeaefb5d | 22 | * Copyright (C) 2017 Renesas Electronics Corporation. All rights reserved. |
dkato | 0:5a74eeaefb5d | 23 | *******************************************************************************/ |
dkato | 0:5a74eeaefb5d | 24 | |
dkato | 0:5a74eeaefb5d | 25 | #include "mbed.h" |
dkato | 0:5a74eeaefb5d | 26 | #include "FlashAccess.h" |
dkato | 0:5a74eeaefb5d | 27 | |
dkato | 0:5a74eeaefb5d | 28 | /* ---- serial flash command ---- */ |
dkato | 0:5a74eeaefb5d | 29 | #define SFLASHCMD_SECTOR_ERASE (0x20u) /* SE 3-byte address(1bit) */ |
dkato | 0:5a74eeaefb5d | 30 | #define SFLASHCMD_PAGE_PROGRAM (0x02u) /* PP 3-byte address(1bit), data(1bit) */ |
dkato | 0:5a74eeaefb5d | 31 | #define SFLASHCMD_READ (0x03u) /* READ 3-byte address(1bit), data(1bit) */ |
dkato | 0:5a74eeaefb5d | 32 | #define SFLASHCMD_READ_STATUS_REG (0x05u) /* RDSR data(1bit) */ |
dkato | 0:5a74eeaefb5d | 33 | #define SFLASHCMD_WRITE_ENABLE (0x06u) /* WREN */ |
dkato | 0:5a74eeaefb5d | 34 | /* ---- serial flash register definitions ---- */ |
dkato | 0:5a74eeaefb5d | 35 | #define STREG_BUSY_BIT (0x01u) /* SR.[0]BUSY Erase/Write In Progress (RO) */ |
dkato | 0:5a74eeaefb5d | 36 | |
dkato | 0:5a74eeaefb5d | 37 | /* Definition of the base address for the MMU translation table */ |
dkato | 0:5a74eeaefb5d | 38 | #if defined(__CC_ARM) || defined(__GNUC__) |
dkato | 0:5a74eeaefb5d | 39 | extern uint32_t Image$$TTB$$ZI$$Base; |
dkato | 0:5a74eeaefb5d | 40 | #define TTB ((uint32_t)&Image$$TTB$$ZI$$Base) /* using linker symbol */ |
dkato | 0:5a74eeaefb5d | 41 | #elif defined(__ICCARM__) |
dkato | 0:5a74eeaefb5d | 42 | #pragma section="TTB" |
dkato | 0:5a74eeaefb5d | 43 | #define TTB ((uint32_t)__section_begin("TTB")) |
dkato | 0:5a74eeaefb5d | 44 | #endif |
dkato | 0:5a74eeaefb5d | 45 | |
dkato | 0:5a74eeaefb5d | 46 | /** public **/ |
dkato | 0:5a74eeaefb5d | 47 | |
dkato | 0:5a74eeaefb5d | 48 | FlashAccess::FlashAccess() : SPIBSC(&SPIBSC0) { |
dkato | 0:5a74eeaefb5d | 49 | } |
dkato | 0:5a74eeaefb5d | 50 | |
dkato | 0:5a74eeaefb5d | 51 | bool FlashAccess::SectorErase(uint32_t addr) { |
dkato | 0:5a74eeaefb5d | 52 | bool ret; |
dkato | 0:5a74eeaefb5d | 53 | #if defined (__ICCARM__) |
dkato | 0:5a74eeaefb5d | 54 | int was_masked = __disable_irq_iar(); |
dkato | 0:5a74eeaefb5d | 55 | #else |
dkato | 0:5a74eeaefb5d | 56 | int was_masked = __disable_irq(); |
dkato | 0:5a74eeaefb5d | 57 | #endif |
dkato | 0:5a74eeaefb5d | 58 | spi_mode(); |
dkato | 0:5a74eeaefb5d | 59 | ret = _SectorErase(addr); |
dkato | 0:5a74eeaefb5d | 60 | ex_mode(); |
dkato | 0:5a74eeaefb5d | 61 | if (0 == was_masked) { |
dkato | 0:5a74eeaefb5d | 62 | __enable_irq(); |
dkato | 0:5a74eeaefb5d | 63 | } |
dkato | 0:5a74eeaefb5d | 64 | return ret; |
dkato | 0:5a74eeaefb5d | 65 | } |
dkato | 0:5a74eeaefb5d | 66 | |
dkato | 0:5a74eeaefb5d | 67 | bool FlashAccess::PageProgram(uint32_t addr, uint8_t * buf, int32_t size) { |
dkato | 0:5a74eeaefb5d | 68 | bool ret; |
dkato | 0:5a74eeaefb5d | 69 | #if defined (__ICCARM__) |
dkato | 0:5a74eeaefb5d | 70 | int was_masked = __disable_irq_iar(); |
dkato | 0:5a74eeaefb5d | 71 | #else |
dkato | 0:5a74eeaefb5d | 72 | int was_masked = __disable_irq(); |
dkato | 0:5a74eeaefb5d | 73 | #endif |
dkato | 0:5a74eeaefb5d | 74 | spi_mode(); |
dkato | 0:5a74eeaefb5d | 75 | ret = _PageProgram(addr, buf, size); |
dkato | 0:5a74eeaefb5d | 76 | ex_mode(); |
dkato | 0:5a74eeaefb5d | 77 | if (0 == was_masked) { |
dkato | 0:5a74eeaefb5d | 78 | __enable_irq(); |
dkato | 0:5a74eeaefb5d | 79 | } |
dkato | 0:5a74eeaefb5d | 80 | return ret; |
dkato | 0:5a74eeaefb5d | 81 | } |
dkato | 0:5a74eeaefb5d | 82 | |
dkato | 0:5a74eeaefb5d | 83 | bool FlashAccess::Read(uint32_t addr, uint8_t * buf, int32_t size) { |
dkato | 0:5a74eeaefb5d | 84 | bool ret; |
dkato | 0:5a74eeaefb5d | 85 | #if defined (__ICCARM__) |
dkato | 0:5a74eeaefb5d | 86 | int was_masked = __disable_irq_iar(); |
dkato | 0:5a74eeaefb5d | 87 | #else |
dkato | 0:5a74eeaefb5d | 88 | int was_masked = __disable_irq(); |
dkato | 0:5a74eeaefb5d | 89 | #endif |
dkato | 0:5a74eeaefb5d | 90 | spi_mode(); |
dkato | 0:5a74eeaefb5d | 91 | ret = _Read(addr, buf, size); |
dkato | 0:5a74eeaefb5d | 92 | ex_mode(); |
dkato | 0:5a74eeaefb5d | 93 | if (0 == was_masked) { |
dkato | 0:5a74eeaefb5d | 94 | __enable_irq(); |
dkato | 0:5a74eeaefb5d | 95 | } |
dkato | 0:5a74eeaefb5d | 96 | return ret; |
dkato | 0:5a74eeaefb5d | 97 | } |
dkato | 0:5a74eeaefb5d | 98 | |
dkato | 0:5a74eeaefb5d | 99 | /** protected **/ |
dkato | 0:5a74eeaefb5d | 100 | |
dkato | 0:5a74eeaefb5d | 101 | bool FlashAccess::_SectorErase(uint32_t addr) { |
dkato | 0:5a74eeaefb5d | 102 | bool ret; |
dkato | 0:5a74eeaefb5d | 103 | |
dkato | 0:5a74eeaefb5d | 104 | /* ---- Write enable ---- */ |
dkato | 0:5a74eeaefb5d | 105 | ret = _WriteEnable(); /* WREN Command */ |
dkato | 0:5a74eeaefb5d | 106 | if (ret == false) { |
dkato | 0:5a74eeaefb5d | 107 | return ret; |
dkato | 0:5a74eeaefb5d | 108 | } |
dkato | 0:5a74eeaefb5d | 109 | |
dkato | 0:5a74eeaefb5d | 110 | /* ---- spimd_reg init ---- */ |
dkato | 0:5a74eeaefb5d | 111 | clear_spimd_reg(&spimd_reg); |
dkato | 0:5a74eeaefb5d | 112 | |
dkato | 0:5a74eeaefb5d | 113 | /* ---- command ---- */ |
dkato | 0:5a74eeaefb5d | 114 | spimd_reg.cde = SPIBSC_OUTPUT_ENABLE; |
dkato | 0:5a74eeaefb5d | 115 | spimd_reg.cdb = SPIBSC_1BIT; |
dkato | 0:5a74eeaefb5d | 116 | spimd_reg.cmd = SFLASHCMD_SECTOR_ERASE; |
dkato | 0:5a74eeaefb5d | 117 | |
dkato | 0:5a74eeaefb5d | 118 | /* ---- address ---- */ |
dkato | 0:5a74eeaefb5d | 119 | spimd_reg.ade = SPIBSC_OUTPUT_ADDR_24; |
dkato | 0:5a74eeaefb5d | 120 | spimd_reg.addre = SPIBSC_SDR_TRANS; /* SDR */ |
dkato | 0:5a74eeaefb5d | 121 | spimd_reg.adb = SPIBSC_1BIT; |
dkato | 0:5a74eeaefb5d | 122 | spimd_reg.addr = addr; |
dkato | 0:5a74eeaefb5d | 123 | |
dkato | 0:5a74eeaefb5d | 124 | ret = spibsc_transfer(&spimd_reg); |
dkato | 0:5a74eeaefb5d | 125 | if (ret == false) { |
dkato | 0:5a74eeaefb5d | 126 | return ret; |
dkato | 0:5a74eeaefb5d | 127 | } |
dkato | 0:5a74eeaefb5d | 128 | |
dkato | 0:5a74eeaefb5d | 129 | ret = _busy_wait(); |
dkato | 0:5a74eeaefb5d | 130 | |
dkato | 0:5a74eeaefb5d | 131 | return ret; |
dkato | 0:5a74eeaefb5d | 132 | } |
dkato | 0:5a74eeaefb5d | 133 | |
dkato | 0:5a74eeaefb5d | 134 | bool FlashAccess::_PageProgram(uint32_t addr, uint8_t * buf, int32_t size) { |
dkato | 0:5a74eeaefb5d | 135 | bool ret; |
dkato | 0:5a74eeaefb5d | 136 | |
dkato | 0:5a74eeaefb5d | 137 | /* ---- Write enable ---- */ |
dkato | 0:5a74eeaefb5d | 138 | ret = _WriteEnable(); /* WREN Command */ |
dkato | 0:5a74eeaefb5d | 139 | if (ret == false) { |
dkato | 0:5a74eeaefb5d | 140 | return ret; |
dkato | 0:5a74eeaefb5d | 141 | } |
dkato | 0:5a74eeaefb5d | 142 | |
dkato | 0:5a74eeaefb5d | 143 | /* ----------- 1. Command, Address ---------------*/ |
dkato | 0:5a74eeaefb5d | 144 | /* ---- spimd_reg init ---- */ |
dkato | 0:5a74eeaefb5d | 145 | clear_spimd_reg(&spimd_reg); |
dkato | 0:5a74eeaefb5d | 146 | |
dkato | 0:5a74eeaefb5d | 147 | /* ---- command ---- */ |
dkato | 0:5a74eeaefb5d | 148 | spimd_reg.cde = SPIBSC_OUTPUT_ENABLE; |
dkato | 0:5a74eeaefb5d | 149 | spimd_reg.cdb = SPIBSC_1BIT; |
dkato | 0:5a74eeaefb5d | 150 | spimd_reg.cmd = SFLASHCMD_PAGE_PROGRAM; |
dkato | 0:5a74eeaefb5d | 151 | |
dkato | 0:5a74eeaefb5d | 152 | /* ---- address ---- */ |
dkato | 0:5a74eeaefb5d | 153 | spimd_reg.ade = SPIBSC_OUTPUT_ADDR_24; |
dkato | 0:5a74eeaefb5d | 154 | spimd_reg.addre = SPIBSC_SDR_TRANS; /* SDR */ |
dkato | 0:5a74eeaefb5d | 155 | spimd_reg.adb = SPIBSC_1BIT; |
dkato | 0:5a74eeaefb5d | 156 | spimd_reg.addr = addr; |
dkato | 0:5a74eeaefb5d | 157 | |
dkato | 0:5a74eeaefb5d | 158 | /* ---- Others ---- */ |
dkato | 0:5a74eeaefb5d | 159 | spimd_reg.sslkp = SPIBSC_SPISSL_KEEP; /* SPBSSL level */ |
dkato | 0:5a74eeaefb5d | 160 | |
dkato | 0:5a74eeaefb5d | 161 | ret = spibsc_transfer(&spimd_reg); /* Command,Address */ |
dkato | 0:5a74eeaefb5d | 162 | if (ret == false) { |
dkato | 0:5a74eeaefb5d | 163 | return ret; |
dkato | 0:5a74eeaefb5d | 164 | } |
dkato | 0:5a74eeaefb5d | 165 | |
dkato | 0:5a74eeaefb5d | 166 | /* ----------- 2. Data ---------------*/ |
dkato | 0:5a74eeaefb5d | 167 | ret = data_send(SPIBSC_1BIT, SPIBSC_SPISSL_NEGATE, buf, size); |
dkato | 0:5a74eeaefb5d | 168 | if (ret == false) { |
dkato | 0:5a74eeaefb5d | 169 | return ret; |
dkato | 0:5a74eeaefb5d | 170 | } |
dkato | 0:5a74eeaefb5d | 171 | |
dkato | 0:5a74eeaefb5d | 172 | ret = _busy_wait(); |
dkato | 0:5a74eeaefb5d | 173 | |
dkato | 0:5a74eeaefb5d | 174 | return ret; |
dkato | 0:5a74eeaefb5d | 175 | } |
dkato | 0:5a74eeaefb5d | 176 | |
dkato | 0:5a74eeaefb5d | 177 | bool FlashAccess::_Read(uint32_t addr, uint8_t * buf, int32_t size) { |
dkato | 0:5a74eeaefb5d | 178 | bool ret; |
dkato | 0:5a74eeaefb5d | 179 | |
dkato | 0:5a74eeaefb5d | 180 | /* ----------- 1. Command, Address ---------------*/ |
dkato | 0:5a74eeaefb5d | 181 | /* ---- spimd_reg init ---- */ |
dkato | 0:5a74eeaefb5d | 182 | clear_spimd_reg(&spimd_reg); |
dkato | 0:5a74eeaefb5d | 183 | |
dkato | 0:5a74eeaefb5d | 184 | /* ---- command ---- */ |
dkato | 0:5a74eeaefb5d | 185 | spimd_reg.cde = SPIBSC_OUTPUT_ENABLE; |
dkato | 0:5a74eeaefb5d | 186 | spimd_reg.cdb = SPIBSC_1BIT; |
dkato | 0:5a74eeaefb5d | 187 | spimd_reg.cmd = SFLASHCMD_READ; |
dkato | 0:5a74eeaefb5d | 188 | |
dkato | 0:5a74eeaefb5d | 189 | /* ---- address ---- */ |
dkato | 0:5a74eeaefb5d | 190 | spimd_reg.ade = SPIBSC_OUTPUT_ADDR_24; |
dkato | 0:5a74eeaefb5d | 191 | spimd_reg.addre = SPIBSC_SDR_TRANS; /* SDR */ |
dkato | 0:5a74eeaefb5d | 192 | spimd_reg.adb = SPIBSC_1BIT; |
dkato | 0:5a74eeaefb5d | 193 | spimd_reg.addr = addr; |
dkato | 0:5a74eeaefb5d | 194 | |
dkato | 0:5a74eeaefb5d | 195 | /* ---- Others ---- */ |
dkato | 0:5a74eeaefb5d | 196 | spimd_reg.sslkp = SPIBSC_SPISSL_KEEP; /* SPBSSL level */ |
dkato | 0:5a74eeaefb5d | 197 | |
dkato | 0:5a74eeaefb5d | 198 | ret = spibsc_transfer(&spimd_reg); /* Command,Address */ |
dkato | 0:5a74eeaefb5d | 199 | if (ret == false) { |
dkato | 0:5a74eeaefb5d | 200 | return ret; |
dkato | 0:5a74eeaefb5d | 201 | } |
dkato | 0:5a74eeaefb5d | 202 | |
dkato | 0:5a74eeaefb5d | 203 | /* ----------- 2. Data ---------------*/ |
dkato | 0:5a74eeaefb5d | 204 | ret = data_recv(SPIBSC_1BIT, SPIBSC_SPISSL_NEGATE, buf, size); |
dkato | 0:5a74eeaefb5d | 205 | |
dkato | 0:5a74eeaefb5d | 206 | return ret; |
dkato | 0:5a74eeaefb5d | 207 | } |
dkato | 0:5a74eeaefb5d | 208 | |
dkato | 0:5a74eeaefb5d | 209 | bool FlashAccess::_WriteEnable(void) { |
dkato | 0:5a74eeaefb5d | 210 | bool ret; |
dkato | 0:5a74eeaefb5d | 211 | |
dkato | 0:5a74eeaefb5d | 212 | /* ---- spimd_reg init ---- */ |
dkato | 0:5a74eeaefb5d | 213 | clear_spimd_reg(&spimd_reg); |
dkato | 0:5a74eeaefb5d | 214 | |
dkato | 0:5a74eeaefb5d | 215 | /* ---- command ---- */ |
dkato | 0:5a74eeaefb5d | 216 | spimd_reg.cde = SPIBSC_OUTPUT_ENABLE; |
dkato | 0:5a74eeaefb5d | 217 | spimd_reg.cdb = SPIBSC_1BIT; |
dkato | 0:5a74eeaefb5d | 218 | spimd_reg.cmd = SFLASHCMD_WRITE_ENABLE; |
dkato | 0:5a74eeaefb5d | 219 | |
dkato | 0:5a74eeaefb5d | 220 | ret = spibsc_transfer(&spimd_reg); |
dkato | 0:5a74eeaefb5d | 221 | |
dkato | 0:5a74eeaefb5d | 222 | return ret; |
dkato | 0:5a74eeaefb5d | 223 | } |
dkato | 0:5a74eeaefb5d | 224 | |
dkato | 0:5a74eeaefb5d | 225 | bool FlashAccess::_busy_wait(void) { |
dkato | 0:5a74eeaefb5d | 226 | bool ret; |
dkato | 0:5a74eeaefb5d | 227 | uint8_t st_reg; |
dkato | 0:5a74eeaefb5d | 228 | |
dkato | 0:5a74eeaefb5d | 229 | while (1) { |
dkato | 0:5a74eeaefb5d | 230 | ret = _read_register(SFLASHCMD_READ_STATUS_REG, &st_reg); |
dkato | 0:5a74eeaefb5d | 231 | if (ret == false) { |
dkato | 0:5a74eeaefb5d | 232 | break; |
dkato | 0:5a74eeaefb5d | 233 | } |
dkato | 0:5a74eeaefb5d | 234 | if ((st_reg & STREG_BUSY_BIT) == 0) { |
dkato | 0:5a74eeaefb5d | 235 | break; |
dkato | 0:5a74eeaefb5d | 236 | } |
dkato | 0:5a74eeaefb5d | 237 | } |
dkato | 0:5a74eeaefb5d | 238 | |
dkato | 0:5a74eeaefb5d | 239 | return ret; |
dkato | 0:5a74eeaefb5d | 240 | } |
dkato | 0:5a74eeaefb5d | 241 | |
dkato | 0:5a74eeaefb5d | 242 | bool FlashAccess::_read_register(uint8_t cmd, uint8_t * status) { |
dkato | 0:5a74eeaefb5d | 243 | bool ret; |
dkato | 0:5a74eeaefb5d | 244 | |
dkato | 0:5a74eeaefb5d | 245 | /* ---- spimd_reg init ---- */ |
dkato | 0:5a74eeaefb5d | 246 | clear_spimd_reg(&spimd_reg); |
dkato | 0:5a74eeaefb5d | 247 | |
dkato | 0:5a74eeaefb5d | 248 | /* ---- command ---- */ |
dkato | 0:5a74eeaefb5d | 249 | spimd_reg.cde = SPIBSC_OUTPUT_ENABLE; |
dkato | 0:5a74eeaefb5d | 250 | spimd_reg.cdb = SPIBSC_1BIT; |
dkato | 0:5a74eeaefb5d | 251 | spimd_reg.cmd = cmd; |
dkato | 0:5a74eeaefb5d | 252 | |
dkato | 0:5a74eeaefb5d | 253 | /* ---- Others ---- */ |
dkato | 0:5a74eeaefb5d | 254 | spimd_reg.sslkp = SPIBSC_SPISSL_NEGATE; /* SPBSSL level */ |
dkato | 0:5a74eeaefb5d | 255 | spimd_reg.spire = SPIBSC_SPIDATA_ENABLE; /* read enable/disable */ |
dkato | 0:5a74eeaefb5d | 256 | spimd_reg.spiwe = SPIBSC_SPIDATA_ENABLE; /* write enable/disable */ |
dkato | 0:5a74eeaefb5d | 257 | |
dkato | 0:5a74eeaefb5d | 258 | /* ---- data ---- */ |
dkato | 0:5a74eeaefb5d | 259 | spimd_reg.spide = SPIBSC_OUTPUT_SPID_8; /* Enable(8bit) */ |
dkato | 0:5a74eeaefb5d | 260 | spimd_reg.spidre = SPIBSC_SDR_TRANS; /* SDR */ |
dkato | 0:5a74eeaefb5d | 261 | spimd_reg.spidb = SPIBSC_1BIT; |
dkato | 0:5a74eeaefb5d | 262 | spimd_reg.smwdr[0] = 0x00; /* Output 0 in read status */ |
dkato | 0:5a74eeaefb5d | 263 | spimd_reg.smwdr[1] = 0x00; /* Output 0 in read status */ |
dkato | 0:5a74eeaefb5d | 264 | |
dkato | 0:5a74eeaefb5d | 265 | ret = spibsc_transfer(&spimd_reg); |
dkato | 0:5a74eeaefb5d | 266 | if (ret != false) { |
dkato | 0:5a74eeaefb5d | 267 | *status = (uint8_t)(spimd_reg.smrdr[0]); /* Data[7:0] */ |
dkato | 0:5a74eeaefb5d | 268 | } |
dkato | 0:5a74eeaefb5d | 269 | |
dkato | 0:5a74eeaefb5d | 270 | return ret; |
dkato | 0:5a74eeaefb5d | 271 | } |
dkato | 0:5a74eeaefb5d | 272 | |
dkato | 0:5a74eeaefb5d | 273 | bool FlashAccess::data_send(uint32_t bit_width, uint32_t spbssl_level, uint8_t * buf, int32_t size) { |
dkato | 0:5a74eeaefb5d | 274 | bool ret = true; |
dkato | 0:5a74eeaefb5d | 275 | int32_t unit; |
dkato | 0:5a74eeaefb5d | 276 | uint8_t *buf_b; |
dkato | 0:5a74eeaefb5d | 277 | uint16_t *buf_s; |
dkato | 0:5a74eeaefb5d | 278 | uint32_t *buf_l; |
dkato | 0:5a74eeaefb5d | 279 | |
dkato | 0:5a74eeaefb5d | 280 | /* ---- spimd_reg init ---- */ |
dkato | 0:5a74eeaefb5d | 281 | clear_spimd_reg(&spimd_reg); |
dkato | 0:5a74eeaefb5d | 282 | |
dkato | 0:5a74eeaefb5d | 283 | /* ---- Others ---- */ |
dkato | 0:5a74eeaefb5d | 284 | spimd_reg.sslkp = SPIBSC_SPISSL_KEEP; /* SPBSSL level */ |
dkato | 0:5a74eeaefb5d | 285 | spimd_reg.spiwe = SPIBSC_SPIDATA_ENABLE; /* write enable/disable */ |
dkato | 0:5a74eeaefb5d | 286 | |
dkato | 0:5a74eeaefb5d | 287 | /* ---- data ---- */ |
dkato | 0:5a74eeaefb5d | 288 | spimd_reg.spidb = bit_width; |
dkato | 0:5a74eeaefb5d | 289 | spimd_reg.spidre= SPIBSC_SDR_TRANS; /* SDR */ |
dkato | 0:5a74eeaefb5d | 290 | |
dkato | 0:5a74eeaefb5d | 291 | if (((uint32_t)size & 0x3) == 0) { |
dkato | 0:5a74eeaefb5d | 292 | spimd_reg.spide = SPIBSC_OUTPUT_SPID_32; /* Enable(32bit) */ |
dkato | 0:5a74eeaefb5d | 293 | unit = 4; |
dkato | 0:5a74eeaefb5d | 294 | } else if (((uint32_t)size & 0x1) == 0) { |
dkato | 0:5a74eeaefb5d | 295 | spimd_reg.spide = SPIBSC_OUTPUT_SPID_16; /* Enable(16bit) */ |
dkato | 0:5a74eeaefb5d | 296 | unit = 2; |
dkato | 0:5a74eeaefb5d | 297 | } else { |
dkato | 0:5a74eeaefb5d | 298 | spimd_reg.spide = SPIBSC_OUTPUT_SPID_8; /* Enable(8bit) */ |
dkato | 0:5a74eeaefb5d | 299 | unit = 1; |
dkato | 0:5a74eeaefb5d | 300 | } |
dkato | 0:5a74eeaefb5d | 301 | |
dkato | 0:5a74eeaefb5d | 302 | while (size > 0) { |
dkato | 0:5a74eeaefb5d | 303 | if (unit == 1) { |
dkato | 0:5a74eeaefb5d | 304 | buf_b = (uint8_t *)buf; |
dkato | 0:5a74eeaefb5d | 305 | spimd_reg.smwdr[0] = (uint32_t)(((uint32_t)*buf_b) & 0x000000FF); |
dkato | 0:5a74eeaefb5d | 306 | } else if (unit == 2) { |
dkato | 0:5a74eeaefb5d | 307 | buf_s = (uint16_t *)buf; |
dkato | 0:5a74eeaefb5d | 308 | spimd_reg.smwdr[0] = (uint32_t)(((uint32_t)*buf_s) & 0x0000FFFF); |
dkato | 0:5a74eeaefb5d | 309 | } else if (unit == 4) { |
dkato | 0:5a74eeaefb5d | 310 | buf_l = (uint32_t *)buf; |
dkato | 0:5a74eeaefb5d | 311 | spimd_reg.smwdr[0] = (uint32_t)(((uint32_t)(*buf_l)) & 0xfffffffful); |
dkato | 0:5a74eeaefb5d | 312 | } else { |
dkato | 0:5a74eeaefb5d | 313 | /* Do Nothing */ |
dkato | 0:5a74eeaefb5d | 314 | } |
dkato | 0:5a74eeaefb5d | 315 | |
dkato | 0:5a74eeaefb5d | 316 | buf += unit; |
dkato | 0:5a74eeaefb5d | 317 | size -= unit; |
dkato | 0:5a74eeaefb5d | 318 | |
dkato | 0:5a74eeaefb5d | 319 | if (size <= 0) { |
dkato | 0:5a74eeaefb5d | 320 | spimd_reg.sslkp = spbssl_level; |
dkato | 0:5a74eeaefb5d | 321 | } |
dkato | 0:5a74eeaefb5d | 322 | |
dkato | 0:5a74eeaefb5d | 323 | ret = spibsc_transfer(&spimd_reg); /* Data */ |
dkato | 0:5a74eeaefb5d | 324 | if (ret == false) { |
dkato | 0:5a74eeaefb5d | 325 | return ret; |
dkato | 0:5a74eeaefb5d | 326 | } |
dkato | 0:5a74eeaefb5d | 327 | } |
dkato | 0:5a74eeaefb5d | 328 | |
dkato | 0:5a74eeaefb5d | 329 | return ret; |
dkato | 0:5a74eeaefb5d | 330 | } |
dkato | 0:5a74eeaefb5d | 331 | |
dkato | 0:5a74eeaefb5d | 332 | bool FlashAccess::data_recv(uint32_t bit_width, uint32_t spbssl_level, uint8_t * buf, int32_t size) { |
dkato | 0:5a74eeaefb5d | 333 | bool ret = true; |
dkato | 0:5a74eeaefb5d | 334 | int32_t unit; |
dkato | 0:5a74eeaefb5d | 335 | uint8_t *buf_b; |
dkato | 0:5a74eeaefb5d | 336 | uint16_t *buf_s; |
dkato | 0:5a74eeaefb5d | 337 | uint32_t *buf_l; |
dkato | 0:5a74eeaefb5d | 338 | |
dkato | 0:5a74eeaefb5d | 339 | /* ---- spimd_reg init ---- */ |
dkato | 0:5a74eeaefb5d | 340 | clear_spimd_reg(&spimd_reg); |
dkato | 0:5a74eeaefb5d | 341 | |
dkato | 0:5a74eeaefb5d | 342 | /* ---- Others ---- */ |
dkato | 0:5a74eeaefb5d | 343 | spimd_reg.sslkp = SPIBSC_SPISSL_KEEP; /* SPBSSL level */ |
dkato | 0:5a74eeaefb5d | 344 | spimd_reg.spire = SPIBSC_SPIDATA_ENABLE; /* read enable/disable */ |
dkato | 0:5a74eeaefb5d | 345 | |
dkato | 0:5a74eeaefb5d | 346 | /* ---- data ---- */ |
dkato | 0:5a74eeaefb5d | 347 | spimd_reg.spidb = bit_width; |
dkato | 0:5a74eeaefb5d | 348 | spimd_reg.spidre = SPIBSC_SDR_TRANS; /* SDR */ |
dkato | 0:5a74eeaefb5d | 349 | |
dkato | 0:5a74eeaefb5d | 350 | if (((uint32_t)size & 0x3) == 0) { |
dkato | 0:5a74eeaefb5d | 351 | spimd_reg.spide = SPIBSC_OUTPUT_SPID_32; /* Enable(32bit) */ |
dkato | 0:5a74eeaefb5d | 352 | unit = 4; |
dkato | 0:5a74eeaefb5d | 353 | } else if (((uint32_t)size & 0x1) == 0) { |
dkato | 0:5a74eeaefb5d | 354 | spimd_reg.spide = SPIBSC_OUTPUT_SPID_16; /* Enable(16bit) */ |
dkato | 0:5a74eeaefb5d | 355 | unit = 2; |
dkato | 0:5a74eeaefb5d | 356 | } else { |
dkato | 0:5a74eeaefb5d | 357 | spimd_reg.spide = SPIBSC_OUTPUT_SPID_8; /* Enable(8bit) */ |
dkato | 0:5a74eeaefb5d | 358 | unit = 1; |
dkato | 0:5a74eeaefb5d | 359 | } |
dkato | 0:5a74eeaefb5d | 360 | |
dkato | 0:5a74eeaefb5d | 361 | while (size > 0) { |
dkato | 0:5a74eeaefb5d | 362 | if (unit >= size) { |
dkato | 0:5a74eeaefb5d | 363 | spimd_reg.sslkp = spbssl_level; |
dkato | 0:5a74eeaefb5d | 364 | } |
dkato | 0:5a74eeaefb5d | 365 | |
dkato | 0:5a74eeaefb5d | 366 | ret = spibsc_transfer(&spimd_reg); /* Data */ |
dkato | 0:5a74eeaefb5d | 367 | if (ret == false) { |
dkato | 0:5a74eeaefb5d | 368 | return ret; |
dkato | 0:5a74eeaefb5d | 369 | } |
dkato | 0:5a74eeaefb5d | 370 | |
dkato | 0:5a74eeaefb5d | 371 | if (unit == 1) { |
dkato | 0:5a74eeaefb5d | 372 | buf_b = (uint8_t *)buf; |
dkato | 0:5a74eeaefb5d | 373 | *buf_b = (uint8_t)((spimd_reg.smrdr[0]) & 0x000000fful); |
dkato | 0:5a74eeaefb5d | 374 | } else if (unit == 2) { |
dkato | 0:5a74eeaefb5d | 375 | buf_s = (uint16_t *)buf; |
dkato | 0:5a74eeaefb5d | 376 | *buf_s = (uint16_t)((spimd_reg.smrdr[0]) & 0x0000fffful); |
dkato | 0:5a74eeaefb5d | 377 | } else if (unit == 4) { |
dkato | 0:5a74eeaefb5d | 378 | buf_l = (uint32_t *)buf; |
dkato | 0:5a74eeaefb5d | 379 | *buf_l = (uint32_t)((spimd_reg.smrdr[0]) & 0xfffffffful); |
dkato | 0:5a74eeaefb5d | 380 | } else { |
dkato | 0:5a74eeaefb5d | 381 | /* Do Nothing */ |
dkato | 0:5a74eeaefb5d | 382 | } |
dkato | 0:5a74eeaefb5d | 383 | |
dkato | 0:5a74eeaefb5d | 384 | buf += unit; |
dkato | 0:5a74eeaefb5d | 385 | size -= unit; |
dkato | 0:5a74eeaefb5d | 386 | } |
dkato | 0:5a74eeaefb5d | 387 | |
dkato | 0:5a74eeaefb5d | 388 | return ret; |
dkato | 0:5a74eeaefb5d | 389 | } |
dkato | 0:5a74eeaefb5d | 390 | |
dkato | 0:5a74eeaefb5d | 391 | void FlashAccess::spi_mode(void) { |
dkato | 0:5a74eeaefb5d | 392 | volatile uint32_t dummy_read_32; |
dkato | 0:5a74eeaefb5d | 393 | |
dkato | 0:5a74eeaefb5d | 394 | if (RegRead_32(&SPIBSC->CMNCR, SPIBSC_CMNCR_MD_SHIFT, SPIBSC_CMNCR_MD) != SPIBSC_CMNCR_MD_SPI) { |
dkato | 0:5a74eeaefb5d | 395 | /* ==== Change the MMU translation table SPI Multi-I/O bus space settings |
dkato | 0:5a74eeaefb5d | 396 | for use in SPI operating mode ==== */ |
dkato | 0:5a74eeaefb5d | 397 | change_mmu_ttbl_spibsc(0); |
dkato | 0:5a74eeaefb5d | 398 | |
dkato | 0:5a74eeaefb5d | 399 | /* ==== Cleaning and invalidation of cache ==== */ |
dkato | 0:5a74eeaefb5d | 400 | cache_control(); |
dkato | 0:5a74eeaefb5d | 401 | |
dkato | 0:5a74eeaefb5d | 402 | /* ==== Switch to SPI operating mode ==== */ |
dkato | 0:5a74eeaefb5d | 403 | spibsc_stop(); |
dkato | 0:5a74eeaefb5d | 404 | |
dkato | 0:5a74eeaefb5d | 405 | dummy_read_32 = SPIBSC->CMNCR; /* dummy read */ |
dkato | 0:5a74eeaefb5d | 406 | /* SPI Mode */ |
dkato | 0:5a74eeaefb5d | 407 | RegWwrite_32(&SPIBSC->CMNCR, SPIBSC_CMNCR_MD_SPI, SPIBSC_CMNCR_MD_SHIFT, SPIBSC_CMNCR_MD); |
dkato | 0:5a74eeaefb5d | 408 | dummy_read_32 = SPIBSC->CMNCR; /* dummy read */ |
dkato | 0:5a74eeaefb5d | 409 | |
dkato | 0:5a74eeaefb5d | 410 | } |
dkato | 0:5a74eeaefb5d | 411 | (void)dummy_read_32; |
dkato | 0:5a74eeaefb5d | 412 | } |
dkato | 0:5a74eeaefb5d | 413 | |
dkato | 0:5a74eeaefb5d | 414 | void FlashAccess::ex_mode(void) { |
dkato | 0:5a74eeaefb5d | 415 | volatile uint32_t dummy_read_32; |
dkato | 0:5a74eeaefb5d | 416 | |
dkato | 0:5a74eeaefb5d | 417 | if (RegRead_32(&SPIBSC->CMNCR, SPIBSC_CMNCR_MD_SHIFT, SPIBSC_CMNCR_MD) != SPIBSC_CMNCR_MD_EXTRD) { |
dkato | 0:5a74eeaefb5d | 418 | /* ==== Switch to external address space read mode and clear SPIBSC read cache ==== */ |
dkato | 0:5a74eeaefb5d | 419 | spibsc_stop(); |
dkato | 0:5a74eeaefb5d | 420 | |
dkato | 0:5a74eeaefb5d | 421 | /* Flush SPIBSC's read cache */ |
dkato | 0:5a74eeaefb5d | 422 | RegWwrite_32(&SPIBSC->DRCR, SPIBSC_DRCR_RCF_EXE, SPIBSC_DRCR_RCF_SHIFT, SPIBSC_DRCR_RCF); |
dkato | 0:5a74eeaefb5d | 423 | dummy_read_32 = SPIBSC->DRCR; /* dummy read */ |
dkato | 0:5a74eeaefb5d | 424 | |
dkato | 0:5a74eeaefb5d | 425 | /* External address space read mode */ |
dkato | 0:5a74eeaefb5d | 426 | RegWwrite_32(&SPIBSC->CMNCR, SPIBSC_CMNCR_MD_EXTRD, SPIBSC_CMNCR_MD_SHIFT, SPIBSC_CMNCR_MD); |
dkato | 0:5a74eeaefb5d | 427 | dummy_read_32 = SPIBSC->CMNCR; /* dummy read */ |
dkato | 0:5a74eeaefb5d | 428 | |
dkato | 0:5a74eeaefb5d | 429 | /* ==== Change the MMU translation table SPI Multi-I/O bus space settings |
dkato | 0:5a74eeaefb5d | 430 | for use in external address space read mode ==== */ |
dkato | 0:5a74eeaefb5d | 431 | change_mmu_ttbl_spibsc(1); |
dkato | 0:5a74eeaefb5d | 432 | |
dkato | 0:5a74eeaefb5d | 433 | /* ==== Cleaning and invalidation of cache ==== */ |
dkato | 0:5a74eeaefb5d | 434 | cache_control(); |
dkato | 0:5a74eeaefb5d | 435 | } |
dkato | 0:5a74eeaefb5d | 436 | (void)dummy_read_32; |
dkato | 0:5a74eeaefb5d | 437 | } |
dkato | 0:5a74eeaefb5d | 438 | |
dkato | 0:5a74eeaefb5d | 439 | void FlashAccess::clear_spimd_reg(st_spibsc_spimd_reg_t * regset) { |
dkato | 0:5a74eeaefb5d | 440 | /* ---- command ---- */ |
dkato | 0:5a74eeaefb5d | 441 | regset->cde = SPIBSC_OUTPUT_DISABLE; |
dkato | 0:5a74eeaefb5d | 442 | regset->cdb = SPIBSC_1BIT; |
dkato | 0:5a74eeaefb5d | 443 | regset->cmd = 0x00; |
dkato | 0:5a74eeaefb5d | 444 | |
dkato | 0:5a74eeaefb5d | 445 | /* ---- optional command ---- */ |
dkato | 0:5a74eeaefb5d | 446 | regset->ocde = SPIBSC_OUTPUT_DISABLE; |
dkato | 0:5a74eeaefb5d | 447 | regset->ocdb = SPIBSC_1BIT; |
dkato | 0:5a74eeaefb5d | 448 | regset->ocmd = 0x00; |
dkato | 0:5a74eeaefb5d | 449 | |
dkato | 0:5a74eeaefb5d | 450 | /* ---- address ---- */ |
dkato | 0:5a74eeaefb5d | 451 | regset->ade = SPIBSC_OUTPUT_DISABLE; |
dkato | 0:5a74eeaefb5d | 452 | regset->addre = SPIBSC_SDR_TRANS; /* SDR */ |
dkato | 0:5a74eeaefb5d | 453 | regset->adb = SPIBSC_1BIT; |
dkato | 0:5a74eeaefb5d | 454 | regset->addr = 0x00000000; |
dkato | 0:5a74eeaefb5d | 455 | |
dkato | 0:5a74eeaefb5d | 456 | /* ---- option data ---- */ |
dkato | 0:5a74eeaefb5d | 457 | regset->opde = SPIBSC_OUTPUT_DISABLE; |
dkato | 0:5a74eeaefb5d | 458 | regset->opdre = SPIBSC_SDR_TRANS; /* SDR */ |
dkato | 0:5a74eeaefb5d | 459 | regset->opdb = SPIBSC_1BIT; |
dkato | 0:5a74eeaefb5d | 460 | regset->opd[0] = 0x00; /* OPD3 */ |
dkato | 0:5a74eeaefb5d | 461 | regset->opd[1] = 0x00; /* OPD2 */ |
dkato | 0:5a74eeaefb5d | 462 | regset->opd[2] = 0x00; /* OPD1 */ |
dkato | 0:5a74eeaefb5d | 463 | regset->opd[3] = 0x00; /* OPD0 */ |
dkato | 0:5a74eeaefb5d | 464 | |
dkato | 0:5a74eeaefb5d | 465 | /* ---- dummy cycle ---- */ |
dkato | 0:5a74eeaefb5d | 466 | regset->dme = SPIBSC_DUMMY_CYC_DISABLE; |
dkato | 0:5a74eeaefb5d | 467 | regset->dmdb = SPIBSC_1BIT; |
dkato | 0:5a74eeaefb5d | 468 | regset->dmcyc = SPIBSC_DUMMY_1CYC; |
dkato | 0:5a74eeaefb5d | 469 | |
dkato | 0:5a74eeaefb5d | 470 | /* ---- data ---- */ |
dkato | 0:5a74eeaefb5d | 471 | regset->spide = SPIBSC_OUTPUT_DISABLE; |
dkato | 0:5a74eeaefb5d | 472 | regset->spidre = SPIBSC_SDR_TRANS; /* SDR */ |
dkato | 0:5a74eeaefb5d | 473 | regset->spidb = SPIBSC_1BIT; |
dkato | 0:5a74eeaefb5d | 474 | |
dkato | 0:5a74eeaefb5d | 475 | /* ---- Others ---- */ |
dkato | 0:5a74eeaefb5d | 476 | regset->sslkp = SPIBSC_SPISSL_NEGATE; /* SPBSSL level */ |
dkato | 0:5a74eeaefb5d | 477 | regset->spire = SPIBSC_SPIDATA_DISABLE; /* read enable/disable */ |
dkato | 0:5a74eeaefb5d | 478 | regset->spiwe = SPIBSC_SPIDATA_DISABLE; /* write enable/disable */ |
dkato | 0:5a74eeaefb5d | 479 | } |
dkato | 0:5a74eeaefb5d | 480 | |
dkato | 0:5a74eeaefb5d | 481 | bool FlashAccess::spibsc_transfer(st_spibsc_spimd_reg_t * regset) { |
dkato | 0:5a74eeaefb5d | 482 | if (RegRead_32(&SPIBSC->CMNCR, SPIBSC_CMNCR_MD_SHIFT, SPIBSC_CMNCR_MD) != SPIBSC_CMNCR_MD_SPI) { |
dkato | 0:5a74eeaefb5d | 483 | if (RegRead_32(&SPIBSC->CMNSR, SPIBSC_CMNSR_SSLF_SHIFT, SPIBSC_CMNSR_SSLF) != SPIBSC_SSL_NEGATE) { |
dkato | 0:5a74eeaefb5d | 484 | return false; |
dkato | 0:5a74eeaefb5d | 485 | } |
dkato | 0:5a74eeaefb5d | 486 | /* SPI Mode */ |
dkato | 0:5a74eeaefb5d | 487 | RegWwrite_32(&SPIBSC->CMNCR, SPIBSC_CMNCR_MD_SPI, SPIBSC_CMNCR_MD_SHIFT, SPIBSC_CMNCR_MD); |
dkato | 0:5a74eeaefb5d | 488 | } |
dkato | 0:5a74eeaefb5d | 489 | |
dkato | 0:5a74eeaefb5d | 490 | if (RegRead_32(&SPIBSC->CMNSR, SPIBSC_CMNSR_TEND_SHIFT, SPIBSC_CMNSR_TEND) != SPIBSC_TRANS_END) { |
dkato | 0:5a74eeaefb5d | 491 | return false; |
dkato | 0:5a74eeaefb5d | 492 | } |
dkato | 0:5a74eeaefb5d | 493 | |
dkato | 0:5a74eeaefb5d | 494 | /* ---- Command ---- */ |
dkato | 0:5a74eeaefb5d | 495 | /* Enable/Disable */ |
dkato | 0:5a74eeaefb5d | 496 | RegWwrite_32(&SPIBSC->SMENR, regset->cde, SPIBSC_SMENR_CDE_SHIFT, SPIBSC_SMENR_CDE); |
dkato | 0:5a74eeaefb5d | 497 | if (regset->cde != SPIBSC_OUTPUT_DISABLE) { |
dkato | 0:5a74eeaefb5d | 498 | /* Command */ |
dkato | 0:5a74eeaefb5d | 499 | RegWwrite_32(&SPIBSC->SMCMR, regset->cmd, SPIBSC_SMCMR_CMD_SHIFT, SPIBSC_SMCMR_CMD); |
dkato | 0:5a74eeaefb5d | 500 | /* Single/Dual/Quad */ |
dkato | 0:5a74eeaefb5d | 501 | RegWwrite_32(&SPIBSC->SMENR, regset->cdb, SPIBSC_SMENR_CDB_SHIFT, SPIBSC_SMENR_CDB); |
dkato | 0:5a74eeaefb5d | 502 | } |
dkato | 0:5a74eeaefb5d | 503 | |
dkato | 0:5a74eeaefb5d | 504 | /* ---- Option Command ---- */ |
dkato | 0:5a74eeaefb5d | 505 | /* Enable/Disable */ |
dkato | 0:5a74eeaefb5d | 506 | RegWwrite_32(&SPIBSC->SMENR, regset->ocde, SPIBSC_SMENR_OCDE_SHIFT, SPIBSC_SMENR_OCDE); |
dkato | 0:5a74eeaefb5d | 507 | if (regset->ocde != SPIBSC_OUTPUT_DISABLE) { |
dkato | 0:5a74eeaefb5d | 508 | /* Option Command */ |
dkato | 0:5a74eeaefb5d | 509 | RegWwrite_32(&SPIBSC->SMCMR, regset->ocmd, SPIBSC_SMCMR_OCMD_SHIFT, SPIBSC_SMCMR_OCMD); |
dkato | 0:5a74eeaefb5d | 510 | /* Single/Dual/Quad */ |
dkato | 0:5a74eeaefb5d | 511 | RegWwrite_32(&SPIBSC->SMENR, regset->ocdb, SPIBSC_SMENR_OCDB_SHIFT, SPIBSC_SMENR_OCDB); |
dkato | 0:5a74eeaefb5d | 512 | } |
dkato | 0:5a74eeaefb5d | 513 | |
dkato | 0:5a74eeaefb5d | 514 | /* ---- Address ---- */ |
dkato | 0:5a74eeaefb5d | 515 | /* Enable/Disable */ |
dkato | 0:5a74eeaefb5d | 516 | RegWwrite_32(&SPIBSC->SMENR, regset->ade, SPIBSC_SMENR_ADE_SHIFT, SPIBSC_SMENR_ADE); |
dkato | 0:5a74eeaefb5d | 517 | if (regset->ade != SPIBSC_OUTPUT_DISABLE) { |
dkato | 0:5a74eeaefb5d | 518 | /* Address */ |
dkato | 0:5a74eeaefb5d | 519 | RegWwrite_32(&SPIBSC->SMADR, regset->addr, SPIBSC_SMADR_ADR_SHIFT, SPIBSC_SMADR_ADR); |
dkato | 0:5a74eeaefb5d | 520 | /* Single/Dual/Quad */ |
dkato | 0:5a74eeaefb5d | 521 | RegWwrite_32(&SPIBSC->SMENR, regset->adb, SPIBSC_SMENR_ADB_SHIFT, SPIBSC_SMENR_ADB); |
dkato | 0:5a74eeaefb5d | 522 | } |
dkato | 0:5a74eeaefb5d | 523 | |
dkato | 0:5a74eeaefb5d | 524 | /* ---- Option Data ---- */ |
dkato | 0:5a74eeaefb5d | 525 | /* Enable/Disable */ |
dkato | 0:5a74eeaefb5d | 526 | RegWwrite_32(&SPIBSC->SMENR, regset->opde, SPIBSC_SMENR_OPDE_SHIFT, SPIBSC_SMENR_OPDE); |
dkato | 0:5a74eeaefb5d | 527 | if (regset->opde != SPIBSC_OUTPUT_DISABLE) { |
dkato | 0:5a74eeaefb5d | 528 | /* Option Data */ |
dkato | 0:5a74eeaefb5d | 529 | RegWwrite_32(&SPIBSC->SMOPR, regset->opd[0], SPIBSC_SMOPR_OPD3_SHIFT, SPIBSC_SMOPR_OPD3); |
dkato | 0:5a74eeaefb5d | 530 | RegWwrite_32(&SPIBSC->SMOPR, regset->opd[1], SPIBSC_SMOPR_OPD2_SHIFT, SPIBSC_SMOPR_OPD2); |
dkato | 0:5a74eeaefb5d | 531 | RegWwrite_32(&SPIBSC->SMOPR, regset->opd[2], SPIBSC_SMOPR_OPD1_SHIFT, SPIBSC_SMOPR_OPD1); |
dkato | 0:5a74eeaefb5d | 532 | RegWwrite_32(&SPIBSC->SMOPR, regset->opd[3], SPIBSC_SMOPR_OPD0_SHIFT, SPIBSC_SMOPR_OPD0); |
dkato | 0:5a74eeaefb5d | 533 | /* Single/Dual/Quad */ |
dkato | 0:5a74eeaefb5d | 534 | RegWwrite_32(&SPIBSC->SMENR, regset->opdb, SPIBSC_SMENR_OPDB_SHIFT, SPIBSC_SMENR_OPDB); |
dkato | 0:5a74eeaefb5d | 535 | } |
dkato | 0:5a74eeaefb5d | 536 | |
dkato | 0:5a74eeaefb5d | 537 | /* ---- Dummy ---- */ |
dkato | 0:5a74eeaefb5d | 538 | /* Enable/Disable */ |
dkato | 0:5a74eeaefb5d | 539 | RegWwrite_32(&SPIBSC->SMENR, regset->dme, SPIBSC_SMENR_DME_SHIFT, SPIBSC_SMENR_DME); |
dkato | 0:5a74eeaefb5d | 540 | if (regset->dme != SPIBSC_DUMMY_CYC_DISABLE) { |
dkato | 0:5a74eeaefb5d | 541 | RegWwrite_32(&SPIBSC->SMDMCR, regset->dmdb, SPIBSC_SMDMCR_DMDB_SHIFT, SPIBSC_SMDMCR_DMDB); |
dkato | 0:5a74eeaefb5d | 542 | /* Dummy Cycle */ |
dkato | 0:5a74eeaefb5d | 543 | RegWwrite_32(&SPIBSC->SMDMCR, regset->dmcyc, SPIBSC_SMDMCR_DMCYC_SHIFT, SPIBSC_SMDMCR_DMCYC); |
dkato | 0:5a74eeaefb5d | 544 | } |
dkato | 0:5a74eeaefb5d | 545 | |
dkato | 0:5a74eeaefb5d | 546 | /* ---- Data ---- */ |
dkato | 0:5a74eeaefb5d | 547 | /* Enable/Disable */ |
dkato | 0:5a74eeaefb5d | 548 | RegWwrite_32(&SPIBSC->SMENR, regset->spide, SPIBSC_SMENR_SPIDE_SHIFT, SPIBSC_SMENR_SPIDE); |
dkato | 0:5a74eeaefb5d | 549 | if (regset->spide != SPIBSC_OUTPUT_DISABLE) { |
dkato | 0:5a74eeaefb5d | 550 | if (SPIBSC_OUTPUT_SPID_8 == regset->spide) { |
dkato | 0:5a74eeaefb5d | 551 | if (RegRead_32(&SPIBSC0.CMNCR, SPIBSC_CMNCR_BSZ_SHIFT, SPIBSC_CMNCR_BSZ) == SPIBSC_CMNCR_BSZ_SINGLE) { |
dkato | 0:5a74eeaefb5d | 552 | SPIBSC->SMWDR0.UINT8[0] = (uint8_t)(regset->smwdr[0]); |
dkato | 0:5a74eeaefb5d | 553 | } else { |
dkato | 0:5a74eeaefb5d | 554 | SPIBSC->SMWDR0.UINT16[0] = (uint16_t)(regset->smwdr[0]); |
dkato | 0:5a74eeaefb5d | 555 | } |
dkato | 0:5a74eeaefb5d | 556 | } else if (regset->spide == SPIBSC_OUTPUT_SPID_16) { |
dkato | 0:5a74eeaefb5d | 557 | if (RegRead_32(&SPIBSC0.CMNCR, SPIBSC_CMNCR_BSZ_SHIFT, SPIBSC_CMNCR_BSZ) == SPIBSC_CMNCR_BSZ_SINGLE) { |
dkato | 0:5a74eeaefb5d | 558 | SPIBSC->SMWDR0.UINT16[0] = (uint16_t)(regset->smwdr[0]); |
dkato | 0:5a74eeaefb5d | 559 | } else { |
dkato | 0:5a74eeaefb5d | 560 | SPIBSC->SMWDR0.UINT32 = regset->smwdr[0]; |
dkato | 0:5a74eeaefb5d | 561 | } |
dkato | 0:5a74eeaefb5d | 562 | } else if (regset->spide == SPIBSC_OUTPUT_SPID_32) { |
dkato | 0:5a74eeaefb5d | 563 | if (RegRead_32(&SPIBSC0.CMNCR, SPIBSC_CMNCR_BSZ_SHIFT, SPIBSC_CMNCR_BSZ) == SPIBSC_CMNCR_BSZ_SINGLE) { |
dkato | 0:5a74eeaefb5d | 564 | SPIBSC->SMWDR0.UINT32 = (uint32_t)(regset->smwdr[0]); |
dkato | 0:5a74eeaefb5d | 565 | } else { |
dkato | 0:5a74eeaefb5d | 566 | SPIBSC->SMWDR0.UINT32 = (uint32_t)(regset->smwdr[0]); |
dkato | 0:5a74eeaefb5d | 567 | SPIBSC->SMWDR1.UINT32 = (uint32_t)(regset->smwdr[1]); /* valid in two serial-flash */ |
dkato | 0:5a74eeaefb5d | 568 | } |
dkato | 0:5a74eeaefb5d | 569 | } else { |
dkato | 0:5a74eeaefb5d | 570 | /* none */ |
dkato | 0:5a74eeaefb5d | 571 | } |
dkato | 0:5a74eeaefb5d | 572 | |
dkato | 0:5a74eeaefb5d | 573 | /* Single/Dual/Quad */ |
dkato | 0:5a74eeaefb5d | 574 | RegWwrite_32(&SPIBSC->SMENR, regset->spidb, SPIBSC_SMENR_SPIDB_SHIFT, SPIBSC_SMENR_SPIDB); |
dkato | 0:5a74eeaefb5d | 575 | } |
dkato | 0:5a74eeaefb5d | 576 | |
dkato | 0:5a74eeaefb5d | 577 | RegWwrite_32(&SPIBSC->SMCR, regset->sslkp, SPIBSC_SMCR_SSLKP_SHIFT, SPIBSC_SMCR_SSLKP); |
dkato | 0:5a74eeaefb5d | 578 | |
dkato | 0:5a74eeaefb5d | 579 | if ((regset->spidb != SPIBSC_1BIT) && (regset->spide != SPIBSC_OUTPUT_DISABLE)) { |
dkato | 0:5a74eeaefb5d | 580 | if ((regset->spire == SPIBSC_SPIDATA_ENABLE) && (regset->spiwe == SPIBSC_SPIDATA_ENABLE)) { |
dkato | 0:5a74eeaefb5d | 581 | /* not set in same time */ |
dkato | 0:5a74eeaefb5d | 582 | return false; |
dkato | 0:5a74eeaefb5d | 583 | } |
dkato | 0:5a74eeaefb5d | 584 | } |
dkato | 0:5a74eeaefb5d | 585 | |
dkato | 0:5a74eeaefb5d | 586 | RegWwrite_32(&SPIBSC->SMCR, regset->spire, SPIBSC_SMCR_SPIRE_SHIFT, SPIBSC_SMCR_SPIRE); |
dkato | 0:5a74eeaefb5d | 587 | RegWwrite_32(&SPIBSC->SMCR, regset->spiwe, SPIBSC_SMCR_SPIWE_SHIFT, SPIBSC_SMCR_SPIWE); |
dkato | 0:5a74eeaefb5d | 588 | |
dkato | 0:5a74eeaefb5d | 589 | /* SDR Transmission/DDR Transmission Setting */ |
dkato | 0:5a74eeaefb5d | 590 | RegWwrite_32(&SPIBSC->SMDRENR, regset->addre, SPIBSC_SMDRENR_ADDRE_SHIFT, SPIBSC_SMDRENR_ADDRE); |
dkato | 0:5a74eeaefb5d | 591 | RegWwrite_32(&SPIBSC->SMDRENR, regset->opdre, SPIBSC_SMDRENR_OPDRE_SHIFT, SPIBSC_SMDRENR_OPDRE); |
dkato | 0:5a74eeaefb5d | 592 | RegWwrite_32(&SPIBSC->SMDRENR, regset->spidre, SPIBSC_SMDRENR_SPIDRE_SHIFT, SPIBSC_SMDRENR_SPIDRE); |
dkato | 0:5a74eeaefb5d | 593 | |
dkato | 0:5a74eeaefb5d | 594 | /* execute after setting SPNDL bit */ |
dkato | 0:5a74eeaefb5d | 595 | RegWwrite_32(&SPIBSC->SMCR, SPIBSC_SPI_ENABLE, SPIBSC_SMCR_SPIE_SHIFT, SPIBSC_SMCR_SPIE); |
dkato | 0:5a74eeaefb5d | 596 | |
dkato | 0:5a74eeaefb5d | 597 | /* wait for transfer-start */ |
dkato | 0:5a74eeaefb5d | 598 | while (RegRead_32(&SPIBSC->CMNSR, SPIBSC_CMNSR_TEND_SHIFT, SPIBSC_CMNSR_TEND) != SPIBSC_TRANS_END) { |
dkato | 0:5a74eeaefb5d | 599 | /* wait for transfer-end */ |
dkato | 0:5a74eeaefb5d | 600 | } |
dkato | 0:5a74eeaefb5d | 601 | |
dkato | 0:5a74eeaefb5d | 602 | if (SPIBSC_OUTPUT_SPID_8 == regset->spide) { |
dkato | 0:5a74eeaefb5d | 603 | if (RegRead_32(&SPIBSC0.CMNCR, SPIBSC_CMNCR_BSZ_SHIFT, SPIBSC_CMNCR_BSZ) == SPIBSC_CMNCR_BSZ_SINGLE) { |
dkato | 0:5a74eeaefb5d | 604 | regset->smrdr[0] = SPIBSC->SMRDR0.UINT8[0]; |
dkato | 0:5a74eeaefb5d | 605 | } else { |
dkato | 0:5a74eeaefb5d | 606 | regset->smrdr[0] = SPIBSC->SMRDR0.UINT16[0]; /* valid in two serial-flash */ |
dkato | 0:5a74eeaefb5d | 607 | } |
dkato | 0:5a74eeaefb5d | 608 | } else if (regset->spide == SPIBSC_OUTPUT_SPID_16) { |
dkato | 0:5a74eeaefb5d | 609 | if (RegRead_32(&SPIBSC0.CMNCR, SPIBSC_CMNCR_BSZ_SHIFT, SPIBSC_CMNCR_BSZ) == SPIBSC_CMNCR_BSZ_SINGLE) { |
dkato | 0:5a74eeaefb5d | 610 | regset->smrdr[0] = SPIBSC->SMRDR0.UINT16[0]; |
dkato | 0:5a74eeaefb5d | 611 | } else { |
dkato | 0:5a74eeaefb5d | 612 | regset->smrdr[0] = SPIBSC->SMRDR0.UINT32; /* valid in two serial-flash */ |
dkato | 0:5a74eeaefb5d | 613 | } |
dkato | 0:5a74eeaefb5d | 614 | } else if (regset->spide == SPIBSC_OUTPUT_SPID_32) { |
dkato | 0:5a74eeaefb5d | 615 | if (RegRead_32(&SPIBSC0.CMNCR, SPIBSC_CMNCR_BSZ_SHIFT, SPIBSC_CMNCR_BSZ) == SPIBSC_CMNCR_BSZ_SINGLE) { |
dkato | 0:5a74eeaefb5d | 616 | regset->smrdr[0] = SPIBSC->SMRDR0.UINT32; |
dkato | 0:5a74eeaefb5d | 617 | } else { |
dkato | 0:5a74eeaefb5d | 618 | regset->smrdr[0] = SPIBSC->SMRDR0.UINT32; /* valid in two serial-flash */ |
dkato | 0:5a74eeaefb5d | 619 | regset->smrdr[1] = SPIBSC->SMRDR1.UINT32; |
dkato | 0:5a74eeaefb5d | 620 | } |
dkato | 0:5a74eeaefb5d | 621 | } else { |
dkato | 0:5a74eeaefb5d | 622 | /* none */ |
dkato | 0:5a74eeaefb5d | 623 | } |
dkato | 0:5a74eeaefb5d | 624 | |
dkato | 0:5a74eeaefb5d | 625 | return true; |
dkato | 0:5a74eeaefb5d | 626 | } |
dkato | 0:5a74eeaefb5d | 627 | |
dkato | 0:5a74eeaefb5d | 628 | uint32_t FlashAccess::RegRead_32(volatile uint32_t * ioreg, uint32_t shift, uint32_t mask) { |
dkato | 0:5a74eeaefb5d | 629 | uint32_t reg_value; |
dkato | 0:5a74eeaefb5d | 630 | |
dkato | 0:5a74eeaefb5d | 631 | reg_value = *ioreg; /* Read from register */ |
dkato | 0:5a74eeaefb5d | 632 | reg_value = (reg_value & mask) >> shift; /* Clear other bit and Bit shift */ |
dkato | 0:5a74eeaefb5d | 633 | |
dkato | 0:5a74eeaefb5d | 634 | return reg_value; |
dkato | 0:5a74eeaefb5d | 635 | } |
dkato | 0:5a74eeaefb5d | 636 | |
dkato | 0:5a74eeaefb5d | 637 | void FlashAccess::RegWwrite_32(volatile uint32_t * ioreg, uint32_t write_value, uint32_t shift, uint32_t mask) { |
dkato | 0:5a74eeaefb5d | 638 | uint32_t reg_value; |
dkato | 0:5a74eeaefb5d | 639 | |
dkato | 0:5a74eeaefb5d | 640 | reg_value = *ioreg; /* Read from register */ |
dkato | 0:5a74eeaefb5d | 641 | reg_value = (reg_value & (~mask)) | (write_value << shift); /* Modify value */ |
dkato | 0:5a74eeaefb5d | 642 | *ioreg = reg_value; /* Write to register */ |
dkato | 0:5a74eeaefb5d | 643 | } |
dkato | 0:5a74eeaefb5d | 644 | |
dkato | 0:5a74eeaefb5d | 645 | /** private **/ |
dkato | 0:5a74eeaefb5d | 646 | |
dkato | 0:5a74eeaefb5d | 647 | void FlashAccess::change_mmu_ttbl_spibsc(uint32_t type) { |
dkato | 0:5a74eeaefb5d | 648 | uint32_t index; /* Loop variable: table index */ |
dkato | 0:5a74eeaefb5d | 649 | mmu_ttbl_desc_section_t desc; /* Loop variable: descriptor */ |
dkato | 0:5a74eeaefb5d | 650 | mmu_ttbl_desc_section_t * table = (mmu_ttbl_desc_section_t *)TTB; |
dkato | 0:5a74eeaefb5d | 651 | |
dkato | 0:5a74eeaefb5d | 652 | /* ==== Modify SPI Multi-I/O bus space settings in the MMU translation table ==== */ |
dkato | 0:5a74eeaefb5d | 653 | for (index = (SPIBSC_ADDR_START >> 20); index <= (SPIBSC_ADDR_END >> 20); index++) { |
dkato | 0:5a74eeaefb5d | 654 | /* Modify memory attribute descriptor */ |
dkato | 0:5a74eeaefb5d | 655 | if (type == 0) { /* Spi */ |
dkato | 0:5a74eeaefb5d | 656 | desc = table[index]; |
dkato | 0:5a74eeaefb5d | 657 | desc_tbl[index - (SPIBSC_ADDR_START >> 20)] = desc; |
dkato | 0:5a74eeaefb5d | 658 | desc.AP1_0 = 0x0u; /* AP[2:0] = b'000 (No access) */ |
dkato | 0:5a74eeaefb5d | 659 | desc.AP2 = 0x0u; |
dkato | 0:5a74eeaefb5d | 660 | desc.XN = 0x1u; /* XN = 1 (Execute never) */ |
dkato | 0:5a74eeaefb5d | 661 | } else { /* Xip */ |
dkato | 0:5a74eeaefb5d | 662 | desc = desc_tbl[index - (SPIBSC_ADDR_START >> 20)]; |
dkato | 0:5a74eeaefb5d | 663 | } |
dkato | 0:5a74eeaefb5d | 664 | /* Write descriptor back to translation table */ |
dkato | 0:5a74eeaefb5d | 665 | table[index] = desc; |
dkato | 0:5a74eeaefb5d | 666 | } |
dkato | 0:5a74eeaefb5d | 667 | } |
dkato | 0:5a74eeaefb5d | 668 | |
dkato | 0:5a74eeaefb5d | 669 | void FlashAccess::spibsc_stop(void) { |
dkato | 0:5a74eeaefb5d | 670 | if (((SPIBSC->DRCR & SPIBSC_DRCR_RBE) != 0) && |
dkato | 0:5a74eeaefb5d | 671 | ((SPIBSC->DRCR & SPIBSC_DRCR_SSLE) != 0)) { |
dkato | 0:5a74eeaefb5d | 672 | RegWwrite_32(&SPIBSC->DRCR, 1, SPIBSC_DRCR_SSLN_SHIFT, SPIBSC_DRCR_SSLN); |
dkato | 0:5a74eeaefb5d | 673 | } |
dkato | 0:5a74eeaefb5d | 674 | |
dkato | 0:5a74eeaefb5d | 675 | while (RegRead_32(&SPIBSC->CMNSR, SPIBSC_CMNSR_SSLF_SHIFT, SPIBSC_CMNSR_SSLF) != SPIBSC_SSL_NEGATE) { |
dkato | 0:5a74eeaefb5d | 676 | ; |
dkato | 0:5a74eeaefb5d | 677 | } |
dkato | 0:5a74eeaefb5d | 678 | |
dkato | 0:5a74eeaefb5d | 679 | while (RegRead_32(&SPIBSC->CMNSR, SPIBSC_CMNSR_TEND_SHIFT, SPIBSC_CMNSR_TEND) != SPIBSC_TRANS_END) { |
dkato | 0:5a74eeaefb5d | 680 | ; |
dkato | 0:5a74eeaefb5d | 681 | } |
dkato | 0:5a74eeaefb5d | 682 | } |
dkato | 0:5a74eeaefb5d | 683 | |
dkato | 0:5a74eeaefb5d | 684 | #ifndef __STATIC_FORCEINLINE |
dkato | 0:5a74eeaefb5d | 685 | #if defined ( __CC_ARM ) |
dkato | 0:5a74eeaefb5d | 686 | #define __STATIC_FORCEINLINE static __forceinline |
dkato | 0:5a74eeaefb5d | 687 | #elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) |
dkato | 0:5a74eeaefb5d | 688 | #define __STATIC_FORCEINLINE __attribute__((always_inline)) static __inline |
dkato | 0:5a74eeaefb5d | 689 | #elif defined ( __GNUC__ ) |
dkato | 0:5a74eeaefb5d | 690 | #define __STATIC_FORCEINLINE __attribute__((always_inline)) static __inline |
dkato | 0:5a74eeaefb5d | 691 | #elif defined ( __ICCARM__ ) |
dkato | 0:5a74eeaefb5d | 692 | #define __STATIC_FORCEINLINE _Pragma("inline=forced") static inline |
dkato | 0:5a74eeaefb5d | 693 | #endif |
dkato | 0:5a74eeaefb5d | 694 | #endif |
dkato | 0:5a74eeaefb5d | 695 | |
dkato | 0:5a74eeaefb5d | 696 | #if defined ( __CC_ARM ) |
dkato | 0:5a74eeaefb5d | 697 | __STATIC_FORCEINLINE __ASM void L1C_CleanInvalidateCache_sforce(uint32_t op) { |
dkato | 0:5a74eeaefb5d | 698 | ARM |
dkato | 0:5a74eeaefb5d | 699 | |
dkato | 0:5a74eeaefb5d | 700 | PUSH {R4-R11} |
dkato | 0:5a74eeaefb5d | 701 | |
dkato | 0:5a74eeaefb5d | 702 | MRC p15, 1, R6, c0, c0, 1 // Read CLIDR |
dkato | 0:5a74eeaefb5d | 703 | ANDS R3, R6, #0x07000000 // Extract coherency level |
dkato | 0:5a74eeaefb5d | 704 | MOV R3, R3, LSR #23 // Total cache levels << 1 |
dkato | 0:5a74eeaefb5d | 705 | BEQ Finished // If 0, no need to clean |
dkato | 0:5a74eeaefb5d | 706 | |
dkato | 0:5a74eeaefb5d | 707 | MOV R10, #0 // R10 holds current cache level << 1 |
dkato | 0:5a74eeaefb5d | 708 | Loop1 ADD R2, R10, R10, LSR #1 // R2 holds cache "Set" position |
dkato | 0:5a74eeaefb5d | 709 | MOV R1, R6, LSR R2 // Bottom 3 bits are the Cache-type for this level |
dkato | 0:5a74eeaefb5d | 710 | AND R1, R1, #7 // Isolate those lower 3 bits |
dkato | 0:5a74eeaefb5d | 711 | CMP R1, #2 |
dkato | 0:5a74eeaefb5d | 712 | BLT Skip // No cache or only instruction cache at this level |
dkato | 0:5a74eeaefb5d | 713 | |
dkato | 0:5a74eeaefb5d | 714 | MCR p15, 2, R10, c0, c0, 0 // Write the Cache Size selection register |
dkato | 0:5a74eeaefb5d | 715 | ISB // ISB to sync the change to the CacheSizeID reg |
dkato | 0:5a74eeaefb5d | 716 | MRC p15, 1, R1, c0, c0, 0 // Reads current Cache Size ID register |
dkato | 0:5a74eeaefb5d | 717 | AND R2, R1, #7 // Extract the line length field |
dkato | 0:5a74eeaefb5d | 718 | ADD R2, R2, #4 // Add 4 for the line length offset (log2 16 bytes) |
dkato | 0:5a74eeaefb5d | 719 | LDR R4, =0x3FF |
dkato | 0:5a74eeaefb5d | 720 | ANDS R4, R4, R1, LSR #3 // R4 is the max number on the way size (right aligned) |
dkato | 0:5a74eeaefb5d | 721 | CLZ R5, R4 // R5 is the bit position of the way size increment |
dkato | 0:5a74eeaefb5d | 722 | LDR R7, =0x7FFF |
dkato | 0:5a74eeaefb5d | 723 | ANDS R7, R7, R1, LSR #13 // R7 is the max number of the index size (right aligned) |
dkato | 0:5a74eeaefb5d | 724 | |
dkato | 0:5a74eeaefb5d | 725 | Loop2 MOV R9, R4 // R9 working copy of the max way size (right aligned) |
dkato | 0:5a74eeaefb5d | 726 | |
dkato | 0:5a74eeaefb5d | 727 | Loop3 ORR R11, R10, R9, LSL R5 // Factor in the Way number and cache number into R11 |
dkato | 0:5a74eeaefb5d | 728 | ORR R11, R11, R7, LSL R2 // Factor in the Set number |
dkato | 0:5a74eeaefb5d | 729 | CMP R0, #0 |
dkato | 0:5a74eeaefb5d | 730 | BNE Dccsw |
dkato | 0:5a74eeaefb5d | 731 | MCR p15, 0, R11, c7, c6, 2 // DCISW. Invalidate by Set/Way |
dkato | 0:5a74eeaefb5d | 732 | B cont |
dkato | 0:5a74eeaefb5d | 733 | Dccsw CMP R0, #1 |
dkato | 0:5a74eeaefb5d | 734 | BNE Dccisw |
dkato | 0:5a74eeaefb5d | 735 | MCR p15, 0, R11, c7, c10, 2 // DCCSW. Clean by Set/Way |
dkato | 0:5a74eeaefb5d | 736 | B cont |
dkato | 0:5a74eeaefb5d | 737 | Dccisw MCR p15, 0, R11, c7, c14, 2 // DCCISW. Clean and Invalidate by Set/Way |
dkato | 0:5a74eeaefb5d | 738 | cont SUBS R9, R9, #1 // Decrement the Way number |
dkato | 0:5a74eeaefb5d | 739 | BGE Loop3 |
dkato | 0:5a74eeaefb5d | 740 | SUBS R7, R7, #1 // Decrement the Set number |
dkato | 0:5a74eeaefb5d | 741 | BGE Loop2 |
dkato | 0:5a74eeaefb5d | 742 | Skip ADD R10, R10, #2 // Increment the cache number |
dkato | 0:5a74eeaefb5d | 743 | CMP R3, R10 |
dkato | 0:5a74eeaefb5d | 744 | BGT Loop1 |
dkato | 0:5a74eeaefb5d | 745 | |
dkato | 0:5a74eeaefb5d | 746 | Finished |
dkato | 0:5a74eeaefb5d | 747 | DSB |
dkato | 0:5a74eeaefb5d | 748 | POP {R4-R11} |
dkato | 0:5a74eeaefb5d | 749 | BX lr |
dkato | 0:5a74eeaefb5d | 750 | } |
dkato | 0:5a74eeaefb5d | 751 | |
dkato | 0:5a74eeaefb5d | 752 | #elif (defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)) || defined ( __GNUC__ ) |
dkato | 0:5a74eeaefb5d | 753 | __STATIC_FORCEINLINE void L1C_CleanInvalidateCache_sforce(uint32_t op) { |
dkato | 0:5a74eeaefb5d | 754 | __ASM volatile( |
dkato | 0:5a74eeaefb5d | 755 | " PUSH {R4-R11} \n" |
dkato | 0:5a74eeaefb5d | 756 | |
dkato | 0:5a74eeaefb5d | 757 | " MRC p15, 1, R6, c0, c0, 1 \n" // Read CLIDR |
dkato | 0:5a74eeaefb5d | 758 | " ANDS R3, R6, #0x07000000 \n" // Extract coherency level |
dkato | 0:5a74eeaefb5d | 759 | " MOV R3, R3, LSR #23 \n" // Total cache levels << 1 |
dkato | 0:5a74eeaefb5d | 760 | " BEQ Finished \n" // If 0, no need to clean |
dkato | 0:5a74eeaefb5d | 761 | |
dkato | 0:5a74eeaefb5d | 762 | " MOV R10, #0 \n" // R10 holds current cache level << 1 |
dkato | 0:5a74eeaefb5d | 763 | "Loop1: ADD R2, R10, R10, LSR #1 \n" // R2 holds cache "Set" position |
dkato | 0:5a74eeaefb5d | 764 | " MOV R1, R6, LSR R2 \n" // Bottom 3 bits are the Cache-type for this level |
dkato | 0:5a74eeaefb5d | 765 | " AND R1, R1, #7 \n" // Isolate those lower 3 bits |
dkato | 0:5a74eeaefb5d | 766 | " CMP R1, #2 \n" |
dkato | 0:5a74eeaefb5d | 767 | " BLT Skip \n" // No cache or only instruction cache at this level |
dkato | 0:5a74eeaefb5d | 768 | |
dkato | 0:5a74eeaefb5d | 769 | " MCR p15, 2, R10, c0, c0, 0 \n" // Write the Cache Size selection register |
dkato | 0:5a74eeaefb5d | 770 | " ISB \n" // ISB to sync the change to the CacheSizeID reg |
dkato | 0:5a74eeaefb5d | 771 | " MRC p15, 1, R1, c0, c0, 0 \n" // Reads current Cache Size ID register |
dkato | 0:5a74eeaefb5d | 772 | " AND R2, R1, #7 \n" // Extract the line length field |
dkato | 0:5a74eeaefb5d | 773 | " ADD R2, R2, #4 \n" // Add 4 for the line length offset (log2 16 bytes) |
dkato | 0:5a74eeaefb5d | 774 | " LDR R4, =0x3FF \n" |
dkato | 0:5a74eeaefb5d | 775 | " ANDS R4, R4, R1, LSR #3 \n" // R4 is the max number on the way size (right aligned) |
dkato | 0:5a74eeaefb5d | 776 | " CLZ R5, R4 \n" // R5 is the bit position of the way size increment |
dkato | 0:5a74eeaefb5d | 777 | " LDR R7, =0x7FFF \n" |
dkato | 0:5a74eeaefb5d | 778 | " ANDS R7, R7, R1, LSR #13 \n" // R7 is the max number of the index size (right aligned) |
dkato | 0:5a74eeaefb5d | 779 | |
dkato | 0:5a74eeaefb5d | 780 | "Loop2: MOV R9, R4 \n" // R9 working copy of the max way size (right aligned) |
dkato | 0:5a74eeaefb5d | 781 | |
dkato | 0:5a74eeaefb5d | 782 | "Loop3: ORR R11, R10, R9, LSL R5 \n" // Factor in the Way number and cache number into R11 |
dkato | 0:5a74eeaefb5d | 783 | " ORR R11, R11, R7, LSL R2 \n" // Factor in the Set number |
dkato | 0:5a74eeaefb5d | 784 | " CMP R0, #0 \n" |
dkato | 0:5a74eeaefb5d | 785 | " BNE Dccsw \n" |
dkato | 0:5a74eeaefb5d | 786 | " MCR p15, 0, R11, c7, c6, 2 \n" // DCISW. Invalidate by Set/Way |
dkato | 0:5a74eeaefb5d | 787 | " B cont \n" |
dkato | 0:5a74eeaefb5d | 788 | "Dccsw: CMP R0, #1 \n" |
dkato | 0:5a74eeaefb5d | 789 | " BNE Dccisw \n" |
dkato | 0:5a74eeaefb5d | 790 | " MCR p15, 0, R11, c7, c10, 2 \n" // DCCSW. Clean by Set/Way |
dkato | 0:5a74eeaefb5d | 791 | " B cont \n" |
dkato | 0:5a74eeaefb5d | 792 | "Dccisw: MCR p15, 0, R11, c7, c14, 2 \n" // DCCISW. Clean and Invalidate by Set/Way |
dkato | 0:5a74eeaefb5d | 793 | "cont: SUBS R9, R9, #1 \n" // Decrement the Way number |
dkato | 0:5a74eeaefb5d | 794 | " BGE Loop3 \n" |
dkato | 0:5a74eeaefb5d | 795 | " SUBS R7, R7, #1 \n" // Decrement the Set number |
dkato | 0:5a74eeaefb5d | 796 | " BGE Loop2 \n" |
dkato | 0:5a74eeaefb5d | 797 | "Skip: ADD R10, R10, #2 \n" // Increment the cache number |
dkato | 0:5a74eeaefb5d | 798 | " CMP R3, R10 \n" |
dkato | 0:5a74eeaefb5d | 799 | " BGT Loop1 \n" |
dkato | 0:5a74eeaefb5d | 800 | |
dkato | 0:5a74eeaefb5d | 801 | "Finished: \n" |
dkato | 0:5a74eeaefb5d | 802 | " DSB \n" |
dkato | 0:5a74eeaefb5d | 803 | " POP {R4-R11} " |
dkato | 0:5a74eeaefb5d | 804 | ); |
dkato | 0:5a74eeaefb5d | 805 | } |
dkato | 0:5a74eeaefb5d | 806 | |
dkato | 0:5a74eeaefb5d | 807 | #else |
dkato | 0:5a74eeaefb5d | 808 | __STATIC_FORCEINLINE void __L1C_MaintainDCacheSetWay_sforce(uint32_t level, uint32_t maint) { |
dkato | 0:5a74eeaefb5d | 809 | register volatile uint32_t Dummy; |
dkato | 0:5a74eeaefb5d | 810 | register volatile uint32_t ccsidr; |
dkato | 0:5a74eeaefb5d | 811 | uint32_t num_sets; |
dkato | 0:5a74eeaefb5d | 812 | uint32_t num_ways; |
dkato | 0:5a74eeaefb5d | 813 | uint32_t shift_way; |
dkato | 0:5a74eeaefb5d | 814 | uint32_t log2_linesize; |
dkato | 0:5a74eeaefb5d | 815 | uint32_t log2_num_ways; |
dkato | 0:5a74eeaefb5d | 816 | |
dkato | 0:5a74eeaefb5d | 817 | Dummy = level << 1; |
dkato | 0:5a74eeaefb5d | 818 | /* set csselr, select ccsidr register */ |
dkato | 0:5a74eeaefb5d | 819 | __set_CCSIDR(Dummy); |
dkato | 0:5a74eeaefb5d | 820 | /* get current ccsidr register */ |
dkato | 0:5a74eeaefb5d | 821 | ccsidr = __get_CCSIDR(); |
dkato | 0:5a74eeaefb5d | 822 | num_sets = ((ccsidr & 0x0FFFE000) >> 13) + 1; |
dkato | 0:5a74eeaefb5d | 823 | num_ways = ((ccsidr & 0x00001FF8) >> 3) + 1; |
dkato | 0:5a74eeaefb5d | 824 | log2_linesize = (ccsidr & 0x00000007) + 2 + 2; |
dkato | 0:5a74eeaefb5d | 825 | log2_num_ways = log2_up(num_ways); |
dkato | 0:5a74eeaefb5d | 826 | shift_way = 32 - log2_num_ways; |
dkato | 0:5a74eeaefb5d | 827 | for (int way = num_ways-1; way >= 0; way--) { |
dkato | 0:5a74eeaefb5d | 828 | for (int set = num_sets-1; set >= 0; set--) { |
dkato | 0:5a74eeaefb5d | 829 | Dummy = (level << 1) | (set << log2_linesize) | (way << shift_way); |
dkato | 0:5a74eeaefb5d | 830 | switch (maint) { |
dkato | 0:5a74eeaefb5d | 831 | case 0: |
dkato | 0:5a74eeaefb5d | 832 | // DCISW. Invalidate by Set/Way |
dkato | 0:5a74eeaefb5d | 833 | __ASM volatile("MCR p15, 0, %0, c7, c6, 2" : : "r"(Dummy) : "memory"); |
dkato | 0:5a74eeaefb5d | 834 | break; |
dkato | 0:5a74eeaefb5d | 835 | case 1: |
dkato | 0:5a74eeaefb5d | 836 | // DCCSW. Clean by Set/Way |
dkato | 0:5a74eeaefb5d | 837 | __ASM volatile("MCR p15, 0, %0, c7, c10, 2" : : "r"(Dummy) : "memory"); |
dkato | 0:5a74eeaefb5d | 838 | break; |
dkato | 0:5a74eeaefb5d | 839 | default: |
dkato | 0:5a74eeaefb5d | 840 | // DCCISW. Clean and Invalidate by Set/Way |
dkato | 0:5a74eeaefb5d | 841 | __ASM volatile("MCR p15, 0, %0, c7, c14, 2" : : "r"(Dummy) : "memory"); |
dkato | 0:5a74eeaefb5d | 842 | break; |
dkato | 0:5a74eeaefb5d | 843 | } |
dkato | 0:5a74eeaefb5d | 844 | } |
dkato | 0:5a74eeaefb5d | 845 | } |
dkato | 0:5a74eeaefb5d | 846 | __DMB(); |
dkato | 0:5a74eeaefb5d | 847 | } |
dkato | 0:5a74eeaefb5d | 848 | |
dkato | 0:5a74eeaefb5d | 849 | __STATIC_FORCEINLINE void L1C_CleanInvalidateCache_sforce(uint32_t op) { |
dkato | 0:5a74eeaefb5d | 850 | register volatile uint32_t clidr; |
dkato | 0:5a74eeaefb5d | 851 | uint32_t cache_type; |
dkato | 0:5a74eeaefb5d | 852 | clidr = __get_CLIDR(); |
dkato | 0:5a74eeaefb5d | 853 | for (uint32_t i = 0; i<7; i++) { |
dkato | 0:5a74eeaefb5d | 854 | cache_type = (clidr >> i*3) & 0x7UL; |
dkato | 0:5a74eeaefb5d | 855 | if ((cache_type >= 2) && (cache_type <= 4)) { |
dkato | 0:5a74eeaefb5d | 856 | __L1C_MaintainDCacheSetWay_sforce(i, op); |
dkato | 0:5a74eeaefb5d | 857 | } |
dkato | 0:5a74eeaefb5d | 858 | } |
dkato | 0:5a74eeaefb5d | 859 | } |
dkato | 0:5a74eeaefb5d | 860 | #endif |
dkato | 0:5a74eeaefb5d | 861 | |
dkato | 0:5a74eeaefb5d | 862 | #ifdef MBED_VERSION |
dkato | 0:5a74eeaefb5d | 863 | |
dkato | 0:5a74eeaefb5d | 864 | void FlashAccess::cache_control(void) { |
dkato | 0:5a74eeaefb5d | 865 | unsigned int assoc; |
dkato | 0:5a74eeaefb5d | 866 | |
dkato | 0:5a74eeaefb5d | 867 | /* ==== Cleaning and invalidation of the L1 data cache ==== */ |
dkato | 0:5a74eeaefb5d | 868 | L1C_CleanInvalidateCache_sforce(2); |
dkato | 0:5a74eeaefb5d | 869 | __DSB(); |
dkato | 0:5a74eeaefb5d | 870 | |
dkato | 0:5a74eeaefb5d | 871 | /* ==== Cleaning and invalidation of the L2 cache ==== */ |
dkato | 0:5a74eeaefb5d | 872 | if (PL310->AUX_CNT & (1<<16)) { |
dkato | 0:5a74eeaefb5d | 873 | assoc = 16; |
dkato | 0:5a74eeaefb5d | 874 | } else { |
dkato | 0:5a74eeaefb5d | 875 | assoc = 8; |
dkato | 0:5a74eeaefb5d | 876 | } |
dkato | 0:5a74eeaefb5d | 877 | PL310->INV_WAY = (1 << assoc) - 1; |
dkato | 0:5a74eeaefb5d | 878 | while(PL310->INV_WAY & ((1 << assoc) - 1)); // poll invalidate |
dkato | 0:5a74eeaefb5d | 879 | PL310->CACHE_SYNC = 0x0; |
dkato | 0:5a74eeaefb5d | 880 | |
dkato | 0:5a74eeaefb5d | 881 | /* ==== Invalidate all TLB entries ==== */ |
dkato | 0:5a74eeaefb5d | 882 | __ca9u_inv_tlb_all(); |
dkato | 0:5a74eeaefb5d | 883 | |
dkato | 0:5a74eeaefb5d | 884 | /* ==== Invalidate the L1 instruction cache ==== */ |
dkato | 0:5a74eeaefb5d | 885 | __v7_inv_icache_all(); |
dkato | 0:5a74eeaefb5d | 886 | __DSB(); |
dkato | 0:5a74eeaefb5d | 887 | __ISB(); |
dkato | 0:5a74eeaefb5d | 888 | } |
dkato | 0:5a74eeaefb5d | 889 | |
dkato | 0:5a74eeaefb5d | 890 | #else // mbed-os 5.6.4 |
dkato | 0:5a74eeaefb5d | 891 | |
dkato | 0:5a74eeaefb5d | 892 | void FlashAccess::cache_control(void) { |
dkato | 0:5a74eeaefb5d | 893 | unsigned int assoc; |
dkato | 0:5a74eeaefb5d | 894 | |
dkato | 0:5a74eeaefb5d | 895 | /* ==== Cleaning and invalidation of the L1 data cache ==== */ |
dkato | 0:5a74eeaefb5d | 896 | L1C_CleanInvalidateCache_sforce(2); |
dkato | 0:5a74eeaefb5d | 897 | __DSB(); |
dkato | 0:5a74eeaefb5d | 898 | |
dkato | 0:5a74eeaefb5d | 899 | /* ==== Cleaning and invalidation of the L2 cache ==== */ |
dkato | 0:5a74eeaefb5d | 900 | if (L2C_310->AUX_CNT & (1U << 16U)) { |
dkato | 0:5a74eeaefb5d | 901 | assoc = 16U; |
dkato | 0:5a74eeaefb5d | 902 | } else { |
dkato | 0:5a74eeaefb5d | 903 | assoc = 8U; |
dkato | 0:5a74eeaefb5d | 904 | } |
dkato | 0:5a74eeaefb5d | 905 | L2C_310->CLEAN_INV_WAY = (1U << assoc) - 1U; |
dkato | 0:5a74eeaefb5d | 906 | while (L2C_310->CLEAN_INV_WAY & ((1U << assoc) - 1U)); // poll invalidate |
dkato | 0:5a74eeaefb5d | 907 | L2C_310->CACHE_SYNC = 0x0; |
dkato | 0:5a74eeaefb5d | 908 | |
dkato | 0:5a74eeaefb5d | 909 | /* ==== Invalidate all TLB entries ==== */ |
dkato | 0:5a74eeaefb5d | 910 | __set_TLBIALL(0); |
dkato | 0:5a74eeaefb5d | 911 | __DSB(); // ensure completion of the invalidation |
dkato | 0:5a74eeaefb5d | 912 | __ISB(); // ensure instruction fetch path sees new state |
dkato | 0:5a74eeaefb5d | 913 | |
dkato | 0:5a74eeaefb5d | 914 | /* ==== Invalidate the L1 instruction cache ==== */ |
dkato | 0:5a74eeaefb5d | 915 | __set_ICIALLU(0); |
dkato | 0:5a74eeaefb5d | 916 | __DSB(); // ensure completion of the invalidation |
dkato | 0:5a74eeaefb5d | 917 | __ISB(); // ensure instruction fetch path sees new I cache state |
dkato | 0:5a74eeaefb5d | 918 | } |
dkato | 0:5a74eeaefb5d | 919 | #endif |