diff options
Diffstat (limited to 'tmk_core/common/chibios')
| -rwxr-xr-x | tmk_core/common/chibios/eeprom_stm32.c | 673 | ||||
| -rwxr-xr-x | tmk_core/common/chibios/eeprom_stm32.h | 89 | ||||
| -rw-r--r-- | tmk_core/common/chibios/eeprom_teensy.c (renamed from tmk_core/common/chibios/eeprom.c) | 0 | ||||
| -rwxr-xr-x | tmk_core/common/chibios/flash_stm32.c | 180 | ||||
| -rwxr-xr-x | tmk_core/common/chibios/flash_stm32.h | 53 | 
5 files changed, 995 insertions, 0 deletions
diff --git a/tmk_core/common/chibios/eeprom_stm32.c b/tmk_core/common/chibios/eeprom_stm32.c new file mode 100755 index 0000000000..3c19451223 --- /dev/null +++ b/tmk_core/common/chibios/eeprom_stm32.c @@ -0,0 +1,673 @@ +/* + * This software is experimental and a work in progress. + * Under no circumstances should these files be used in relation to any critical system(s). + * Use of these files is at your own risk. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * This files are free to use from https://github.com/rogerclarkmelbourne/Arduino_STM32 and  + * https://github.com/leaflabs/libmaple + * + * Modifications for QMK and STM32F303 by Yiancar + */ + +#include "eeprom_stm32.h" + +    FLASH_Status EE_ErasePage(uint32_t); + +    uint16_t EE_CheckPage(uint32_t, uint16_t); +    uint16_t EE_CheckErasePage(uint32_t, uint16_t); +    uint16_t EE_Format(void); +    uint32_t EE_FindValidPage(void); +    uint16_t EE_GetVariablesCount(uint32_t, uint16_t); +    uint16_t EE_PageTransfer(uint32_t, uint32_t, uint16_t); +    uint16_t EE_VerifyPageFullWriteVariable(uint16_t, uint16_t); + +    uint32_t PageBase0 = EEPROM_PAGE0_BASE; +    uint32_t PageBase1 = EEPROM_PAGE1_BASE; +    uint32_t PageSize = EEPROM_PAGE_SIZE; +    uint16_t Status = EEPROM_NOT_INIT; + +// See http://www.st.com/web/en/resource/technical/document/application_note/CD00165693.pdf + +/** +  * @brief  Check page for blank +  * @param  page base address +  * @retval Success or error +  *     EEPROM_BAD_FLASH:   page not empty after erase +  *     EEPROM_OK:          page blank +  */ +uint16_t EE_CheckPage(uint32_t pageBase, uint16_t status) +{ +    uint32_t pageEnd = pageBase + (uint32_t)PageSize; + +    // Page Status not EEPROM_ERASED and not a "state" +    if ((*(__IO uint16_t*)pageBase) != EEPROM_ERASED && (*(__IO uint16_t*)pageBase) != status) +        return EEPROM_BAD_FLASH; +    for(pageBase += 4; pageBase < pageEnd; pageBase += 4) +        if ((*(__IO uint32_t*)pageBase) != 0xFFFFFFFF)  // Verify if slot is empty +            return EEPROM_BAD_FLASH; +    return EEPROM_OK; +} + +/** +  * @brief  Erase page with increment erase counter (page + 2) +  * @param  page base address +  * @retval Success or error +  *         FLASH_COMPLETE: success erase +  *         - Flash error code: on write Flash error +  */ +FLASH_Status EE_ErasePage(uint32_t pageBase) +{ +    FLASH_Status FlashStatus; +    uint16_t data = (*(__IO uint16_t*)(pageBase)); +    if ((data == EEPROM_ERASED) || (data == EEPROM_VALID_PAGE) || (data == EEPROM_RECEIVE_DATA)) +        data = (*(__IO uint16_t*)(pageBase + 2)) + 1; +    else +        data = 0; + +    FlashStatus = FLASH_ErasePage(pageBase); +    if (FlashStatus == FLASH_COMPLETE) +        FlashStatus = FLASH_ProgramHalfWord(pageBase + 2, data); + +    return FlashStatus; +} + +/** +  * @brief  Check page for blank and erase it +  * @param  page base address +  * @retval Success or error +  *         - Flash error code: on write Flash error +  *         - EEPROM_BAD_FLASH: page not empty after erase +  *         - EEPROM_OK:            page blank +  */ +uint16_t EE_CheckErasePage(uint32_t pageBase, uint16_t status) +{ +    uint16_t FlashStatus; +    if (EE_CheckPage(pageBase, status) != EEPROM_OK) +    { +        FlashStatus = EE_ErasePage(pageBase); +        if (FlashStatus != FLASH_COMPLETE) +            return FlashStatus; +        return EE_CheckPage(pageBase, status); +    } +    return EEPROM_OK; +} + +/** +  * @brief  Find valid Page for write or read operation +  * @param  Page0: Page0 base address +  *         Page1: Page1 base address +  * @retval Valid page address (PAGE0 or PAGE1) or NULL in case of no valid page was found +  */ +uint32_t EE_FindValidPage(void) +{ +    uint16_t status0 = (*(__IO uint16_t*)PageBase0);        // Get Page0 actual status +    uint16_t status1 = (*(__IO uint16_t*)PageBase1);        // Get Page1 actual status + +    if (status0 == EEPROM_VALID_PAGE && status1 == EEPROM_ERASED) +        return PageBase0; +    if (status1 == EEPROM_VALID_PAGE && status0 == EEPROM_ERASED) +        return PageBase1; + +    return 0; +} + +/** +  * @brief  Calculate unique variables in EEPROM +  * @param  start: address of first slot to check (page + 4) +  * @param  end: page end address +  * @param  address: 16 bit virtual address of the variable to excluse (or 0XFFFF) +  * @retval count of variables +  */ +uint16_t EE_GetVariablesCount(uint32_t pageBase, uint16_t skipAddress) +{ +    uint16_t varAddress, nextAddress; +    uint32_t idx; +    uint32_t pageEnd = pageBase + (uint32_t)PageSize; +    uint16_t count = 0; + +    for (pageBase += 6; pageBase < pageEnd; pageBase += 4) +    { +        varAddress = (*(__IO uint16_t*)pageBase); +        if (varAddress == 0xFFFF || varAddress == skipAddress) +            continue; + +        count++; +        for(idx = pageBase + 4; idx < pageEnd; idx += 4) +        { +            nextAddress = (*(__IO uint16_t*)idx); +            if (nextAddress == varAddress) +            { +                count--; +                break; +            } +        } +    } +    return count; +} + +/** +  * @brief  Transfers last updated variables data from the full Page to an empty one. +  * @param  newPage: new page base address +  * @param  oldPage: old page base address +  * @param  SkipAddress: 16 bit virtual address of the variable (or 0xFFFF) +  * @retval Success or error status: +  *           - FLASH_COMPLETE: on success +  *           - EEPROM_OUT_SIZE: if valid new page is full +  *           - Flash error code: on write Flash error +  */ +uint16_t EE_PageTransfer(uint32_t newPage, uint32_t oldPage, uint16_t SkipAddress) +{ +    uint32_t oldEnd, newEnd; +    uint32_t oldIdx, newIdx, idx; +    uint16_t address, data, found; +    FLASH_Status FlashStatus; + +    // Transfer process: transfer variables from old to the new active page +    newEnd = newPage + ((uint32_t)PageSize); + +    // Find first free element in new page +    for (newIdx = newPage + 4; newIdx < newEnd; newIdx += 4) +        if ((*(__IO uint32_t*)newIdx) == 0xFFFFFFFF)    // Verify if element +            break;                                  //  contents are 0xFFFFFFFF +    if (newIdx >= newEnd) +        return EEPROM_OUT_SIZE; + +    oldEnd = oldPage + 4; +    oldIdx = oldPage + (uint32_t)(PageSize - 2); + +    for (; oldIdx > oldEnd; oldIdx -= 4) +    { +        address = *(__IO uint16_t*)oldIdx; +        if (address == 0xFFFF || address == SkipAddress) +            continue;                       // it's means that power off after write data + +        found = 0; +        for (idx = newPage + 6; idx < newIdx; idx += 4) +            if ((*(__IO uint16_t*)(idx)) == address) +            { +                found = 1; +                break; +            } + +        if (found) +            continue; + +        if (newIdx < newEnd) +        { +            data = (*(__IO uint16_t*)(oldIdx - 2)); + +            FlashStatus = FLASH_ProgramHalfWord(newIdx, data); +            if (FlashStatus != FLASH_COMPLETE) +                return FlashStatus; + +            FlashStatus = FLASH_ProgramHalfWord(newIdx + 2, address); +            if (FlashStatus != FLASH_COMPLETE) +                return FlashStatus; + +            newIdx += 4; +        } +        else +            return EEPROM_OUT_SIZE; +    } + +    // Erase the old Page: Set old Page status to EEPROM_EEPROM_ERASED status +    data = EE_CheckErasePage(oldPage, EEPROM_ERASED); +    if (data != EEPROM_OK) +        return data; + +    // Set new Page status +    FlashStatus = FLASH_ProgramHalfWord(newPage, EEPROM_VALID_PAGE); +    if (FlashStatus != FLASH_COMPLETE) +        return FlashStatus; + +    return EEPROM_OK; +} + +/** +  * @brief  Verify if active page is full and Writes variable in EEPROM. +  * @param  Address: 16 bit virtual address of the variable +  * @param  Data: 16 bit data to be written as variable value +  * @retval Success or error status: +  *           - FLASH_COMPLETE: on success +  *           - EEPROM_PAGE_FULL: if valid page is full (need page transfer) +  *           - EEPROM_NO_VALID_PAGE: if no valid page was found +  *           - EEPROM_OUT_SIZE: if EEPROM size exceeded +  *           - Flash error code: on write Flash error +  */ +uint16_t EE_VerifyPageFullWriteVariable(uint16_t Address, uint16_t Data) +{ +    FLASH_Status FlashStatus; +    uint32_t idx, pageBase, pageEnd, newPage; +    uint16_t count; + +    // Get valid Page for write operation +    pageBase = EE_FindValidPage(); +    if (pageBase == 0) +        return  EEPROM_NO_VALID_PAGE; + +    // Get the valid Page end Address +    pageEnd = pageBase + PageSize;          // Set end of page + +    for (idx = pageEnd - 2; idx > pageBase; idx -= 4) +    { +        if ((*(__IO uint16_t*)idx) == Address)      // Find last value for address +        { +            count = (*(__IO uint16_t*)(idx - 2));   // Read last data +            if (count == Data) +                return EEPROM_OK; +            if (count == 0xFFFF) +            { +                FlashStatus = FLASH_ProgramHalfWord(idx - 2, Data); // Set variable data +                if (FlashStatus == FLASH_COMPLETE) +                    return EEPROM_OK; +            } +            break; +        } +    } + +    // Check each active page address starting from begining +    for (idx = pageBase + 4; idx < pageEnd; idx += 4) +        if ((*(__IO uint32_t*)idx) == 0xFFFFFFFF)               // Verify if element  +        {                                                   //  contents are 0xFFFFFFFF +            FlashStatus = FLASH_ProgramHalfWord(idx, Data); // Set variable data +            if (FlashStatus != FLASH_COMPLETE) +                return FlashStatus; +            FlashStatus = FLASH_ProgramHalfWord(idx + 2, Address);  // Set variable virtual address +            if (FlashStatus != FLASH_COMPLETE) +                return FlashStatus; +            return EEPROM_OK; +        } + +    // Empty slot not found, need page transfer +    // Calculate unique variables in page +    count = EE_GetVariablesCount(pageBase, Address) + 1; +    if (count >= (PageSize / 4 - 1)) +        return EEPROM_OUT_SIZE; + +    if (pageBase == PageBase1) +        newPage = PageBase0;        // New page address where variable will be moved to +    else +        newPage = PageBase1; + +    // Set the new Page status to RECEIVE_DATA status +    FlashStatus = FLASH_ProgramHalfWord(newPage, EEPROM_RECEIVE_DATA); +    if (FlashStatus != FLASH_COMPLETE) +        return FlashStatus; + +    // Write the variable passed as parameter in the new active page +    FlashStatus = FLASH_ProgramHalfWord(newPage + 4, Data); +    if (FlashStatus != FLASH_COMPLETE) +        return FlashStatus; + +    FlashStatus = FLASH_ProgramHalfWord(newPage + 6, Address); +    if (FlashStatus != FLASH_COMPLETE) +        return FlashStatus; + +    return EE_PageTransfer(newPage, pageBase, Address); +} + +/*EEPROMClass::EEPROMClass(void) +{ +    PageBase0 = EEPROM_PAGE0_BASE; +    PageBase1 = EEPROM_PAGE1_BASE; +    PageSize = EEPROM_PAGE_SIZE; +    Status = EEPROM_NOT_INIT; +}*/ +/* +uint16_t EEPROM_init(uint32_t pageBase0, uint32_t pageBase1, uint32_t pageSize) +{ +    PageBase0 = pageBase0; +    PageBase1 = pageBase1; +    PageSize = pageSize; +    return EEPROM_init(); +}*/ + +uint16_t EEPROM_init(void) +{ +    uint16_t status0 = 6, status1 = 6; +    FLASH_Status FlashStatus; + +    FLASH_Unlock(); +    Status = EEPROM_NO_VALID_PAGE; + +    status0 = (*(__IO uint16_t *)PageBase0); +    status1 = (*(__IO uint16_t *)PageBase1); + +    switch (status0) +    { +/* +        Page0               Page1 +        -----               ----- +    EEPROM_ERASED       EEPROM_VALID_PAGE           Page1 valid, Page0 erased +                        EEPROM_RECEIVE_DATA         Page1 need set to valid, Page0 erased +                        EEPROM_ERASED               make EE_Format +                        any                         Error: EEPROM_NO_VALID_PAGE +*/ +    case EEPROM_ERASED: +        if (status1 == EEPROM_VALID_PAGE)           // Page0 erased, Page1 valid +            Status = EE_CheckErasePage(PageBase0, EEPROM_ERASED); +        else if (status1 == EEPROM_RECEIVE_DATA)    // Page0 erased, Page1 receive +        { +            FlashStatus = FLASH_ProgramHalfWord(PageBase1, EEPROM_VALID_PAGE); +            if (FlashStatus != FLASH_COMPLETE) +                Status = FlashStatus; +            else +                Status = EE_CheckErasePage(PageBase0, EEPROM_ERASED); +        } +        else if (status1 == EEPROM_ERASED)          // Both in erased state so format EEPROM +            Status = EEPROM_format(); +        break; +/* +        Page0               Page1 +        -----               ----- +    EEPROM_RECEIVE_DATA EEPROM_VALID_PAGE           Transfer Page1 to Page0 +                        EEPROM_ERASED               Page0 need set to valid, Page1 erased +                        any                         EEPROM_NO_VALID_PAGE +*/ +    case EEPROM_RECEIVE_DATA: +        if (status1 == EEPROM_VALID_PAGE)           // Page0 receive, Page1 valid +            Status = EE_PageTransfer(PageBase0, PageBase1, 0xFFFF); +        else if (status1 == EEPROM_ERASED)          // Page0 receive, Page1 erased +        { +            Status = EE_CheckErasePage(PageBase1, EEPROM_ERASED); +            if (Status == EEPROM_OK) +            { +                FlashStatus = FLASH_ProgramHalfWord(PageBase0, EEPROM_VALID_PAGE); +                if (FlashStatus != FLASH_COMPLETE) +                    Status = FlashStatus; +                else +                    Status = EEPROM_OK; +            } +        } +        break; +/* +        Page0               Page1 +        -----               ----- +    EEPROM_VALID_PAGE   EEPROM_VALID_PAGE           Error: EEPROM_NO_VALID_PAGE +                        EEPROM_RECEIVE_DATA         Transfer Page0 to Page1 +                        any                         Page0 valid, Page1 erased +*/ +    case EEPROM_VALID_PAGE: +        if (status1 == EEPROM_VALID_PAGE)           // Both pages valid +            Status = EEPROM_NO_VALID_PAGE; +        else if (status1 == EEPROM_RECEIVE_DATA) +            Status = EE_PageTransfer(PageBase1, PageBase0, 0xFFFF); +        else +            Status = EE_CheckErasePage(PageBase1, EEPROM_ERASED); +        break; +/* +        Page0               Page1 +        -----               ----- +        any             EEPROM_VALID_PAGE           Page1 valid, Page0 erased +                        EEPROM_RECEIVE_DATA         Page1 valid, Page0 erased +                        any                         EEPROM_NO_VALID_PAGE +*/ +    default: +        if (status1 == EEPROM_VALID_PAGE) +            Status = EE_CheckErasePage(PageBase0, EEPROM_ERASED);   // Check/Erase Page0 +        else if (status1 == EEPROM_RECEIVE_DATA) +        { +            FlashStatus = FLASH_ProgramHalfWord(PageBase1, EEPROM_VALID_PAGE); +            if (FlashStatus != FLASH_COMPLETE) +                Status = FlashStatus; +            else +                Status = EE_CheckErasePage(PageBase0, EEPROM_ERASED); +        } +        break; +    } +    return Status; +} + +/** +  * @brief  Erases PAGE0 and PAGE1 and writes EEPROM_VALID_PAGE / 0 header to PAGE0 +  * @param  PAGE0 and PAGE1 base addresses +  * @retval Status of the last operation (Flash write or erase) done during EEPROM formating +  */ +uint16_t EEPROM_format(void) +{ +    uint16_t status; +    FLASH_Status FlashStatus; + +    FLASH_Unlock(); + +    // Erase Page0 +    status = EE_CheckErasePage(PageBase0, EEPROM_VALID_PAGE); +    if (status != EEPROM_OK) +        return status; +    if ((*(__IO uint16_t*)PageBase0) == EEPROM_ERASED) +    { +        // Set Page0 as valid page: Write VALID_PAGE at Page0 base address +        FlashStatus = FLASH_ProgramHalfWord(PageBase0, EEPROM_VALID_PAGE); +        if (FlashStatus != FLASH_COMPLETE) +            return FlashStatus; +    } +    // Erase Page1 +    return EE_CheckErasePage(PageBase1, EEPROM_ERASED); +} + +/** +  * @brief  Returns the erase counter for current page +  * @param  Data: Global variable contains the read variable value +  * @retval Success or error status: +  *         - EEPROM_OK: if erases counter return. +  *         - EEPROM_NO_VALID_PAGE: if no valid page was found. +  */ +uint16_t EEPROM_erases(uint16_t *Erases) +{ +    uint32_t pageBase; +    if (Status != EEPROM_OK) +        if (EEPROM_init() != EEPROM_OK) +            return Status; + +    // Get active Page for read operation +    pageBase = EE_FindValidPage(); +    if (pageBase == 0) +        return  EEPROM_NO_VALID_PAGE; + +    *Erases = (*(__IO uint16_t*)pageBase+2); +    return EEPROM_OK; +} + +/** +  * @brief  Returns the last stored variable data, if found, +  *         which correspond to the passed virtual address +  * @param  Address: Variable virtual address +  * @retval Data for variable or EEPROM_DEFAULT_DATA, if any errors +  */ +/* +uint16_t EEPROM_read (uint16_t Address) +{ +    uint16_t data; +    EEPROM_read(Address, &data); +    return data; +}*/ + +/** +  * @brief  Returns the last stored variable data, if found, +  *         which correspond to the passed virtual address +  * @param  Address: Variable virtual address +  * @param  Data: Pointer to data variable +  * @retval Success or error status: +  *           - EEPROM_OK: if variable was found +  *           - EEPROM_BAD_ADDRESS: if the variable was not found +  *           - EEPROM_NO_VALID_PAGE: if no valid page was found. +  */ +uint16_t EEPROM_read(uint16_t Address, uint16_t *Data) +{ +    uint32_t pageBase, pageEnd; + +    // Set default data (empty EEPROM) +    *Data = EEPROM_DEFAULT_DATA; + +    if (Status == EEPROM_NOT_INIT) +        if (EEPROM_init() != EEPROM_OK) +            return Status; + +    // Get active Page for read operation +    pageBase = EE_FindValidPage(); +    if (pageBase == 0) +        return  EEPROM_NO_VALID_PAGE; + +    // Get the valid Page end Address +    pageEnd = pageBase + ((uint32_t)(PageSize - 2)); +     +    // Check each active page address starting from end +    for (pageBase += 6; pageEnd >= pageBase; pageEnd -= 4) +        if ((*(__IO uint16_t*)pageEnd) == Address)      // Compare the read address with the virtual address +        { +            *Data = (*(__IO uint16_t*)(pageEnd - 2));       // Get content of Address-2 which is variable value +            return EEPROM_OK; +        } + +    // Return ReadStatus value: (0: variable exist, 1: variable doesn't exist) +    return EEPROM_BAD_ADDRESS; +} + +/** +  * @brief  Writes/upadtes variable data in EEPROM. +  * @param  VirtAddress: Variable virtual address +  * @param  Data: 16 bit data to be written +  * @retval Success or error status: +  *         - FLASH_COMPLETE: on success +  *         - EEPROM_BAD_ADDRESS: if address = 0xFFFF +  *         - EEPROM_PAGE_FULL: if valid page is full +  *         - EEPROM_NO_VALID_PAGE: if no valid page was found +  *         - EEPROM_OUT_SIZE: if no empty EEPROM variables +  *         - Flash error code: on write Flash error +  */ +uint16_t EEPROM_write(uint16_t Address, uint16_t Data) +{ +    if (Status == EEPROM_NOT_INIT) +        if (EEPROM_init() != EEPROM_OK) +            return Status; + +    if (Address == 0xFFFF) +        return EEPROM_BAD_ADDRESS; + +    // Write the variable virtual address and value in the EEPROM +    uint16_t status = EE_VerifyPageFullWriteVariable(Address, Data); +    return status; +} + +/** +  * @brief  Writes/upadtes variable data in EEPROM. +            The value is written only if differs from the one already saved at the same address. +  * @param  VirtAddress: Variable virtual address +  * @param  Data: 16 bit data to be written +  * @retval Success or error status: +  *         - EEPROM_SAME_VALUE: If new Data matches existing EEPROM Data +  *         - FLASH_COMPLETE: on success +  *         - EEPROM_BAD_ADDRESS: if address = 0xFFFF +  *         - EEPROM_PAGE_FULL: if valid page is full +  *         - EEPROM_NO_VALID_PAGE: if no valid page was found +  *         - EEPROM_OUT_SIZE: if no empty EEPROM variables +  *         - Flash error code: on write Flash error +  */ +uint16_t EEPROM_update(uint16_t Address, uint16_t Data) +{ +    uint16_t temp; +    EEPROM_read(Address, &temp); +    if (Address == Data) +        return EEPROM_SAME_VALUE; +    else +        return EEPROM_write(Address, Data); +} + +/** +  * @brief  Return number of variable +  * @retval Number of variables +  */ +uint16_t EEPROM_count(uint16_t *Count) +{ +    if (Status == EEPROM_NOT_INIT) +        if (EEPROM_init() != EEPROM_OK) +            return Status; + +    // Get valid Page for write operation +    uint32_t pageBase = EE_FindValidPage(); +    if (pageBase == 0) +        return EEPROM_NO_VALID_PAGE;    // No valid page, return max. numbers + +    *Count = EE_GetVariablesCount(pageBase, 0xFFFF); +    return EEPROM_OK; +} + +uint16_t EEPROM_maxcount(void) +{ +    return ((PageSize / 4)-1); +} + + +uint8_t eeprom_read_byte (const uint8_t *Address) +{ +    const uint16_t p = (const uint32_t) Address; +    uint16_t temp; +    EEPROM_read(p, &temp); +    return (uint8_t) temp; +} + +void eeprom_write_byte (uint8_t *Address, uint8_t Value) +{ +    uint16_t p = (uint32_t) Address; +    EEPROM_write(p, (uint16_t) Value); +} + +void eeprom_update_byte (uint8_t *Address, uint8_t Value) +{ +    uint16_t p = (uint32_t) Address; +    EEPROM_update(p, (uint16_t) Value); +} + +uint16_t eeprom_read_word (const uint16_t *Address) +{ +    const uint16_t p = (const uint32_t) Address; +    uint16_t temp; +    EEPROM_read(p, &temp); +    return temp; +} + +void eeprom_write_word (uint16_t *Address, uint16_t Value) +{ +    uint16_t p = (uint32_t) Address; +    EEPROM_write(p, Value); +} + +void eeprom_update_word (uint16_t *Address, uint16_t Value) +{ +    uint16_t p = (uint32_t) Address; +    EEPROM_update(p, Value); +} + +uint32_t eeprom_read_dword (const uint32_t *Address) +{ +    const uint16_t p = (const uint32_t) Address; +    uint16_t temp1, temp2; +    EEPROM_read(p, &temp1); +    EEPROM_read(p + 1, &temp2); +    return temp1 | (temp2 << 16); +} + +void eeprom_write_dword (uint32_t *Address, uint32_t Value) +{ +    uint16_t temp = (uint16_t) Value; +    uint16_t p = (uint32_t) Address; +    EEPROM_write(p, temp); +    temp = (uint16_t) (Value >> 16); +    EEPROM_write(p + 1, temp); +} + +void eeprom_update_dword (uint32_t *Address, uint32_t Value) +{ +    uint16_t temp = (uint16_t) Value; +    uint16_t p = (uint32_t) Address; +    EEPROM_update(p, temp); +    temp = (uint16_t) (Value >> 16); +    EEPROM_update(p + 1, temp); +} diff --git a/tmk_core/common/chibios/eeprom_stm32.h b/tmk_core/common/chibios/eeprom_stm32.h new file mode 100755 index 0000000000..d06d302665 --- /dev/null +++ b/tmk_core/common/chibios/eeprom_stm32.h @@ -0,0 +1,89 @@ +/* + * This software is experimental and a work in progress. + * Under no circumstances should these files be used in relation to any critical system(s). + * Use of these files is at your own risk. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * This files are free to use from https://github.com/rogerclarkmelbourne/Arduino_STM32 and  + * https://github.com/leaflabs/libmaple + * + * Modifications for QMK and STM32F303 by Yiancar + */ + +// This file must be modified if the MCU is not defined below. +// This library also assumes that the pages are not used by the firmware. + +#ifndef __EEPROM_H +#define __EEPROM_H + +#include "ch.h" +#include "hal.h" +#include "flash_stm32.h" + +// HACK ALERT. This definition may not match your processor +// To Do. Work out correct value for EEPROM_PAGE_SIZE on the STM32F103CT6 etc  +#define MCU_STM32F303CC + +#ifndef EEPROM_PAGE_SIZE +    #if defined (MCU_STM32F103RB) +        #define EEPROM_PAGE_SIZE    (uint16_t)0x400  /* Page size = 1KByte */ +    #elif defined (MCU_STM32F103ZE) || defined (MCU_STM32F103RE) || defined (MCU_STM32F103RD) || defined (MCU_STM32F303CC) +        #define EEPROM_PAGE_SIZE    (uint16_t)0x800  /* Page size = 2KByte */ +    #else +        #error  "No MCU type specified. Add something like -DMCU_STM32F103RB to your compiler arguments (probably in a Makefile)." +    #endif +#endif + +#ifndef EEPROM_START_ADDRESS +    #if defined (MCU_STM32F103RB) +        #define EEPROM_START_ADDRESS    ((uint32_t)(0x8000000 + 128 * 1024 - 2 * EEPROM_PAGE_SIZE)) +    #elif defined (MCU_STM32F103ZE) || defined (MCU_STM32F103RE) +        #define EEPROM_START_ADDRESS    ((uint32_t)(0x8000000 + 512 * 1024 - 2 * EEPROM_PAGE_SIZE)) +    #elif defined (MCU_STM32F103RD) +        #define EEPROM_START_ADDRESS    ((uint32_t)(0x8000000 + 384 * 1024 - 2 * EEPROM_PAGE_SIZE)) +    #elif defined (MCU_STM32F303CC) +        #define EEPROM_START_ADDRESS    ((uint32_t)(0x8000000 + 250 * 1024 - 2 * EEPROM_PAGE_SIZE)) +    #else +        #error  "No MCU type specified. Add something like -DMCU_STM32F103RB to your compiler arguments (probably in a Makefile)." +    #endif +#endif + +/* Pages 0 and 1 base and end addresses */ +#define EEPROM_PAGE0_BASE       ((uint32_t)(EEPROM_START_ADDRESS + 0x000)) +#define EEPROM_PAGE1_BASE       ((uint32_t)(EEPROM_START_ADDRESS + EEPROM_PAGE_SIZE)) + +/* Page status definitions */ +#define EEPROM_ERASED           ((uint16_t)0xFFFF)  /* PAGE is empty */ +#define EEPROM_RECEIVE_DATA     ((uint16_t)0xEEEE)  /* PAGE is marked to receive data */ +#define EEPROM_VALID_PAGE       ((uint16_t)0x0000)  /* PAGE containing valid data */ + +/* Page full define */ +enum uint16_t +    { +    EEPROM_OK               = ((uint16_t)0x0000), +    EEPROM_OUT_SIZE         = ((uint16_t)0x0081), +    EEPROM_BAD_ADDRESS      = ((uint16_t)0x0082), +    EEPROM_BAD_FLASH        = ((uint16_t)0x0083), +    EEPROM_NOT_INIT         = ((uint16_t)0x0084), +    EEPROM_SAME_VALUE       = ((uint16_t)0x0085), +    EEPROM_NO_VALID_PAGE    = ((uint16_t)0x00AB) +    }; + +#define EEPROM_DEFAULT_DATA     0xFFFF + +    uint16_t EEPROM_init(void); +    uint16_t EEPROM_format(void); +    uint16_t EEPROM_erases(uint16_t *); +    uint16_t EEPROM_read (uint16_t address, uint16_t *data); +    uint16_t EEPROM_write(uint16_t address, uint16_t data); +    uint16_t EEPROM_update(uint16_t address, uint16_t data); +    uint16_t EEPROM_count(uint16_t *); +    uint16_t EEPROM_maxcount(void); + +#endif  /* __EEPROM_H */ diff --git a/tmk_core/common/chibios/eeprom.c b/tmk_core/common/chibios/eeprom_teensy.c index 9061b790c4..9061b790c4 100644 --- a/tmk_core/common/chibios/eeprom.c +++ b/tmk_core/common/chibios/eeprom_teensy.c diff --git a/tmk_core/common/chibios/flash_stm32.c b/tmk_core/common/chibios/flash_stm32.c new file mode 100755 index 0000000000..e7199ac7b1 --- /dev/null +++ b/tmk_core/common/chibios/flash_stm32.c @@ -0,0 +1,180 @@ +/* + * This software is experimental and a work in progress. + * Under no circumstances should these files be used in relation to any critical system(s). + * Use of these files is at your own risk. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * This files are free to use from https://github.com/rogerclarkmelbourne/Arduino_STM32 and  + * https://github.com/leaflabs/libmaple + * + * Modifications for QMK and STM32F303 by Yiancar + */ + +#define STM32F303xC + +#include "stm32f3xx.h" +#include "flash_stm32.h" + +#define FLASH_KEY1          ((uint32_t)0x45670123) +#define FLASH_KEY2          ((uint32_t)0xCDEF89AB) + +/* Delay definition */ +#define EraseTimeout        ((uint32_t)0x00000FFF) +#define ProgramTimeout      ((uint32_t)0x0000001F) + +#define ASSERT(exp) (void)((0)) + +/** +  * @brief  Inserts a time delay. +  * @param  None +  * @retval None +  */ +static void delay(void) +{ +    __IO uint32_t i = 0; +    for(i = 0xFF; i != 0; i--) { } +} + +/** +  * @brief  Returns the FLASH Status. +  * @param  None +  * @retval FLASH Status: The returned value can be: FLASH_BUSY, FLASH_ERROR_PG, +  *   FLASH_ERROR_WRP or FLASH_COMPLETE +  */ +FLASH_Status FLASH_GetStatus(void) +{ +    if ((FLASH->SR & FLASH_SR_BSY) == FLASH_SR_BSY) +        return FLASH_BUSY; + +    if ((FLASH->SR & FLASH_SR_PGERR) != 0) +        return FLASH_ERROR_PG; + +    if ((FLASH->SR & FLASH_SR_WRPERR) != 0 ) +        return FLASH_ERROR_WRP; + +    if ((FLASH->SR & FLASH_OBR_OPTERR) != 0 ) +        return FLASH_ERROR_OPT; + +    return FLASH_COMPLETE; +} + +/** +  * @brief  Waits for a Flash operation to complete or a TIMEOUT to occur. +  * @param  Timeout: FLASH progamming Timeout +  * @retval FLASH Status: The returned value can be: FLASH_ERROR_PG, +  *   FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT. +  */ +FLASH_Status FLASH_WaitForLastOperation(uint32_t Timeout) +{  +    FLASH_Status status; + +    /* Check for the Flash Status */ +    status = FLASH_GetStatus(); +    /* Wait for a Flash operation to complete or a TIMEOUT to occur */ +    while ((status == FLASH_BUSY) && (Timeout != 0x00)) +    { +        delay(); +        status = FLASH_GetStatus(); +        Timeout--; +    } +    if (Timeout == 0) +        status = FLASH_TIMEOUT; +    /* Return the operation status */ +    return status; +} + +/** +  * @brief  Erases a specified FLASH page. +  * @param  Page_Address: The page address to be erased. +  * @retval FLASH Status: The returned value can be: FLASH_BUSY, FLASH_ERROR_PG, +  *   FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT. +  */ +FLASH_Status FLASH_ErasePage(uint32_t Page_Address) +{ +    FLASH_Status status = FLASH_COMPLETE; +    /* Check the parameters */ +    ASSERT(IS_FLASH_ADDRESS(Page_Address)); +    /* Wait for last operation to be completed */ +    status = FLASH_WaitForLastOperation(EraseTimeout); +   +    if(status == FLASH_COMPLETE) +    { +        /* if the previous operation is completed, proceed to erase the page */ +        FLASH->CR |= FLASH_CR_PER; +        FLASH->AR = Page_Address; +        FLASH->CR |= FLASH_CR_STRT; + +        /* Wait for last operation to be completed */ +        status = FLASH_WaitForLastOperation(EraseTimeout); +        if(status != FLASH_TIMEOUT) +        { +            /* if the erase operation is completed, disable the PER Bit */ +            FLASH->CR &= ~FLASH_CR_PER; +        } +        FLASH->SR = (FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPERR); +    } +    /* Return the Erase Status */ +    return status; +} + +/** +  * @brief  Programs a half word at a specified address. +  * @param  Address: specifies the address to be programmed. +  * @param  Data: specifies the data to be programmed. +  * @retval FLASH Status: The returned value can be: FLASH_ERROR_PG, +  *   FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.  +  */ +FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data) +{ +    FLASH_Status status = FLASH_BAD_ADDRESS; + +    if (IS_FLASH_ADDRESS(Address)) +    { +        /* Wait for last operation to be completed */ +        status = FLASH_WaitForLastOperation(ProgramTimeout); +        if(status == FLASH_COMPLETE) +        { +            /* if the previous operation is completed, proceed to program the new data */ +            FLASH->CR |= FLASH_CR_PG; +            *(__IO uint16_t*)Address = Data; +            /* Wait for last operation to be completed */ +            status = FLASH_WaitForLastOperation(ProgramTimeout); +            if(status != FLASH_TIMEOUT) +            { +                /* if the program operation is completed, disable the PG Bit */ +                FLASH->CR &= ~FLASH_CR_PG; +            } +            FLASH->SR = (FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPERR); +        } +    } +    return status; +} + +/** +  * @brief  Unlocks the FLASH Program Erase Controller. +  * @param  None +  * @retval None +  */ +void FLASH_Unlock(void) +{ +    /* Authorize the FPEC Access */ +    FLASH->KEYR = FLASH_KEY1; +    FLASH->KEYR = FLASH_KEY2; +} + +/** +  * @brief  Locks the FLASH Program Erase Controller. +  * @param  None +  * @retval None +  */ +void FLASH_Lock(void) +{ +    /* Set the Lock Bit to lock the FPEC and the FCR */ +    FLASH->CR |= FLASH_CR_LOCK; +} diff --git a/tmk_core/common/chibios/flash_stm32.h b/tmk_core/common/chibios/flash_stm32.h new file mode 100755 index 0000000000..cc065cbca2 --- /dev/null +++ b/tmk_core/common/chibios/flash_stm32.h @@ -0,0 +1,53 @@ +/* + * This software is experimental and a work in progress. + * Under no circumstances should these files be used in relation to any critical system(s). + * Use of these files is at your own risk. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * This files are free to use from https://github.com/rogerclarkmelbourne/Arduino_STM32 and  + * https://github.com/leaflabs/libmaple + * + * Modifications for QMK and STM32F303 by Yiancar + */ + +#ifndef __FLASH_STM32_H +#define __FLASH_STM32_H + +#ifdef __cplusplus + extern "C" { +#endif + +#include "ch.h" +#include "hal.h" + +typedef enum +    { +    FLASH_BUSY = 1, +    FLASH_ERROR_PG, +    FLASH_ERROR_WRP, +    FLASH_ERROR_OPT, +    FLASH_COMPLETE, +    FLASH_TIMEOUT, +    FLASH_BAD_ADDRESS +    } FLASH_Status; + +#define IS_FLASH_ADDRESS(ADDRESS) (((ADDRESS) >= 0x08000000) && ((ADDRESS) < 0x0807FFFF)) + +FLASH_Status FLASH_WaitForLastOperation(uint32_t Timeout); +FLASH_Status FLASH_ErasePage(uint32_t Page_Address); +FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data); + +void FLASH_Unlock(void); +void FLASH_Lock(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __FLASH_STM32_H */  | 
