├── .gitignore ├── CMakeLists.txt ├── README.md ├── flash ├── flash.c ├── flash.cmake ├── flash.h ├── helper.c ├── helper.h ├── ihex.c ├── ihex.h ├── ihexhelper.c └── ihexhelper.h ├── openocd.cfg └── test ├── CMakeLists.txt ├── chconf.h ├── ffconf.h ├── generate-test-ihex-f407.sh ├── halconf.h ├── mcuconf.h ├── sdcard.c ├── sdcard.h └── test.c /.gitignore: -------------------------------------------------------------------------------- 1 | Thumbs.db 2 | 3 | # Text editors temporary files 4 | *~ 5 | .~* 6 | ~* 7 | *.swp 8 | 9 | # IDE temporary files 10 | *.ncb 11 | *.pdb 12 | *.suo 13 | *.obj 14 | *.lnk 15 | *.user* 16 | *.ilk 17 | 18 | # Object files 19 | *.o 20 | 21 | # Binary files 22 | *.exe 23 | *.out 24 | *.app 25 | *.dll 26 | *.idl 27 | *.tlb 28 | *.a 29 | *.o 30 | *.dll 31 | *.so 32 | *.so.* 33 | *.dylib 34 | 35 | # Auto-generated files 36 | Makefile* 37 | 38 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | project(flash-stm32f407) 4 | 5 | set(CHIBIOS_ROOT "../ChibiOS") 6 | get_filename_component(CHIBIOS_ROOT "${CHIBIOS_ROOT}" ABSOLUTE) 7 | 8 | set(CHIBIOS_BOARD_CMAKE_FILE "${CHIBIOS_ROOT}/tools/cmake/boards/olimex-stm32-p407-sdio.cmake") 9 | 10 | include(${CHIBIOS_ROOT}/tools/cmake/openocd.cmake) 11 | 12 | add_subdirectory(test) 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | flash-stm32f407 2 | =============== 3 | 4 | A ChibiOS/RT based library providing read/write operations on the STM32F407 flash memory. 5 | 6 | This work is greatly inspired by mabl's bootloader example at: 7 | https://github.com/mabl/ARMCM3-STM32F107-BOOTLOADER 8 | 9 | An Intel HEX file parser is provided (written by Vanya A. Sergeev ) 10 | with a helper function to flash an IHex file from FatFS into flash memory. 11 | 12 | -------------------------------------------------------------------------------- /flash/flash.c: -------------------------------------------------------------------------------- 1 | 2 | #include "flash.h" 3 | #include 4 | 5 | size_t flashSectorSize(flashsector_t sector) 6 | { 7 | if (sector >= 0 && sector <= 3) 8 | return 16 * 1024; 9 | else if (sector == 4) 10 | return 64 * 1024; 11 | else if (sector >= 5 && sector <= 11) 12 | return 128 * 1024; 13 | return 0; 14 | } 15 | 16 | flashaddr_t flashSectorBegin(flashsector_t sector) 17 | { 18 | flashaddr_t address = FLASH_BASE; 19 | while (sector > 0) 20 | { 21 | --sector; 22 | address += flashSectorSize(sector); 23 | } 24 | return address; 25 | } 26 | 27 | flashaddr_t flashSectorEnd(flashsector_t sector) 28 | { 29 | return flashSectorBegin(sector + 1); 30 | } 31 | 32 | flashsector_t flashSectorAt(flashaddr_t address) 33 | { 34 | flashsector_t sector = 0; 35 | while (address >= flashSectorEnd(sector)) 36 | ++sector; 37 | return sector; 38 | } 39 | 40 | /** 41 | * @brief Wait for the flash operation to finish. 42 | */ 43 | #define flashWaitWhileBusy() { while (FLASH->SR & FLASH_SR_BSY) {} } 44 | 45 | /** 46 | * @brief Unlock the flash memory for write access. 47 | * @return CH_SUCCESS Unlock was successful. 48 | * @return CH_FAILED Unlock failed. 49 | */ 50 | static bool_t flashUnlock() 51 | { 52 | /* Check if unlock is really needed */ 53 | if (!(FLASH->CR & FLASH_CR_LOCK)) 54 | return CH_SUCCESS; 55 | 56 | /* Write magic unlock sequence */ 57 | FLASH->KEYR = 0x45670123; 58 | FLASH->KEYR = 0xCDEF89AB; 59 | 60 | /* Check if unlock was successful */ 61 | if (FLASH->CR & FLASH_CR_LOCK) 62 | return CH_FAILED; 63 | return CH_SUCCESS; 64 | } 65 | 66 | /** 67 | * @brief Lock the flash memory for write access. 68 | */ 69 | #define flashLock() { FLASH->CR |= FLASH_CR_LOCK; } 70 | 71 | int flashSectorErase(flashsector_t sector) 72 | { 73 | /* Unlock flash for write access */ 74 | if(flashUnlock() == CH_FAILED) 75 | return FLASH_RETURN_NO_PERMISSION; 76 | 77 | /* Wait for any busy flags. */ 78 | flashWaitWhileBusy(); 79 | 80 | /* Setup parallelism before any program/erase */ 81 | FLASH->CR &= ~FLASH_CR_PSIZE_MASK; 82 | FLASH->CR |= FLASH_CR_PSIZE_VALUE; 83 | 84 | /* Start deletion of sector. 85 | * SNB(3:1) is defined as: 86 | * 0000 sector 0 87 | * 0001 sector 1 88 | * ... 89 | * 1011 sector 11 90 | * others not allowed */ 91 | FLASH->CR &= ~(FLASH_CR_SNB_0 | FLASH_CR_SNB_1 | FLASH_CR_SNB_2 | FLASH_CR_SNB_3); 92 | if (sector & 0x1) FLASH->CR |= FLASH_CR_SNB_0; 93 | if (sector & 0x2) FLASH->CR |= FLASH_CR_SNB_1; 94 | if (sector & 0x4) FLASH->CR |= FLASH_CR_SNB_2; 95 | if (sector & 0x8) FLASH->CR |= FLASH_CR_SNB_3; 96 | FLASH->CR |= FLASH_CR_SER; 97 | FLASH->CR |= FLASH_CR_STRT; 98 | 99 | /* Wait until it's finished. */ 100 | flashWaitWhileBusy(); 101 | 102 | /* Sector erase flag does not clear automatically. */ 103 | FLASH->CR &= ~FLASH_CR_SER; 104 | 105 | /* Lock flash again */ 106 | flashLock(); 107 | 108 | /* Check deleted sector for errors */ 109 | if (flashIsErased(flashSectorBegin(sector), flashSectorSize(sector)) == FALSE) 110 | return FLASH_RETURN_BAD_FLASH; /* Sector is not empty despite the erase cycle! */ 111 | 112 | /* Successfully deleted sector */ 113 | return FLASH_RETURN_SUCCESS; 114 | } 115 | 116 | int flashErase(flashaddr_t address, size_t size) 117 | { 118 | while (size > 0) 119 | { 120 | flashsector_t sector = flashSectorAt(address); 121 | int err = flashSectorErase(sector); 122 | if (err != FLASH_RETURN_SUCCESS) 123 | return err; 124 | address = flashSectorEnd(sector); 125 | size_t sector_size = flashSectorSize(sector); 126 | if (sector_size >= size) 127 | break; 128 | else 129 | size -= sector_size; 130 | } 131 | 132 | return FLASH_RETURN_SUCCESS; 133 | } 134 | 135 | bool_t flashIsErased(flashaddr_t address, size_t size) 136 | { 137 | /* Check for default set bits in the flash memory 138 | * For efficiency, compare flashdata_t values as much as possible, 139 | * then, fallback to byte per byte comparison. */ 140 | while (size >= sizeof(flashdata_t)) 141 | { 142 | if (*(volatile flashdata_t*)address != (flashdata_t)(-1)) // flashdata_t being unsigned, -1 is 0xFF..FF 143 | return FALSE; 144 | address += sizeof(flashdata_t); 145 | size -= sizeof(flashdata_t); 146 | } 147 | while (size > 0) 148 | { 149 | if (*(char*)address != 0xff) 150 | return FALSE; 151 | ++address; 152 | --size; 153 | } 154 | 155 | return TRUE; 156 | } 157 | 158 | bool_t flashCompare(flashaddr_t address, const char* buffer, size_t size) 159 | { 160 | /* For efficiency, compare flashdata_t values as much as possible, 161 | * then, fallback to byte per byte comparison. */ 162 | while (size >= sizeof(flashdata_t)) 163 | { 164 | if (*(volatile flashdata_t*)address != *(flashdata_t*)buffer) 165 | return FALSE; 166 | address += sizeof(flashdata_t); 167 | buffer += sizeof(flashdata_t); 168 | size -= sizeof(flashdata_t); 169 | } 170 | while (size > 0) 171 | { 172 | if (*(volatile char*)address != *buffer) 173 | return FALSE; 174 | ++address; 175 | ++buffer; 176 | --size; 177 | } 178 | 179 | return TRUE; 180 | } 181 | 182 | int flashRead(flashaddr_t address, char* buffer, size_t size) 183 | { 184 | memcpy(buffer, (char*)address, size); 185 | return FLASH_RETURN_SUCCESS; 186 | } 187 | 188 | static void flashWriteData(flashaddr_t address, const flashdata_t data) 189 | { 190 | /* Enter flash programming mode */ 191 | FLASH->CR |= FLASH_CR_PG; 192 | 193 | /* Write the data */ 194 | *(flashdata_t*)address = data; 195 | 196 | /* Wait for completion */ 197 | flashWaitWhileBusy(); 198 | 199 | /* Exit flash programming mode */ 200 | FLASH->CR &= ~FLASH_CR_PG; 201 | } 202 | 203 | int flashWrite(flashaddr_t address, const char* buffer, size_t size) 204 | { 205 | /* Unlock flash for write access */ 206 | if(flashUnlock() == CH_FAILED) 207 | return FLASH_RETURN_NO_PERMISSION; 208 | 209 | /* Wait for any busy flags */ 210 | flashWaitWhileBusy(); 211 | 212 | /* Setup parallelism before any program/erase */ 213 | FLASH->CR &= ~FLASH_CR_PSIZE_MASK; 214 | FLASH->CR |= FLASH_CR_PSIZE_VALUE; 215 | 216 | /* Check if the flash address is correctly aligned */ 217 | size_t alignOffset = address % sizeof(flashdata_t); 218 | if (alignOffset != 0) 219 | { 220 | /* Not aligned, thus we have to read the data in flash already present 221 | * and update them with buffer's data */ 222 | 223 | /* Align the flash address correctly */ 224 | flashaddr_t alignedFlashAddress = address - alignOffset; 225 | 226 | /* Read already present data */ 227 | flashdata_t tmp = *(volatile flashdata_t*)alignedFlashAddress; 228 | 229 | /* Compute how much bytes one must update in the data read */ 230 | size_t chunkSize = sizeof(flashdata_t) - alignOffset; 231 | if (chunkSize > size) 232 | chunkSize = size; // this happens when both address and address + size are not aligned 233 | 234 | /* Update the read data with buffer's data */ 235 | memcpy((char*)&tmp + alignOffset, buffer, chunkSize); 236 | 237 | /* Write the new data in flash */ 238 | flashWriteData(alignedFlashAddress, tmp); 239 | 240 | /* Advance */ 241 | address += chunkSize; 242 | buffer += chunkSize; 243 | size -= chunkSize; 244 | } 245 | 246 | /* Now, address is correctly aligned. One can copy data directly from 247 | * buffer's data to flash memory until the size of the data remaining to be 248 | * copied requires special treatment. */ 249 | while (size >= sizeof(flashdata_t)) 250 | { 251 | flashWriteData(address, *(const flashdata_t*)buffer); 252 | address += sizeof(flashdata_t); 253 | buffer += sizeof(flashdata_t); 254 | size -= sizeof(flashdata_t); 255 | } 256 | 257 | /* Now, address is correctly aligned, but the remaining data are to 258 | * small to fill a entier flashdata_t. Thus, one must read data already 259 | * in flash and update them with buffer's data before writing an entire 260 | * flashdata_t to flash memory. */ 261 | if (size > 0) 262 | { 263 | flashdata_t tmp = *(volatile flashdata_t*)address; 264 | memcpy(&tmp, buffer, size); 265 | flashWriteData(address, tmp); 266 | } 267 | 268 | /* Lock flash again */ 269 | flashLock(); 270 | 271 | return FLASH_RETURN_SUCCESS; 272 | } 273 | -------------------------------------------------------------------------------- /flash/flash.cmake: -------------------------------------------------------------------------------- 1 | get_filename_component(FLASH_SOURCE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) 2 | 3 | # add an option to enable or disable IHEX specific functions 4 | option(FLASH_USE_IHEX "TRUE to enable the ihex functions, FALSE to exclude them from the build" FALSE) 5 | 6 | set(FLASH_SRCS 7 | ${FLASH_SOURCE_DIR}/flash.h ${FLASH_SOURCE_DIR}/flash.c 8 | ${FLASH_SOURCE_DIR}/helper.h ${FLASH_SOURCE_DIR}/helper.c 9 | ) 10 | 11 | if(FLASH_USE_IHEX) 12 | set(FLASH_SRCS ${FLASH_SRCS} 13 | ${FLASH_SOURCE_DIR}/ihex.h ${FLASH_SOURCE_DIR}/ihex.c 14 | ${FLASH_SOURCE_DIR}/ihexhelper.h ${FLASH_SOURCE_DIR}/ihexhelper.c 15 | ) 16 | endif() 17 | -------------------------------------------------------------------------------- /flash/flash.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef FLASH_H 3 | #define FLASH_H 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | /** 10 | * @brief Number of sectors in the flash memory. 11 | */ 12 | #if !defined(FLASH_SECTOR_COUNT) || defined(__DOXYGEN__) 13 | #define FLASH_SECTOR_COUNT 12 14 | #endif 15 | 16 | /* Error codes */ 17 | 18 | /** @brief Flash operation successful */ 19 | #define FLASH_RETURN_SUCCESS CH_SUCCESS 20 | 21 | /** @brief Flash operation error because of denied access, corrupted memory.*/ 22 | #define FLASH_RETURN_NO_PERMISSION -1 23 | 24 | /** @brief Flash operation error because of bad flash, corrupted memory */ 25 | #define FLASH_RETURN_BAD_FLASH -11 26 | 27 | #ifdef __cplusplus 28 | extern "C" { 29 | #endif 30 | 31 | /** 32 | * @brief Maximum program/erase parallelism 33 | * 34 | * FLASH_CR_PSIZE_MASK is the mask to configure the parallelism value. 35 | * FLASH_CR_PSIZE_VALUE is the parallelism value suitable for the voltage range. 36 | * 37 | * PSIZE(1:0) is defined as: 38 | * 00 to program 8 bits per step 39 | * 01 to program 16 bits per step 40 | * 10 to program 32 bits per step 41 | * 11 to program 64 bits per step 42 | */ 43 | // Warning, flashdata_t must be unsigned!!! 44 | #if defined(STM32F4XX) || defined(__DOXYGEN__) 45 | #define FLASH_CR_PSIZE_MASK FLASH_CR_PSIZE_0 | FLASH_CR_PSIZE_1 46 | #if ((STM32_VDD >= 270) && (STM32_VDD <= 360)) || defined(__DOXYGEN__) 47 | #define FLASH_CR_PSIZE_VALUE FLASH_CR_PSIZE_1 48 | typedef uint32_t flashdata_t; 49 | #elif (STM32_VDD >= 240) && (STM32_VDD < 270) 50 | #define FLASH_CR_PSIZE_VALUE FLASH_CR_PSIZE_0 51 | typedef uint16_t flashdata_t; 52 | #elif (STM32_VDD >= 210) && (STM32_VDD < 240) 53 | #define FLASH_CR_PSIZE_VALUE FLASH_CR_PSIZE_0 54 | typedef uint16_t flashdata_t; 55 | #elif (STM32_VDD >= 180) && (STM32_VDD < 210) 56 | #define FLASH_CR_PSIZE_VALUE ((uint32_t)0x00000000) 57 | typedef uint8_t flashdata_t; 58 | #else 59 | #error "invalid VDD voltage specified" 60 | #endif 61 | #endif /* defined(STM32F4XX) */ 62 | 63 | /** @brief Address in the flash memory */ 64 | typedef uintptr_t flashaddr_t; 65 | 66 | /** @brief Index of a sector */ 67 | typedef uint8_t flashsector_t; 68 | 69 | /** 70 | * @brief Get the size of @p sector. 71 | * @return @p sector size in bytes. 72 | */ 73 | size_t flashSectorSize(flashsector_t sector); 74 | 75 | /** 76 | * @brief Get the beginning address of @p sector. 77 | * @param sector Sector to retrieve the beginning address of. 78 | * @return First address (inclusive) of @p sector. 79 | */ 80 | flashaddr_t flashSectorBegin(flashsector_t sector); 81 | 82 | /** 83 | * @brief Get the end address of @p sector. 84 | * @param sector Sector to retrieve the end address of. 85 | * @return End address (exclusive) of @p sector (i.e. beginning address of the next sector). 86 | */ 87 | flashaddr_t flashSectorEnd(flashsector_t sector); 88 | 89 | /** 90 | * @brief Get the sector containing @p address. 91 | * @warning @p address must be in the flash addresses range. 92 | * @param address Address to be searched for. 93 | * @return Sector containing @p address. 94 | */ 95 | flashsector_t flashSectorAt(flashaddr_t address); 96 | 97 | /** 98 | * @brief Erase the flash @p sector. 99 | * @details The sector is checked for errors after erase. 100 | * @note The sector is deleted regardless of its current state. 101 | * 102 | * @param sector Sector which is going to be erased. 103 | * @return FLASH_RETURN_SUCCESS No error erasing the sector. 104 | * @return FLASH_RETURN_BAD_FLASH Flash cell error. 105 | * @return FLASH_RETURN_NO_PERMISSION Access denied. 106 | */ 107 | int flashSectorErase(flashsector_t sector); 108 | 109 | /** 110 | * @brief Erase the sectors containing the span of @p size bytes starting at @p address. 111 | * 112 | * @warning If @p address doesn't match the beginning of a sector, the 113 | * data contained between the beginning of the sector and @p address will 114 | * be erased too. The same applies for data contained at @p address + @p size 115 | * up to the end of the sector. 116 | * 117 | * @param address Starting address of the span in flash memory. 118 | * @param size Size of the span in bytes. 119 | * @return FLASH_RETURN_SUCCESS No error erasing the flash memory. 120 | * @return FLASH_RETURN_BAD_FLASH Flash cell error. 121 | * @return FLASH_RETURN_NO_PERMISSION Access denied. 122 | */ 123 | int flashErase(flashaddr_t address, size_t size); 124 | 125 | /** 126 | * @brief Check if the @p size bytes of flash memory starting at @p address are erased. 127 | * @note If the memory is erased, one can write data into it safely. 128 | * @param address First address in flash memory to be checked. 129 | * @param size Size of the memory space to be checked in bytes. 130 | * @return TRUE Memory is already erased. 131 | * @return FALSE Memory is not erased. 132 | */ 133 | bool_t flashIsErased(flashaddr_t address, size_t size); 134 | 135 | /** 136 | * @brief Check if the data in @p buffer are identical to the one in flash memory. 137 | * @param address First address in flash memory to be checked. 138 | * @param buffer Buffer containing the data to compare. 139 | * @param size Size of @p buffer in bytes. 140 | * @return TRUE if the flash memory and the buffer contain identical data. 141 | * @return FALSE if the flash memory and the buffer don't contain identical data. 142 | */ 143 | bool_t flashCompare(flashaddr_t address, const char* buffer, size_t size); 144 | 145 | /** 146 | * @brief Copy data from the flash memory to a @p buffer. 147 | * @warning The @p buffer must be at least @p size bytes long. 148 | * @param address First address of the flash memory to be copied. 149 | * @param buffer Buffer to copy to. 150 | * @param size Size of the data to be copied in bytes. 151 | * @return FLASH_RETURN_SUCCESS if successfully copied. 152 | */ 153 | int flashRead(flashaddr_t address, char* buffer, size_t size); 154 | 155 | /** 156 | * @brief Copy data from a @p buffer to the flash memory. 157 | * @warning The flash memory area receiving the data must be erased. 158 | * @warning The @p buffer must be at least @p size bytes long. 159 | * @param address First address in the flash memory where to copy the data to. 160 | * @param buffer Buffer containing the data to copy. 161 | * @param size Size of the data to be copied in bytes. 162 | * @return FLASH_RETURN_SUCCESS No error. 163 | * @return FLASH_RETURN_NO_PERMISSION Access denied. 164 | */ 165 | int flashWrite(flashaddr_t address, const char* buffer, size_t size); 166 | 167 | #ifdef __cplusplus 168 | } 169 | #endif 170 | 171 | #endif /* FLASH_H */ 172 | -------------------------------------------------------------------------------- /flash/helper.c: -------------------------------------------------------------------------------- 1 | 2 | #include "helper.h" 3 | #include "flash.h" 4 | #include 5 | #include 6 | #include 7 | 8 | void flashJumpApplication(uint32_t address) 9 | { 10 | typedef void (*funcPtr)(void); 11 | 12 | u32 jumpAddr = *(vu32*)(address + 0x04); /* reset ptr in vector table */ 13 | funcPtr usrMain = (funcPtr)jumpAddr; 14 | 15 | /* Reset all interrupts to default */ 16 | chSysDisable(); 17 | 18 | /* Clear pending interrupts just to be on the save side */ 19 | SCB_ICSR = ICSR_PENDSVCLR; 20 | 21 | /* Disable all interrupts */ 22 | int i; 23 | for(i = 0; i < 8; ++i) 24 | NVIC->ICER[i] = NVIC->IABR[i]; 25 | 26 | /* Set stack pointer as in application's vector table */ 27 | __set_MSP(*(vu32*)address); 28 | usrMain(); 29 | } 30 | -------------------------------------------------------------------------------- /flash/helper.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef HELPER_H 3 | #define HELPER_H 4 | 5 | #include 6 | #include 7 | 8 | #define BOOTLOADER_SUCCESS 0 9 | #define BOOTLOADER_ERROR_NOCARD 1 10 | #define BOOTLOADER_ERROR_BADFS 2 11 | #define BOOTLOADER_ERROR_NOFILE 3 12 | #define BOOTLOADER_ERROR_READFAILURE 4 13 | #define BOOTLOADER_ERROR_BADHEX 5 14 | #define BOOTLOADER_ERROR_BADFLASH 6 15 | 16 | /** 17 | * @brief Jump to application located in flash. 18 | * @param address Address to jump to. 19 | * 20 | * @author Code stolen from "matis" 21 | * @link http://forum.chibios.org/phpbb/viewtopic.php?f=2&t=338 22 | */ 23 | void flashJumpApplication(uint32_t address); 24 | 25 | #endif /* HELPER_H */ 26 | -------------------------------------------------------------------------------- /flash/ihex.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ihex.c 3 | * Utility functions to create, read, write, and print Intel HEX8 binary records. 4 | * 5 | * Written by Vanya A. Sergeev 6 | * Version 1.0.5 - February 2011 7 | * 8 | */ 9 | 10 | #include "ihex.h" 11 | 12 | /* Initializes a new IHexRecord structure that the paramater ihexRecord points to with the passed 13 | * record type, 16-bit integer address, 8-bit data array, and size of 8-bit data array. */ 14 | int New_IHexRecord(int type, uint16_t address, const uint8_t *data, int dataLen, 15 | IHexRecord *ihexRecord) { 16 | /* Data length size check, assertion of ihexRecord pointer */ 17 | if (dataLen < 0 || dataLen > IHEX_MAX_DATA_LEN / 2 || ihexRecord == NULL) 18 | return IHEX_ERROR_INVALID_ARGUMENTS; 19 | 20 | ihexRecord->type = type; 21 | ihexRecord->address = address; 22 | memcpy(ihexRecord->data, data, dataLen); 23 | ihexRecord->dataLen = dataLen; 24 | ihexRecord->checksum = Checksum_IHexRecord(ihexRecord); 25 | 26 | return IHEX_OK; 27 | } 28 | 29 | /* Utility function to read an Intel HEX8 record from a FIL */ 30 | int Read_IHexRecord(IHexRecord *ihexRecord, FIL *in) { 31 | char recordBuff[IHEX_RECORD_BUFF_SIZE]; 32 | /* A temporary buffer to hold ASCII hex encoded data, set to the maximum length we would ever need */ 33 | char hexBuff[IHEX_ADDRESS_LEN + 1]; 34 | int dataCount, i; 35 | 36 | /* Check our record pointer and FIL pointer */ 37 | if (ihexRecord == NULL || in == NULL) 38 | return IHEX_ERROR_INVALID_ARGUMENTS; 39 | 40 | if (f_gets(recordBuff, IHEX_RECORD_BUFF_SIZE, in) == NULL) { 41 | /* In case we hit EOF, don't report a FIL error */ 42 | if (f_eof(in) != 0) 43 | return IHEX_ERROR_EOF; 44 | else 45 | return IHEX_ERROR_FILE; 46 | } 47 | /* Null-terminate the string at the first sign of a \r or \n */ 48 | for (i = 0; i < (int) strlen(recordBuff); i++) { 49 | if (recordBuff[i] == '\r' || recordBuff[i] == '\n') { 50 | recordBuff[i] = 0; 51 | break; 52 | } 53 | } 54 | 55 | /* Check if we hit a newline */ 56 | if (strlen(recordBuff) == 0) 57 | return IHEX_ERROR_NEWLINE; 58 | 59 | /* Size check for start code, count, addess, and type fields */ 60 | if (strlen(recordBuff) 61 | < (unsigned int) (1 + IHEX_COUNT_LEN + IHEX_ADDRESS_LEN + IHEX_TYPE_LEN)) 62 | return IHEX_ERROR_INVALID_RECORD; 63 | 64 | /* Check the for colon start code */ 65 | if (recordBuff[IHEX_START_CODE_OFFSET] != IHEX_START_CODE) 66 | return IHEX_ERROR_INVALID_RECORD; 67 | 68 | /* Copy the ASCII hex encoding of the count field into hexBuff, convert it to a usable integer */ 69 | strncpy(hexBuff, recordBuff + IHEX_COUNT_OFFSET, IHEX_COUNT_LEN); 70 | hexBuff[IHEX_COUNT_LEN] = 0; 71 | dataCount = strtol(hexBuff, (char **) NULL, 16); 72 | 73 | /* Copy the ASCII hex encoding of the address field into hexBuff, convert it to a usable integer */ 74 | strncpy(hexBuff, recordBuff + IHEX_ADDRESS_OFFSET, IHEX_ADDRESS_LEN); 75 | hexBuff[IHEX_ADDRESS_LEN] = 0; 76 | ihexRecord->address = (uint16_t) strtol(hexBuff, (char **) NULL, 16); 77 | 78 | /* Copy the ASCII hex encoding of the address field into hexBuff, convert it to a usable integer */ 79 | strncpy(hexBuff, recordBuff + IHEX_TYPE_OFFSET, IHEX_TYPE_LEN); 80 | hexBuff[IHEX_TYPE_LEN] = 0; 81 | ihexRecord->type = strtol(hexBuff, (char **) NULL, 16); 82 | 83 | /* Size check for start code, count, address, type, data and checksum fields */ 84 | if (strlen(recordBuff) 85 | < (unsigned int) (1 + IHEX_COUNT_LEN + IHEX_ADDRESS_LEN + IHEX_TYPE_LEN 86 | + dataCount * 2 + IHEX_CHECKSUM_LEN)) 87 | return IHEX_ERROR_INVALID_RECORD; 88 | 89 | /* Loop through each ASCII hex byte of the data field, pull it out into hexBuff, 90 | * convert it and store the result in the data buffer of the Intel HEX8 record */ 91 | for (i = 0; i < dataCount; i++) { 92 | /* Times two i because every byte is represented by two ASCII hex characters */ 93 | strncpy(hexBuff, recordBuff + IHEX_DATA_OFFSET + 2 * i, 94 | IHEX_ASCII_HEX_BYTE_LEN); 95 | hexBuff[IHEX_ASCII_HEX_BYTE_LEN] = 0; 96 | ihexRecord->data[i] = (uint8_t) strtol(hexBuff, (char **) NULL, 16); 97 | } 98 | ihexRecord->dataLen = dataCount; 99 | 100 | /* Copy the ASCII hex encoding of the checksum field into hexBuff, convert it to a usable integer */ 101 | strncpy(hexBuff, recordBuff + IHEX_DATA_OFFSET + dataCount * 2, 102 | IHEX_CHECKSUM_LEN); 103 | hexBuff[IHEX_CHECKSUM_LEN] = 0; 104 | ihexRecord->checksum = (uint8_t) strtol(hexBuff, (char **) NULL, 16); 105 | 106 | if (ihexRecord->checksum != Checksum_IHexRecord(ihexRecord)) 107 | return IHEX_ERROR_INVALID_RECORD; 108 | 109 | return IHEX_OK; 110 | } 111 | 112 | /* Utility function to calculate the checksum of an Intel HEX8 record */ 113 | uint8_t Checksum_IHexRecord(const IHexRecord *ihexRecord) { 114 | uint8_t checksum; 115 | int i; 116 | 117 | /* Add the data count, type, address, and data bytes together */ 118 | checksum = ihexRecord->dataLen; 119 | checksum += ihexRecord->type; 120 | checksum += (uint8_t) ihexRecord->address; 121 | checksum += (uint8_t) ((ihexRecord->address & 0xFF00) >> 8); 122 | for (i = 0; i < ihexRecord->dataLen; i++) 123 | checksum += ihexRecord->data[i]; 124 | 125 | /* Two's complement on checksum */ 126 | checksum = ~checksum + 1; 127 | 128 | return checksum; 129 | } 130 | 131 | -------------------------------------------------------------------------------- /flash/ihex.h: -------------------------------------------------------------------------------- 1 | #ifndef INTEL_HEX_H 2 | #define INTEL_HEX_H 3 | /** 4 | * \file ihex.h 5 | * \brief Low-level utility functions to create, read, write, and print Intel HEX8 binary records. 6 | * \author Vanya A. Sergeev 7 | * \date February 2011 8 | * \version 1.0.5 9 | */ 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | 17 | /* General definition of the Intel HEX8 specification */ 18 | enum _IHexDefinitions { 19 | /* 768 should be plenty of space to read in a Intel HEX8 record */ 20 | IHEX_RECORD_BUFF_SIZE = 768, 21 | /* Offsets and lengths of various fields in an Intel HEX8 record */ 22 | IHEX_COUNT_OFFSET = 1, 23 | IHEX_COUNT_LEN = 2, 24 | IHEX_ADDRESS_OFFSET = 3, 25 | IHEX_ADDRESS_LEN = 4, 26 | IHEX_TYPE_OFFSET = 7, 27 | IHEX_TYPE_LEN = 2, 28 | IHEX_DATA_OFFSET = 9, 29 | IHEX_CHECKSUM_LEN = 2, 30 | IHEX_MAX_DATA_LEN = 512, 31 | /* Ascii hex encoded length of a single byte */ 32 | IHEX_ASCII_HEX_BYTE_LEN = 2, 33 | /* Start code offset and value */ 34 | IHEX_START_CODE_OFFSET = 0, 35 | IHEX_START_CODE = ':', 36 | }; 37 | 38 | /** 39 | * All possible error codes the Intel HEX8 record utility functions may return. 40 | */ 41 | enum IHexErrors { 42 | IHEX_OK = 0, /**< Error code for success or no error. */ 43 | IHEX_ERROR_FILE = -1, /**< Error code for error while reading from or writing to a file. You may check errno for the exact error if this error code is encountered. */ 44 | IHEX_ERROR_EOF = -2, /**< Error code for encountering end-of-file when reading from a file. */ 45 | IHEX_ERROR_INVALID_RECORD = -3, /**< Error code for error if an invalid record was read. */ 46 | IHEX_ERROR_INVALID_ARGUMENTS = -4, /**< Error code for error from invalid arguments passed to function. */ 47 | IHEX_ERROR_NEWLINE = -5, /**< Error code for encountering a newline with no record when reading from a file. */ 48 | }; 49 | 50 | /** 51 | * Intel HEX8 Record Types 00-05 52 | */ 53 | enum IHexRecordTypes { 54 | IHEX_TYPE_00 = 0, /**< Data Record */ 55 | IHEX_TYPE_01, /**< End of FIL Record */ 56 | IHEX_TYPE_02, /**< Extended Segment Address Record */ 57 | IHEX_TYPE_03, /**< Start Segment Address Record */ 58 | IHEX_TYPE_04, /**< Extended Linear Address Record */ 59 | IHEX_TYPE_05, /**< Start Linear Address Record */ 60 | }; 61 | 62 | /** 63 | * Structure to hold the fields of an Intel HEX8 record. 64 | */ 65 | typedef struct { 66 | uint16_t address; /**< The 16-bit address field. */ 67 | uint8_t data[IHEX_MAX_DATA_LEN/2]; /**< The 8-bit array data field, which has a maximum size of 256 bytes. */ 68 | int dataLen; /**< The number of bytes of data stored in this record. */ 69 | int type; /**< The Intel HEX8 record type of this record. */ 70 | uint8_t checksum; /**< The checksum of this record. */ 71 | } IHexRecord; 72 | 73 | /** 74 | * Sets all of the record fields of an Intel HEX8 record structure. 75 | * \param type The Intel HEX8 record type (integer value of 0 through 5). 76 | * \param address The 16-bit address of the data. 77 | * \param data A point to the 8-bit array of data. 78 | * \param dataLen The size of the 8-bit data array. 79 | * \param ihexRecord A pointer to the target Intel HEX8 record structure where these fields will be set. 80 | * \return IHEX_OK on success, otherwise one of the IHEX_ERROR_ error codes. 81 | * \retval IHEX_OK on success. 82 | * \retval IHEX_ERROR_INVALID_ARGUMENTS if the record pointer is NULL, or if the length of the 8-bit data array is out of range (less than zero or greater than the maximum data length allowed by record specifications, see IHexRecord.data). 83 | */ 84 | int New_IHexRecord(int type, uint16_t address, const uint8_t *data, int dataLen, IHexRecord *ihexRecord); 85 | 86 | /** 87 | * Reads an Intel HEX8 record from an opened file. 88 | * \param ihexRecord A pointer to the Intel HEX8 record structure that will store the read record. 89 | * \param in A FIL pointer to an opened FIL that can be read. 90 | * \return IHEX_OK on success, otherwise one of the IHEX_ERROR_ error codes. 91 | * \retval IHEX_OK on success. 92 | * \retval IHEX_ERROR_INVALID_ARGUMENTS if the record pointer or FIL pointer is NULL. 93 | * \retval IHEX_ERROR_EOF if end-of-file has been reached. 94 | * \retval IHEX_ERROR_FILE if a FIL reading error has occured. 95 | * \retval IHEX_INVALID_RECORD if the record read is invalid (record did not match specifications or record checksum was invalid). 96 | */ 97 | int Read_IHexRecord(IHexRecord *ihexRecord, FIL *in); 98 | 99 | /** 100 | * Calculates the checksum of an Intel HEX8 IHexRecord structure. 101 | * See the Intel HEX8 specifications for more details on the checksum calculation. 102 | * \param ihexRecord A pointer to the Intel HEX8 record structure. 103 | * \return The 8-bit checksum. 104 | */ 105 | uint8_t Checksum_IHexRecord(const IHexRecord *ihexRecord); 106 | 107 | #endif 108 | -------------------------------------------------------------------------------- /flash/ihexhelper.c: -------------------------------------------------------------------------------- 1 | 2 | #include "ihexhelper.h" 3 | #include "ihex.h" 4 | #include "flash.h" 5 | 6 | int flashIHexFile(FIL* file) 7 | { 8 | IHexRecord irec; 9 | flashsector_t sector; 10 | bool_t erasedSectors[FLASH_SECTOR_COUNT] = { FALSE }; 11 | flashaddr_t baseAddress = 0; 12 | flashaddr_t address = 0; 13 | 14 | while (Read_IHexRecord(&irec, file) == IHEX_OK) 15 | { 16 | switch (irec.type) 17 | { 18 | case IHEX_TYPE_00: /**< Data Record */ 19 | /* Compute the target address in flash */ 20 | address = baseAddress + irec.address; 21 | 22 | /* Erase the corresponding addresses if needed */ 23 | for (sector = flashSectorAt(address); sector <= flashSectorAt(address + irec.dataLen - 1); ++sector) 24 | { 25 | /* Check if the sector has been erased during this IHex flashing procedure to 26 | prevent erasing already written data */ 27 | if (erasedSectors[sector] == TRUE) 28 | continue; 29 | 30 | /* Check if the sector in flash needs to be erased */ 31 | if (flashIsErased(flashSectorBegin(sector), flashSectorSize(sector)) == FALSE) 32 | { 33 | /* Erase the sector */ 34 | if (flashSectorErase(sector) != FLASH_RETURN_SUCCESS) 35 | return BOOTLOADER_ERROR_BADFLASH; 36 | } 37 | 38 | /* Set the erased flag to prevent erasing the same sector twice during 39 | the IHex flashing procedure */ 40 | erasedSectors[sector] = TRUE; 41 | } 42 | 43 | /* Write the data in flash */ 44 | if (flashWrite(address, (const char*)irec.data, irec.dataLen) != FLASH_RETURN_SUCCESS) 45 | return BOOTLOADER_ERROR_BADFLASH; 46 | break; 47 | 48 | case IHEX_TYPE_04: /**< Extended Linear Address Record */ 49 | /* Compute the base address of the following data records */ 50 | baseAddress = irec.data[0]; 51 | baseAddress <<= 8; 52 | baseAddress += irec.data[1]; 53 | baseAddress <<= 16; 54 | break; 55 | 56 | case IHEX_TYPE_01: /**< End of File Record */ 57 | /* Check that the end of file record is at the end of the file... */ 58 | return f_eof(file) ? BOOTLOADER_SUCCESS : BOOTLOADER_ERROR_BADHEX; 59 | 60 | case IHEX_TYPE_05: /**< Start Linear Address Record */ 61 | /* Ignored */ 62 | break; 63 | 64 | case IHEX_TYPE_02: /**< Extended Segment Address Record */ 65 | case IHEX_TYPE_03: /**< Start Segment Address Record */ 66 | /* Not supported */ 67 | return BOOTLOADER_ERROR_BADHEX; 68 | } 69 | } 70 | 71 | return BOOTLOADER_ERROR_BADHEX; 72 | } 73 | -------------------------------------------------------------------------------- /flash/ihexhelper.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef IHEXHELPER_H 3 | #define IHEXHELPER_H 4 | 5 | #include "helper.h" 6 | #include 7 | #include 8 | 9 | /** 10 | * @brief Flash the provided IHex @p file. 11 | * @param file IHex file describing the data to be flashed. 12 | * @return BOOTLOADER_SUCCESS on success 13 | * @return BOOTLOADER_ERROR_BADFLASH if an error occured when manipulating the flash memory 14 | * @return BOOTLOADER_ERROR_BADHEX if an error occured when reading the iHex file 15 | */ 16 | int flashIHexFile(FIL* file); 17 | 18 | #endif /* IHEXHELPER_H */ 19 | -------------------------------------------------------------------------------- /openocd.cfg: -------------------------------------------------------------------------------- 1 | source [find interface/stlink-v2.cfg] 2 | source [find target/stm32f4x_stlink.cfg] 3 | init 4 | reset init 5 | reset 6 | #sleep 20000 7 | #dump_image /tmp/dump 0x08000000 1048576 8 | shutdown 9 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(flash-stm32f407-test) 2 | 3 | include(${CHIBIOS_ROOT}/tools/cmake/chibios.cmake) 4 | include(${CHIBIOS_ROOT}/tools/cmake/ext/chprintf.cmake) 5 | include(${CHIBIOS_ROOT}/tools/cmake/ext/fatfs.cmake) 6 | 7 | include_directories(${CMAKE_SOURCE_DIR}) 8 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}) 9 | 10 | include("../flash/flash.cmake") 11 | 12 | set(TEST_SRCS 13 | ${FLASH_SRCS} 14 | chconf.h 15 | halconf.h 16 | mcuconf.h 17 | ffconf.h 18 | test.c 19 | sdcard.h 20 | sdcard.c 21 | ) 22 | 23 | add_chibios_executable(flash-stm32f407-test ${TEST_SRCS}) 24 | add_flash_target(flash-stm32f407-test) 25 | -------------------------------------------------------------------------------- /test/chconf.h: -------------------------------------------------------------------------------- 1 | /* 2 | ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, 3 | 2011,2012 Giovanni Di Sirio. 4 | 5 | This file is part of ChibiOS/RT. 6 | 7 | ChibiOS/RT is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation; either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | ChibiOS/RT is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | 21 | /** 22 | * @file templates/chconf.h 23 | * @brief Configuration file template. 24 | * @details A copy of this file must be placed in each project directory, it 25 | * contains the application specific kernel settings. 26 | * 27 | * @addtogroup config 28 | * @details Kernel related settings and hooks. 29 | * @{ 30 | */ 31 | 32 | #ifndef _CHCONF_H_ 33 | #define _CHCONF_H_ 34 | 35 | /*===========================================================================*/ 36 | /** 37 | * @name Kernel parameters and options 38 | * @{ 39 | */ 40 | /*===========================================================================*/ 41 | 42 | /** 43 | * @brief System tick frequency. 44 | * @details Frequency of the system timer that drives the system ticks. This 45 | * setting also defines the system tick time unit. 46 | */ 47 | #if !defined(CH_FREQUENCY) || defined(__DOXYGEN__) 48 | #define CH_FREQUENCY 1000 49 | #endif 50 | 51 | /** 52 | * @brief Round robin interval. 53 | * @details This constant is the number of system ticks allowed for the 54 | * threads before preemption occurs. Setting this value to zero 55 | * disables the preemption for threads with equal priority and the 56 | * round robin becomes cooperative. Note that higher priority 57 | * threads can still preempt, the kernel is always preemptive. 58 | * 59 | * @note Disabling the round robin preemption makes the kernel more compact 60 | * and generally faster. 61 | */ 62 | #if !defined(CH_TIME_QUANTUM) || defined(__DOXYGEN__) 63 | #define CH_TIME_QUANTUM 0 64 | #endif 65 | 66 | /** 67 | * @brief Managed RAM size. 68 | * @details Size of the RAM area to be managed by the OS. If set to zero 69 | * then the whole available RAM is used. The core memory is made 70 | * available to the heap allocator and/or can be used directly through 71 | * the simplified core memory allocator. 72 | * 73 | * @note In order to let the OS manage the whole RAM the linker script must 74 | * provide the @p __heap_base__ and @p __heap_end__ symbols. 75 | * @note Requires @p CH_USE_MEMCORE. 76 | */ 77 | #if !defined(CH_MEMCORE_SIZE) || defined(__DOXYGEN__) 78 | #define CH_MEMCORE_SIZE 0 79 | #endif 80 | 81 | /** 82 | * @brief Idle thread automatic spawn suppression. 83 | * @details When this option is activated the function @p chSysInit() 84 | * does not spawn the idle thread automatically. The application has 85 | * then the responsibility to do one of the following: 86 | * - Spawn a custom idle thread at priority @p IDLEPRIO. 87 | * - Change the main() thread priority to @p IDLEPRIO then enter 88 | * an endless loop. In this scenario the @p main() thread acts as 89 | * the idle thread. 90 | * . 91 | * @note Unless an idle thread is spawned the @p main() thread must not 92 | * enter a sleep state. 93 | */ 94 | #if !defined(CH_NO_IDLE_THREAD) || defined(__DOXYGEN__) 95 | #define CH_NO_IDLE_THREAD FALSE 96 | #endif 97 | 98 | /** @} */ 99 | 100 | /*===========================================================================*/ 101 | /** 102 | * @name Performance options 103 | * @{ 104 | */ 105 | /*===========================================================================*/ 106 | 107 | /** 108 | * @brief OS optimization. 109 | * @details If enabled then time efficient rather than space efficient code 110 | * is used when two possible implementations exist. 111 | * 112 | * @note This is not related to the compiler optimization options. 113 | * @note The default is @p TRUE. 114 | */ 115 | #if !defined(CH_OPTIMIZE_SPEED) || defined(__DOXYGEN__) 116 | #define CH_OPTIMIZE_SPEED FALSE 117 | #endif 118 | 119 | /** @} */ 120 | 121 | /*===========================================================================*/ 122 | /** 123 | * @name Subsystem options 124 | * @{ 125 | */ 126 | /*===========================================================================*/ 127 | 128 | /** 129 | * @brief Threads registry APIs. 130 | * @details If enabled then the registry APIs are included in the kernel. 131 | * 132 | * @note The default is @p TRUE. 133 | */ 134 | #if !defined(CH_USE_REGISTRY) || defined(__DOXYGEN__) 135 | #define CH_USE_REGISTRY FALSE 136 | #endif 137 | 138 | /** 139 | * @brief Threads synchronization APIs. 140 | * @details If enabled then the @p chThdWait() function is included in 141 | * the kernel. 142 | * 143 | * @note The default is @p TRUE. 144 | */ 145 | #if !defined(CH_USE_WAITEXIT) || defined(__DOXYGEN__) 146 | #define CH_USE_WAITEXIT FALSE 147 | #endif 148 | 149 | /** 150 | * @brief Semaphores APIs. 151 | * @details If enabled then the Semaphores APIs are included in the kernel. 152 | * 153 | * @note The default is @p TRUE. 154 | */ 155 | #if !defined(CH_USE_SEMAPHORES) || defined(__DOXYGEN__) 156 | #define CH_USE_SEMAPHORES TRUE 157 | #endif 158 | 159 | /** 160 | * @brief Semaphores queuing mode. 161 | * @details If enabled then the threads are enqueued on semaphores by 162 | * priority rather than in FIFO order. 163 | * 164 | * @note The default is @p FALSE. Enable this if you have special requirements. 165 | * @note Requires @p CH_USE_SEMAPHORES. 166 | */ 167 | #if !defined(CH_USE_SEMAPHORES_PRIORITY) || defined(__DOXYGEN__) 168 | #define CH_USE_SEMAPHORES_PRIORITY FALSE 169 | #endif 170 | 171 | /** 172 | * @brief Atomic semaphore API. 173 | * @details If enabled then the semaphores the @p chSemSignalWait() API 174 | * is included in the kernel. 175 | * 176 | * @note The default is @p TRUE. 177 | * @note Requires @p CH_USE_SEMAPHORES. 178 | */ 179 | #if !defined(CH_USE_SEMSW) || defined(__DOXYGEN__) 180 | #define CH_USE_SEMSW FALSE 181 | #endif 182 | 183 | /** 184 | * @brief Mutexes APIs. 185 | * @details If enabled then the mutexes APIs are included in the kernel. 186 | * 187 | * @note The default is @p TRUE. 188 | */ 189 | #if !defined(CH_USE_MUTEXES) || defined(__DOXYGEN__) 190 | #define CH_USE_MUTEXES FALSE 191 | #endif 192 | 193 | /** 194 | * @brief Conditional Variables APIs. 195 | * @details If enabled then the conditional variables APIs are included 196 | * in the kernel. 197 | * 198 | * @note The default is @p TRUE. 199 | * @note Requires @p CH_USE_MUTEXES. 200 | */ 201 | #if !defined(CH_USE_CONDVARS) || defined(__DOXYGEN__) 202 | #define CH_USE_CONDVARS FALSE 203 | #endif 204 | 205 | /** 206 | * @brief Conditional Variables APIs with timeout. 207 | * @details If enabled then the conditional variables APIs with timeout 208 | * specification are included in the kernel. 209 | * 210 | * @note The default is @p TRUE. 211 | * @note Requires @p CH_USE_CONDVARS. 212 | */ 213 | #if !defined(CH_USE_CONDVARS_TIMEOUT) || defined(__DOXYGEN__) 214 | #define CH_USE_CONDVARS_TIMEOUT TRUE 215 | #endif 216 | 217 | /** 218 | * @brief Events Flags APIs. 219 | * @details If enabled then the event flags APIs are included in the kernel. 220 | * 221 | * @note The default is @p TRUE. 222 | */ 223 | #if !defined(CH_USE_EVENTS) || defined(__DOXYGEN__) 224 | #define CH_USE_EVENTS TRUE 225 | #endif 226 | 227 | /** 228 | * @brief Events Flags APIs with timeout. 229 | * @details If enabled then the events APIs with timeout specification 230 | * are included in the kernel. 231 | * 232 | * @note The default is @p TRUE. 233 | * @note Requires @p CH_USE_EVENTS. 234 | */ 235 | #if !defined(CH_USE_EVENTS_TIMEOUT) || defined(__DOXYGEN__) 236 | #define CH_USE_EVENTS_TIMEOUT TRUE 237 | #endif 238 | 239 | /** 240 | * @brief Synchronous Messages APIs. 241 | * @details If enabled then the synchronous messages APIs are included 242 | * in the kernel. 243 | * 244 | * @note The default is @p TRUE. 245 | */ 246 | #if !defined(CH_USE_MESSAGES) || defined(__DOXYGEN__) 247 | #define CH_USE_MESSAGES FALSE 248 | #endif 249 | 250 | /** 251 | * @brief Synchronous Messages queuing mode. 252 | * @details If enabled then messages are served by priority rather than in 253 | * FIFO order. 254 | * 255 | * @note The default is @p FALSE. Enable this if you have special requirements. 256 | * @note Requires @p CH_USE_MESSAGES. 257 | */ 258 | #if !defined(CH_USE_MESSAGES_PRIORITY) || defined(__DOXYGEN__) 259 | #define CH_USE_MESSAGES_PRIORITY FALSE 260 | #endif 261 | 262 | /** 263 | * @brief Mailboxes APIs. 264 | * @details If enabled then the asynchronous messages (mailboxes) APIs are 265 | * included in the kernel. 266 | * 267 | * @note The default is @p TRUE. 268 | * @note Requires @p CH_USE_SEMAPHORES. 269 | */ 270 | #if !defined(CH_USE_MAILBOXES) || defined(__DOXYGEN__) 271 | #define CH_USE_MAILBOXES FALSE 272 | #endif 273 | 274 | /** 275 | * @brief I/O Queues APIs. 276 | * @details If enabled then the I/O queues APIs are included in the kernel. 277 | * 278 | * @note The default is @p TRUE. 279 | */ 280 | #if !defined(CH_USE_QUEUES) || defined(__DOXYGEN__) 281 | #define CH_USE_QUEUES TRUE 282 | #endif 283 | 284 | /** 285 | * @brief Core Memory Manager APIs. 286 | * @details If enabled then the core memory manager APIs are included 287 | * in the kernel. 288 | * 289 | * @note The default is @p TRUE. 290 | */ 291 | #if !defined(CH_USE_MEMCORE) || defined(__DOXYGEN__) 292 | #define CH_USE_MEMCORE TRUE 293 | #endif 294 | 295 | /** 296 | * @brief Heap Allocator APIs. 297 | * @details If enabled then the memory heap allocator APIs are included 298 | * in the kernel. 299 | * 300 | * @note The default is @p TRUE. 301 | * @note Requires @p CH_USE_MEMCORE and either @p CH_USE_MUTEXES or 302 | * @p CH_USE_SEMAPHORES. 303 | * @note Mutexes are recommended. 304 | */ 305 | #if !defined(CH_USE_HEAP) || defined(__DOXYGEN__) 306 | #define CH_USE_HEAP TRUE 307 | #endif 308 | 309 | /** 310 | * @brief C-runtime allocator. 311 | * @details If enabled the the heap allocator APIs just wrap the C-runtime 312 | * @p malloc() and @p free() functions. 313 | * 314 | * @note The default is @p FALSE. 315 | * @note Requires @p CH_USE_HEAP. 316 | * @note The C-runtime may or may not require @p CH_USE_MEMCORE, see the 317 | * appropriate documentation. 318 | */ 319 | #if !defined(CH_USE_MALLOC_HEAP) || defined(__DOXYGEN__) 320 | #define CH_USE_MALLOC_HEAP FALSE 321 | #endif 322 | 323 | /** 324 | * @brief Memory Pools Allocator APIs. 325 | * @details If enabled then the memory pools allocator APIs are included 326 | * in the kernel. 327 | * 328 | * @note The default is @p TRUE. 329 | */ 330 | #if !defined(CH_USE_MEMPOOLS) || defined(__DOXYGEN__) 331 | #define CH_USE_MEMPOOLS TRUE 332 | #endif 333 | 334 | /** 335 | * @brief Dynamic Threads APIs. 336 | * @details If enabled then the dynamic threads creation APIs are included 337 | * in the kernel. 338 | * 339 | * @note The default is @p TRUE. 340 | * @note Requires @p CH_USE_WAITEXIT. 341 | * @note Requires @p CH_USE_HEAP and/or @p CH_USE_MEMPOOLS. 342 | */ 343 | #if !defined(CH_USE_DYNAMIC) || defined(__DOXYGEN__) 344 | #define CH_USE_DYNAMIC FALSE 345 | #endif 346 | 347 | /** @} */ 348 | 349 | /*===========================================================================*/ 350 | /** 351 | * @name Debug options 352 | * @{ 353 | */ 354 | /*===========================================================================*/ 355 | 356 | /** 357 | * @brief Debug option, system state check. 358 | * @details If enabled the correct call protocol for system APIs is checked 359 | * at runtime. 360 | * 361 | * @note The default is @p FALSE. 362 | */ 363 | #if !defined(CH_DBG_SYSTEM_STATE_CHECK) || defined(__DOXYGEN__) 364 | #define CH_DBG_SYSTEM_STATE_CHECK FALSE 365 | #endif 366 | 367 | /** 368 | * @brief Debug option, parameters checks. 369 | * @details If enabled then the checks on the API functions input 370 | * parameters are activated. 371 | * 372 | * @note The default is @p FALSE. 373 | */ 374 | #if !defined(CH_DBG_ENABLE_CHECKS) || defined(__DOXYGEN__) 375 | #define CH_DBG_ENABLE_CHECKS FALSE 376 | #endif 377 | 378 | /** 379 | * @brief Debug option, consistency checks. 380 | * @details If enabled then all the assertions in the kernel code are 381 | * activated. This includes consistency checks inside the kernel, 382 | * runtime anomalies and port-defined checks. 383 | * 384 | * @note The default is @p FALSE. 385 | */ 386 | #if !defined(CH_DBG_ENABLE_ASSERTS) || defined(__DOXYGEN__) 387 | #define CH_DBG_ENABLE_ASSERTS TRUE 388 | #endif 389 | 390 | /** 391 | * @brief Debug option, trace buffer. 392 | * @details If enabled then the context switch circular trace buffer is 393 | * activated. 394 | * 395 | * @note The default is @p FALSE. 396 | */ 397 | #if !defined(CH_DBG_ENABLE_TRACE) || defined(__DOXYGEN__) 398 | #define CH_DBG_ENABLE_TRACE FALSE 399 | #endif 400 | 401 | /** 402 | * @brief Debug option, stack checks. 403 | * @details If enabled then a runtime stack check is performed. 404 | * 405 | * @note The default is @p FALSE. 406 | * @note The stack check is performed in a architecture/port dependent way. 407 | * It may not be implemented or some ports. 408 | * @note The default failure mode is to halt the system with the global 409 | * @p panic_msg variable set to @p NULL. 410 | */ 411 | #if !defined(CH_DBG_ENABLE_STACK_CHECK) || defined(__DOXYGEN__) 412 | #define CH_DBG_ENABLE_STACK_CHECK FALSE 413 | #endif 414 | 415 | /** 416 | * @brief Debug option, stacks initialization. 417 | * @details If enabled then the threads working area is filled with a byte 418 | * value when a thread is created. This can be useful for the 419 | * runtime measurement of the used stack. 420 | * 421 | * @note The default is @p FALSE. 422 | */ 423 | #if !defined(CH_DBG_FILL_THREADS) || defined(__DOXYGEN__) 424 | #define CH_DBG_FILL_THREADS FALSE 425 | #endif 426 | 427 | /** 428 | * @brief Debug option, threads profiling. 429 | * @details If enabled then a field is added to the @p Thread structure that 430 | * counts the system ticks occurred while executing the thread. 431 | * 432 | * @note The default is @p TRUE. 433 | * @note This debug option is defaulted to TRUE because it is required by 434 | * some test cases into the test suite. 435 | */ 436 | #if !defined(CH_DBG_THREADS_PROFILING) || defined(__DOXYGEN__) 437 | #define CH_DBG_THREADS_PROFILING FALSE 438 | #endif 439 | 440 | /** @} */ 441 | 442 | /*===========================================================================*/ 443 | /** 444 | * @name Kernel hooks 445 | * @{ 446 | */ 447 | /*===========================================================================*/ 448 | 449 | /** 450 | * @brief Threads descriptor structure extension. 451 | * @details User fields added to the end of the @p Thread structure. 452 | */ 453 | #if !defined(THREAD_EXT_FIELDS) || defined(__DOXYGEN__) 454 | #define THREAD_EXT_FIELDS \ 455 | /* Add threads custom fields here.*/ 456 | #endif 457 | 458 | /** 459 | * @brief Threads initialization hook. 460 | * @details User initialization code added to the @p chThdInit() API. 461 | * 462 | * @note It is invoked from within @p chThdInit() and implicitly from all 463 | * the threads creation APIs. 464 | */ 465 | #if !defined(THREAD_EXT_INIT_HOOK) || defined(__DOXYGEN__) 466 | #define THREAD_EXT_INIT_HOOK(tp) { \ 467 | /* Add threads initialization code here.*/ \ 468 | } 469 | #endif 470 | 471 | /** 472 | * @brief Threads finalization hook. 473 | * @details User finalization code added to the @p chThdExit() API. 474 | * 475 | * @note It is inserted into lock zone. 476 | * @note It is also invoked when the threads simply return in order to 477 | * terminate. 478 | */ 479 | #if !defined(THREAD_EXT_EXIT_HOOK) || defined(__DOXYGEN__) 480 | #define THREAD_EXT_EXIT_HOOK(tp) { \ 481 | /* Add threads finalization code here.*/ \ 482 | } 483 | #endif 484 | 485 | /** 486 | * @brief Context switch hook. 487 | * @details This hook is invoked just before switching between threads. 488 | */ 489 | #if !defined(THREAD_CONTEXT_SWITCH_HOOK) || defined(__DOXYGEN__) 490 | #define THREAD_CONTEXT_SWITCH_HOOK(ntp, otp) { \ 491 | /* System halt code here.*/ \ 492 | } 493 | #endif 494 | 495 | /** 496 | * @brief Idle Loop hook. 497 | * @details This hook is continuously invoked by the idle thread loop. 498 | */ 499 | #if !defined(IDLE_LOOP_HOOK) || defined(__DOXYGEN__) 500 | #define IDLE_LOOP_HOOK() { \ 501 | /* Idle loop code here.*/ \ 502 | } 503 | #endif 504 | 505 | /** 506 | * @brief System tick event hook. 507 | * @details This hook is invoked in the system tick handler immediately 508 | * after processing the virtual timers queue. 509 | */ 510 | #if !defined(SYSTEM_TICK_EVENT_HOOK) || defined(__DOXYGEN__) 511 | #define SYSTEM_TICK_EVENT_HOOK() { \ 512 | /* System tick event code here.*/ \ 513 | } 514 | #endif 515 | 516 | /** 517 | * @brief System halt hook. 518 | * @details This hook is invoked in case to a system halting error before 519 | * the system is halted. 520 | */ 521 | #if !defined(SYSTEM_HALT_HOOK) || defined(__DOXYGEN__) 522 | #define SYSTEM_HALT_HOOK() { \ 523 | /* System halt code here.*/ \ 524 | } 525 | #endif 526 | 527 | /** @} */ 528 | 529 | /*===========================================================================*/ 530 | /* Port-specific settings (override port settings defaulted in chcore.h). */ 531 | /*===========================================================================*/ 532 | 533 | #endif /* _CHCONF_H_ */ 534 | 535 | /** @} */ 536 | -------------------------------------------------------------------------------- /test/ffconf.h: -------------------------------------------------------------------------------- 1 | /* CHIBIOS FIX */ 2 | #include "ch.h" 3 | 4 | /*---------------------------------------------------------------------------/ 5 | / FatFs - FAT file system module configuration file R0.09 (C)ChaN, 2011 6 | /----------------------------------------------------------------------------/ 7 | / 8 | / CAUTION! Do not forget to make clean the project after any changes to 9 | / the configuration options. 10 | / 11 | /----------------------------------------------------------------------------*/ 12 | #ifndef _FFCONF 13 | #define _FFCONF 6502 /* Revision ID */ 14 | 15 | 16 | /*---------------------------------------------------------------------------/ 17 | / Functions and Buffer Configurations 18 | /----------------------------------------------------------------------------*/ 19 | 20 | #define _FS_TINY 1 /* 0:Normal or 1:Tiny */ 21 | /* When _FS_TINY is set to 1, FatFs uses the sector buffer in the file system 22 | / object instead of the sector buffer in the individual file object for file 23 | / data transfer. This reduces memory consumption 512 bytes each file object. */ 24 | 25 | 26 | #define _FS_READONLY 0 /* 0:Read/Write or 1:Read only */ 27 | /* Setting _FS_READONLY to 1 defines read only configuration. This removes 28 | / writing functions, f_write, f_sync, f_unlink, f_mkdir, f_chmod, f_rename, 29 | / f_truncate and useless f_getfree. */ 30 | 31 | 32 | #define _FS_MINIMIZE 0 /* 0 to 3 */ 33 | /* The _FS_MINIMIZE option defines minimization level to remove some functions. 34 | / 35 | / 0: Full function. 36 | / 1: f_stat, f_getfree, f_unlink, f_mkdir, f_chmod, f_truncate and f_rename 37 | / are removed. 38 | / 2: f_opendir and f_readdir are removed in addition to 1. 39 | / 3: f_lseek is removed in addition to 2. */ 40 | 41 | 42 | #define _USE_STRFUNC 1 /* 0:Disable or 1-2:Enable */ 43 | /* To enable string functions, set _USE_STRFUNC to 1 or 2. */ 44 | 45 | 46 | #define _USE_MKFS 0 /* 0:Disable or 1:Enable */ 47 | /* To enable f_mkfs function, set _USE_MKFS to 1 and set _FS_READONLY to 0 */ 48 | 49 | 50 | #define _USE_FORWARD 0 /* 0:Disable or 1:Enable */ 51 | /* To enable f_forward function, set _USE_FORWARD to 1 and set _FS_TINY to 1. */ 52 | 53 | 54 | #define _USE_FASTSEEK 0 /* 0:Disable or 1:Enable */ 55 | /* To enable fast seek feature, set _USE_FASTSEEK to 1. */ 56 | 57 | 58 | 59 | /*---------------------------------------------------------------------------/ 60 | / Locale and Namespace Configurations 61 | /----------------------------------------------------------------------------*/ 62 | 63 | #define _CODE_PAGE 850 64 | /* The _CODE_PAGE specifies the OEM code page to be used on the target system. 65 | / Incorrect setting of the code page can cause a file open failure. 66 | / 67 | / 932 - Japanese Shift-JIS (DBCS, OEM, Windows) 68 | / 936 - Simplified Chinese GBK (DBCS, OEM, Windows) 69 | / 949 - Korean (DBCS, OEM, Windows) 70 | / 950 - Traditional Chinese Big5 (DBCS, OEM, Windows) 71 | / 1250 - Central Europe (Windows) 72 | / 1251 - Cyrillic (Windows) 73 | / 1252 - Latin 1 (Windows) 74 | / 1253 - Greek (Windows) 75 | / 1254 - Turkish (Windows) 76 | / 1255 - Hebrew (Windows) 77 | / 1256 - Arabic (Windows) 78 | / 1257 - Baltic (Windows) 79 | / 1258 - Vietnam (OEM, Windows) 80 | / 437 - U.S. (OEM) 81 | / 720 - Arabic (OEM) 82 | / 737 - Greek (OEM) 83 | / 775 - Baltic (OEM) 84 | / 850 - Multilingual Latin 1 (OEM) 85 | / 858 - Multilingual Latin 1 + Euro (OEM) 86 | / 852 - Latin 2 (OEM) 87 | / 855 - Cyrillic (OEM) 88 | / 866 - Russian (OEM) 89 | / 857 - Turkish (OEM) 90 | / 862 - Hebrew (OEM) 91 | / 874 - Thai (OEM, Windows) 92 | / 1 - ASCII only (Valid for non LFN cfg.) 93 | */ 94 | 95 | 96 | #define _USE_LFN 1 /* 0 to 3 */ 97 | #define _MAX_LFN 255 /* Maximum LFN length to handle (12 to 255) */ 98 | /* The _USE_LFN option switches the LFN support. 99 | / 100 | / 0: Disable LFN feature. _MAX_LFN and _LFN_UNICODE have no effect. 101 | / 1: Enable LFN with static working buffer on the BSS. Always NOT reentrant. 102 | / 2: Enable LFN with dynamic working buffer on the STACK. 103 | / 3: Enable LFN with dynamic working buffer on the HEAP. 104 | / 105 | / The LFN working buffer occupies (_MAX_LFN + 1) * 2 bytes. To enable LFN, 106 | / Unicode handling functions ff_convert() and ff_wtoupper() must be added 107 | / to the project. When enable to use heap, memory control functions 108 | / ff_memalloc() and ff_memfree() must be added to the project. */ 109 | 110 | 111 | #define _LFN_UNICODE 0 /* 0:ANSI/OEM or 1:Unicode */ 112 | /* To switch the character code set on FatFs API to Unicode, 113 | / enable LFN feature and set _LFN_UNICODE to 1. */ 114 | 115 | 116 | #define _FS_RPATH 0 /* 0 to 2 */ 117 | /* The _FS_RPATH option configures relative path feature. 118 | / 119 | / 0: Disable relative path feature and remove related functions. 120 | / 1: Enable relative path. f_chdrive() and f_chdir() are available. 121 | / 2: f_getcwd() is available in addition to 1. 122 | / 123 | / Note that output of the f_readdir fnction is affected by this option. */ 124 | 125 | 126 | 127 | /*---------------------------------------------------------------------------/ 128 | / Physical Drive Configurations 129 | /----------------------------------------------------------------------------*/ 130 | 131 | #define _VOLUMES 1 132 | /* Number of volumes (logical drives) to be used. */ 133 | 134 | 135 | #define _MAX_SS 512 /* 512, 1024, 2048 or 4096 */ 136 | /* Maximum sector size to be handled. 137 | / Always set 512 for memory card and hard disk but a larger value may be 138 | / required for on-board flash memory, floppy disk and optical disk. 139 | / When _MAX_SS is larger than 512, it configures FatFs to variable sector size 140 | / and GET_SECTOR_SIZE command must be implememted to the disk_ioctl function. */ 141 | 142 | 143 | #define _MULTI_PARTITION 0 /* 0:Single partition, 1/2:Enable multiple partition */ 144 | /* When set to 0, each volume is bound to the same physical drive number and 145 | / it can mount only first primaly partition. When it is set to 1, each volume 146 | / is tied to the partitions listed in VolToPart[]. */ 147 | 148 | 149 | #define _USE_ERASE 0 /* 0:Disable or 1:Enable */ 150 | /* To enable sector erase feature, set _USE_ERASE to 1. CTRL_ERASE_SECTOR command 151 | / should be added to the disk_ioctl functio. */ 152 | 153 | 154 | 155 | /*---------------------------------------------------------------------------/ 156 | / System Configurations 157 | /----------------------------------------------------------------------------*/ 158 | 159 | #define _WORD_ACCESS 0 /* 0 or 1 */ 160 | /* Set 0 first and it is always compatible with all platforms. The _WORD_ACCESS 161 | / option defines which access method is used to the word data on the FAT volume. 162 | / 163 | / 0: Byte-by-byte access. 164 | / 1: Word access. Do not choose this unless following condition is met. 165 | / 166 | / When the byte order on the memory is big-endian or address miss-aligned word 167 | / access results incorrect behavior, the _WORD_ACCESS must be set to 0. 168 | / If it is not the case, the value can also be set to 1 to improve the 169 | / performance and code size. 170 | */ 171 | 172 | 173 | /* A header file that defines sync object types on the O/S, such as 174 | / windows.h, ucos_ii.h and semphr.h, must be included prior to ff.h. */ 175 | 176 | #define _FS_REENTRANT 0 /* 0:Disable or 1:Enable */ 177 | #define _FS_TIMEOUT 1000 /* Timeout period in unit of time ticks */ 178 | #define _SYNC_t Semaphore * /* O/S dependent type of sync object. e.g. HANDLE, OS_EVENT*, ID and etc.. */ 179 | 180 | /* The _FS_REENTRANT option switches the reentrancy (thread safe) of the FatFs module. 181 | / 182 | / 0: Disable reentrancy. _SYNC_t and _FS_TIMEOUT have no effect. 183 | / 1: Enable reentrancy. Also user provided synchronization handlers, 184 | / ff_req_grant, ff_rel_grant, ff_del_syncobj and ff_cre_syncobj 185 | / function must be added to the project. */ 186 | 187 | 188 | #define _FS_SHARE 0 /* 0:Disable or >=1:Enable */ 189 | /* To enable file shareing feature, set _FS_SHARE to 1 or greater. The value 190 | defines how many files can be opened simultaneously. */ 191 | 192 | 193 | #endif /* _FFCONFIG */ 194 | -------------------------------------------------------------------------------- /test/generate-test-ihex-f407.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # generate a iHex file suitable for the unit test on a stm32f407 4 | 5 | # generate a chunk of data in the middle of sector 5 6 | # generate a chunk of data across the end of sector 5 and the beginning of sector 6 7 | # generate a chunk of data in the middle of sector 6 8 | 9 | # sector 5: 0x08020000 -> 0x0803FFFF 10 | # sector 6: 0x08040000 -> 0x0805FFFF 11 | 12 | srec_cat \ 13 | -generate 0x08030460 0x08030500 -repeat-string "unit test: chunk 1 pattern" \ 14 | -generate 0x0803FF83 0x08040011 -repeat-string "unit test: chunk 2 pattern" \ 15 | -generate 0x08040500 0x08040507 -repeat-string "unit test: chink 3 pattern" \ 16 | -o test-f407.ihex -intel 17 | 18 | -------------------------------------------------------------------------------- /test/halconf.h: -------------------------------------------------------------------------------- 1 | /* 2 | ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, 3 | 2011,2012 Giovanni Di Sirio. 4 | 5 | This file is part of ChibiOS/RT. 6 | 7 | ChibiOS/RT is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation; either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | ChibiOS/RT is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | 21 | /** 22 | * @file templates/halconf.h 23 | * @brief HAL configuration header. 24 | * @details HAL configuration file, this file allows to enable or disable the 25 | * various device drivers from your application. You may also use 26 | * this file in order to override the device drivers default settings. 27 | * 28 | * @addtogroup HAL_CONF 29 | * @{ 30 | */ 31 | 32 | #ifndef _HALCONF_H_ 33 | #define _HALCONF_H_ 34 | 35 | #include "mcuconf.h" 36 | 37 | /** 38 | * @brief Enables the TM subsystem. 39 | */ 40 | #if !defined(HAL_USE_TM) || defined(__DOXYGEN__) 41 | #define HAL_USE_TM FALSE 42 | #endif 43 | 44 | /** 45 | * @brief Enables the PAL subsystem. 46 | */ 47 | #if !defined(HAL_USE_PAL) || defined(__DOXYGEN__) 48 | #define HAL_USE_PAL TRUE 49 | #endif 50 | 51 | /** 52 | * @brief Enables the ADC subsystem. 53 | */ 54 | #if !defined(HAL_USE_ADC) || defined(__DOXYGEN__) 55 | #define HAL_USE_ADC FALSE 56 | #endif 57 | 58 | /** 59 | * @brief Enables the CAN subsystem. 60 | */ 61 | #if !defined(HAL_USE_CAN) || defined(__DOXYGEN__) 62 | #define HAL_USE_CAN FALSE 63 | #endif 64 | 65 | /** 66 | * @brief Enables the EXT subsystem. 67 | */ 68 | #if !defined(HAL_USE_EXT) || defined(__DOXYGEN__) 69 | #define HAL_USE_EXT FALSE 70 | #endif 71 | 72 | /** 73 | * @brief Enables the GPT subsystem. 74 | */ 75 | #if !defined(HAL_USE_GPT) || defined(__DOXYGEN__) 76 | #define HAL_USE_GPT FALSE 77 | #endif 78 | 79 | /** 80 | * @brief Enables the I2C subsystem. 81 | */ 82 | #if !defined(HAL_USE_I2C) || defined(__DOXYGEN__) 83 | #define HAL_USE_I2C FALSE 84 | #endif 85 | 86 | /** 87 | * @brief Enables the ICU subsystem. 88 | */ 89 | #if !defined(HAL_USE_ICU) || defined(__DOXYGEN__) 90 | #define HAL_USE_ICU FALSE 91 | #endif 92 | 93 | /** 94 | * @brief Enables the MAC subsystem. 95 | */ 96 | #if !defined(HAL_USE_MAC) || defined(__DOXYGEN__) 97 | #define HAL_USE_MAC FALSE 98 | #endif 99 | 100 | /** 101 | * @brief Enables the MMC_SPI subsystem. 102 | */ 103 | #if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__) 104 | #define HAL_USE_MMC_SPI FALSE 105 | #endif 106 | 107 | /** 108 | * @brief Enables the PWM subsystem. 109 | */ 110 | #if !defined(HAL_USE_PWM) || defined(__DOXYGEN__) 111 | #define HAL_USE_PWM FALSE 112 | #endif 113 | 114 | /** 115 | * @brief Enables the RTC subsystem. 116 | */ 117 | #if !defined(HAL_USE_RTC) || defined(__DOXYGEN__) 118 | #define HAL_USE_RTC FALSE 119 | #endif 120 | 121 | /** 122 | * @brief Enables the SDC subsystem. 123 | */ 124 | #if !defined(HAL_USE_SDC) || defined(__DOXYGEN__) 125 | #define HAL_USE_SDC TRUE 126 | #endif 127 | 128 | /** 129 | * @brief Enables the SERIAL subsystem. 130 | */ 131 | #if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__) 132 | #define HAL_USE_SERIAL TRUE 133 | #endif 134 | 135 | /** 136 | * @brief Enables the SERIAL over USB subsystem. 137 | */ 138 | #if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__) 139 | #define HAL_USE_SERIAL_USB FALSE 140 | #endif 141 | 142 | /** 143 | * @brief Enables the SPI subsystem. 144 | */ 145 | #if !defined(HAL_USE_SPI) || defined(__DOXYGEN__) 146 | #define HAL_USE_SPI FALSE 147 | #endif 148 | 149 | /** 150 | * @brief Enables the UART subsystem. 151 | */ 152 | #if !defined(HAL_USE_UART) || defined(__DOXYGEN__) 153 | #define HAL_USE_UART FALSE 154 | #endif 155 | 156 | /** 157 | * @brief Enables the USB subsystem. 158 | */ 159 | #if !defined(HAL_USE_USB) || defined(__DOXYGEN__) 160 | #define HAL_USE_USB FALSE 161 | #endif 162 | 163 | /*===========================================================================*/ 164 | /* ADC driver related settings. */ 165 | /*===========================================================================*/ 166 | 167 | /** 168 | * @brief Enables synchronous APIs. 169 | * @note Disabling this option saves both code and data space. 170 | */ 171 | #if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__) 172 | #define ADC_USE_WAIT TRUE 173 | #endif 174 | 175 | /** 176 | * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs. 177 | * @note Disabling this option saves both code and data space. 178 | */ 179 | #if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) 180 | #define ADC_USE_MUTUAL_EXCLUSION TRUE 181 | #endif 182 | 183 | /*===========================================================================*/ 184 | /* CAN driver related settings. */ 185 | /*===========================================================================*/ 186 | 187 | /** 188 | * @brief Sleep mode related APIs inclusion switch. 189 | */ 190 | #if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__) 191 | #define CAN_USE_SLEEP_MODE TRUE 192 | #endif 193 | 194 | /*===========================================================================*/ 195 | /* I2C driver related settings. */ 196 | /*===========================================================================*/ 197 | 198 | /** 199 | * @brief Enables the mutual exclusion APIs on the I2C bus. 200 | */ 201 | #if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) 202 | #define I2C_USE_MUTUAL_EXCLUSION TRUE 203 | #endif 204 | 205 | /*===========================================================================*/ 206 | /* MAC driver related settings. */ 207 | /*===========================================================================*/ 208 | 209 | /** 210 | * @brief Enables an event sources for incoming packets. 211 | */ 212 | #if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__) 213 | #define MAC_USE_EVENTS TRUE 214 | #endif 215 | 216 | /*===========================================================================*/ 217 | /* MMC_SPI driver related settings. */ 218 | /*===========================================================================*/ 219 | 220 | /** 221 | * @brief Block size for MMC transfers. 222 | */ 223 | #if !defined(MMC_SECTOR_SIZE) || defined(__DOXYGEN__) 224 | #define MMC_SECTOR_SIZE 512 225 | #endif 226 | 227 | /** 228 | * @brief Delays insertions. 229 | * @details If enabled this options inserts delays into the MMC waiting 230 | * routines releasing some extra CPU time for the threads with 231 | * lower priority, this may slow down the driver a bit however. 232 | * This option is recommended also if the SPI driver does not 233 | * use a DMA channel and heavily loads the CPU. 234 | */ 235 | #if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__) 236 | #define MMC_NICE_WAITING TRUE 237 | #endif 238 | 239 | /** 240 | * @brief Number of positive insertion queries before generating the 241 | * insertion event. 242 | */ 243 | #if !defined(MMC_POLLING_INTERVAL) || defined(__DOXYGEN__) 244 | #define MMC_POLLING_INTERVAL 10 245 | #endif 246 | 247 | /** 248 | * @brief Interval, in milliseconds, between insertion queries. 249 | */ 250 | #if !defined(MMC_POLLING_DELAY) || defined(__DOXYGEN__) 251 | #define MMC_POLLING_DELAY 10 252 | #endif 253 | 254 | /** 255 | * @brief Uses the SPI polled API for small data transfers. 256 | * @details Polled transfers usually improve performance because it 257 | * saves two context switches and interrupt servicing. Note 258 | * that this option has no effect on large transfers which 259 | * are always performed using DMAs/IRQs. 260 | */ 261 | #if !defined(MMC_USE_SPI_POLLING) || defined(__DOXYGEN__) 262 | #define MMC_USE_SPI_POLLING TRUE 263 | #endif 264 | 265 | /*===========================================================================*/ 266 | /* SDC driver related settings. */ 267 | /*===========================================================================*/ 268 | 269 | /** 270 | * @brief Number of initialization attempts before rejecting the card. 271 | * @note Attempts are performed at 10mS intervals. 272 | */ 273 | #if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__) 274 | #define SDC_INIT_RETRY 100 275 | #endif 276 | 277 | /** 278 | * @brief Include support for MMC cards. 279 | * @note MMC support is not yet implemented so this option must be kept 280 | * at @p FALSE. 281 | */ 282 | #if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__) 283 | #define SDC_MMC_SUPPORT FALSE 284 | #endif 285 | 286 | /** 287 | * @brief Delays insertions. 288 | * @details If enabled this options inserts delays into the MMC waiting 289 | * routines releasing some extra CPU time for the threads with 290 | * lower priority, this may slow down the driver a bit however. 291 | */ 292 | #if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__) 293 | #define SDC_NICE_WAITING TRUE 294 | #endif 295 | 296 | /*===========================================================================*/ 297 | /* SERIAL driver related settings. */ 298 | /*===========================================================================*/ 299 | 300 | /** 301 | * @brief Default bit rate. 302 | * @details Configuration parameter, this is the baud rate selected for the 303 | * default configuration. 304 | */ 305 | #if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__) 306 | #define SERIAL_DEFAULT_BITRATE 38400 307 | #endif 308 | 309 | /** 310 | * @brief Serial buffers size. 311 | * @details Configuration parameter, you can change the depth of the queue 312 | * buffers depending on the requirements of your application. 313 | * @note The default is 64 bytes for both the transmission and receive 314 | * buffers. 315 | */ 316 | #if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__) 317 | #define SERIAL_BUFFERS_SIZE 16 318 | #endif 319 | 320 | /*===========================================================================*/ 321 | /* SPI driver related settings. */ 322 | /*===========================================================================*/ 323 | 324 | /** 325 | * @brief Enables synchronous APIs. 326 | * @note Disabling this option saves both code and data space. 327 | */ 328 | #if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__) 329 | #define SPI_USE_WAIT TRUE 330 | #endif 331 | 332 | /** 333 | * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs. 334 | * @note Disabling this option saves both code and data space. 335 | */ 336 | #if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) 337 | #define SPI_USE_MUTUAL_EXCLUSION TRUE 338 | #endif 339 | 340 | #endif /* _HALCONF_H_ */ 341 | 342 | /** @} */ 343 | -------------------------------------------------------------------------------- /test/mcuconf.h: -------------------------------------------------------------------------------- 1 | /* 2 | ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, 3 | 2011,2012 Giovanni Di Sirio. 4 | 5 | This file is part of ChibiOS/RT. 6 | 7 | ChibiOS/RT is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation; either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | ChibiOS/RT is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | 21 | /* 22 | * STM32F4xx drivers configuration. 23 | * The following settings override the default settings present in 24 | * the various device driver implementation headers. 25 | * Note that the settings for each driver only have effect if the whole 26 | * driver is enabled in halconf.h. 27 | * 28 | * IRQ priorities: 29 | * 15...0 Lowest...Highest. 30 | * 31 | * DMA priorities: 32 | * 0...3 Lowest...Highest. 33 | */ 34 | 35 | #define STM32F4xx_MCUCONF 36 | 37 | /* 38 | * HAL driver system settings. 39 | */ 40 | #define STM32_NO_INIT FALSE 41 | #define STM32_HSI_ENABLED TRUE 42 | #define STM32_LSI_ENABLED TRUE 43 | #define STM32_HSE_ENABLED TRUE 44 | #define STM32_LSE_ENABLED FALSE 45 | #define STM32_CLOCK48_REQUIRED TRUE 46 | #define STM32_SW STM32_SW_PLL 47 | #define STM32_PLLSRC STM32_PLLSRC_HSE 48 | #define STM32_PLLM_VALUE 25 49 | #define STM32_PLLN_VALUE 336 50 | #define STM32_PLLP_VALUE 2 51 | #define STM32_PLLQ_VALUE 7 52 | #define STM32_HPRE STM32_HPRE_DIV1 53 | #define STM32_PPRE1 STM32_PPRE1_DIV4 54 | #define STM32_PPRE2 STM32_PPRE2_DIV2 55 | #define STM32_RTCSEL STM32_RTCSEL_LSI 56 | #define STM32_RTCPRE_VALUE 8 57 | #define STM32_MCO1SEL STM32_MCO1SEL_HSI 58 | #define STM32_MCO1PRE STM32_MCO1PRE_DIV1 59 | #define STM32_MCO2SEL STM32_MCO2SEL_SYSCLK 60 | #define STM32_MCO2PRE STM32_MCO2PRE_DIV5 61 | #define STM32_I2SSRC STM32_I2SSRC_CKIN 62 | #define STM32_PLLI2SN_VALUE 192 63 | #define STM32_PLLI2SR_VALUE 5 64 | #define STM32_VOS STM32_VOS_HIGH 65 | #define STM32_PVD_ENABLE FALSE 66 | #define STM32_PLS STM32_PLS_LEV0 67 | 68 | /* 69 | * ADC driver system settings. 70 | */ 71 | #define STM32_ADC_ADCPRE ADC_CCR_ADCPRE_DIV4 72 | #define STM32_ADC_USE_ADC1 FALSE 73 | #define STM32_ADC_USE_ADC2 FALSE 74 | #define STM32_ADC_USE_ADC3 FALSE 75 | #define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) 76 | #define STM32_ADC_ADC2_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) 77 | #define STM32_ADC_ADC3_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) 78 | #define STM32_ADC_ADC1_DMA_PRIORITY 2 79 | #define STM32_ADC_ADC2_DMA_PRIORITY 2 80 | #define STM32_ADC_ADC3_DMA_PRIORITY 2 81 | #define STM32_ADC_IRQ_PRIORITY 6 82 | #define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 6 83 | #define STM32_ADC_ADC2_DMA_IRQ_PRIORITY 6 84 | #define STM32_ADC_ADC3_DMA_IRQ_PRIORITY 6 85 | 86 | /* 87 | * CAN driver system settings. 88 | */ 89 | #define STM32_CAN_USE_CAN1 TRUE 90 | #define STM32_CAN_USE_CAN2 FALSE 91 | #define STM32_CAN_CAN1_IRQ_PRIORITY 11 92 | #define STM32_CAN_CAN2_IRQ_PRIORITY 11 93 | 94 | /* 95 | * EXT driver system settings. 96 | */ 97 | #define STM32_EXT_EXTI0_IRQ_PRIORITY 6 98 | #define STM32_EXT_EXTI1_IRQ_PRIORITY 6 99 | #define STM32_EXT_EXTI2_IRQ_PRIORITY 6 100 | #define STM32_EXT_EXTI3_IRQ_PRIORITY 6 101 | #define STM32_EXT_EXTI4_IRQ_PRIORITY 6 102 | #define STM32_EXT_EXTI5_9_IRQ_PRIORITY 6 103 | #define STM32_EXT_EXTI10_15_IRQ_PRIORITY 6 104 | #define STM32_EXT_EXTI16_IRQ_PRIORITY 6 105 | #define STM32_EXT_EXTI17_IRQ_PRIORITY 15 106 | #define STM32_EXT_EXTI18_IRQ_PRIORITY 6 107 | #define STM32_EXT_EXTI19_IRQ_PRIORITY 6 108 | #define STM32_EXT_EXTI20_IRQ_PRIORITY 6 109 | #define STM32_EXT_EXTI21_IRQ_PRIORITY 15 110 | #define STM32_EXT_EXTI22_IRQ_PRIORITY 15 111 | 112 | /* 113 | * GPT driver system settings. 114 | */ 115 | #define STM32_GPT_USE_TIM1 FALSE 116 | #define STM32_GPT_USE_TIM2 FALSE 117 | #define STM32_GPT_USE_TIM3 FALSE 118 | #define STM32_GPT_USE_TIM4 FALSE 119 | #define STM32_GPT_USE_TIM5 FALSE 120 | #define STM32_GPT_USE_TIM8 FALSE 121 | #define STM32_GPT_TIM1_IRQ_PRIORITY 7 122 | #define STM32_GPT_TIM2_IRQ_PRIORITY 7 123 | #define STM32_GPT_TIM3_IRQ_PRIORITY 7 124 | #define STM32_GPT_TIM4_IRQ_PRIORITY 7 125 | #define STM32_GPT_TIM5_IRQ_PRIORITY 7 126 | #define STM32_GPT_TIM8_IRQ_PRIORITY 7 127 | 128 | /* 129 | * I2C driver system settings. 130 | */ 131 | #define STM32_I2C_USE_I2C1 FALSE 132 | #define STM32_I2C_USE_I2C2 FALSE 133 | #define STM32_I2C_USE_I2C3 FALSE 134 | #define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) 135 | #define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) 136 | #define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) 137 | #define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) 138 | #define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) 139 | #define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) 140 | #define STM32_I2C_I2C1_IRQ_PRIORITY 5 141 | #define STM32_I2C_I2C2_IRQ_PRIORITY 5 142 | #define STM32_I2C_I2C3_IRQ_PRIORITY 5 143 | #define STM32_I2C_I2C1_DMA_PRIORITY 3 144 | #define STM32_I2C_I2C2_DMA_PRIORITY 3 145 | #define STM32_I2C_I2C3_DMA_PRIORITY 3 146 | #define STM32_I2C_I2C1_DMA_ERROR_HOOK() chSysHalt() 147 | #define STM32_I2C_I2C2_DMA_ERROR_HOOK() chSysHalt() 148 | #define STM32_I2C_I2C3_DMA_ERROR_HOOK() chSysHalt() 149 | 150 | /* 151 | * ICU driver system settings. 152 | */ 153 | #define STM32_ICU_USE_TIM1 FALSE 154 | #define STM32_ICU_USE_TIM2 FALSE 155 | #define STM32_ICU_USE_TIM3 FALSE 156 | #define STM32_ICU_USE_TIM4 FALSE 157 | #define STM32_ICU_USE_TIM5 FALSE 158 | #define STM32_ICU_USE_TIM8 FALSE 159 | #define STM32_ICU_TIM1_IRQ_PRIORITY 7 160 | #define STM32_ICU_TIM2_IRQ_PRIORITY 7 161 | #define STM32_ICU_TIM3_IRQ_PRIORITY 7 162 | #define STM32_ICU_TIM4_IRQ_PRIORITY 7 163 | #define STM32_ICU_TIM5_IRQ_PRIORITY 7 164 | #define STM32_ICU_TIM8_IRQ_PRIORITY 7 165 | 166 | /* 167 | * PWM driver system settings. 168 | */ 169 | #define STM32_PWM_USE_ADVANCED FALSE 170 | #define STM32_PWM_USE_TIM1 FALSE 171 | #define STM32_PWM_USE_TIM2 FALSE 172 | #define STM32_PWM_USE_TIM3 FALSE 173 | #define STM32_PWM_USE_TIM4 FALSE 174 | #define STM32_PWM_USE_TIM5 FALSE 175 | #define STM32_PWM_USE_TIM8 FALSE 176 | #define STM32_PWM_TIM1_IRQ_PRIORITY 7 177 | #define STM32_PWM_TIM2_IRQ_PRIORITY 7 178 | #define STM32_PWM_TIM3_IRQ_PRIORITY 7 179 | #define STM32_PWM_TIM4_IRQ_PRIORITY 7 180 | #define STM32_PWM_TIM5_IRQ_PRIORITY 7 181 | #define STM32_PWM_TIM8_IRQ_PRIORITY 7 182 | 183 | /* 184 | * SERIAL driver system settings. 185 | */ 186 | #define STM32_SERIAL_USE_USART1 FALSE 187 | #define STM32_SERIAL_USE_USART2 FALSE 188 | #define STM32_SERIAL_USE_USART3 FALSE 189 | #define STM32_SERIAL_USE_UART4 FALSE 190 | #define STM32_SERIAL_USE_UART5 FALSE 191 | #define STM32_SERIAL_USE_USART6 TRUE 192 | #define STM32_SERIAL_USART1_PRIORITY 12 193 | #define STM32_SERIAL_USART2_PRIORITY 12 194 | #define STM32_SERIAL_USART3_PRIORITY 12 195 | #define STM32_SERIAL_UART4_PRIORITY 12 196 | #define STM32_SERIAL_UART5_PRIORITY 12 197 | #define STM32_SERIAL_USART6_PRIORITY 12 198 | 199 | /* 200 | * SPI driver system settings. 201 | */ 202 | #define STM32_SPI_USE_SPI1 FALSE 203 | #define STM32_SPI_USE_SPI2 FALSE 204 | #define STM32_SPI_USE_SPI3 FALSE 205 | #define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 0) 206 | #define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) 207 | #define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) 208 | #define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) 209 | #define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) 210 | #define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) 211 | #define STM32_SPI_SPI1_DMA_PRIORITY 1 212 | #define STM32_SPI_SPI2_DMA_PRIORITY 1 213 | #define STM32_SPI_SPI3_DMA_PRIORITY 1 214 | #define STM32_SPI_SPI1_IRQ_PRIORITY 10 215 | #define STM32_SPI_SPI2_IRQ_PRIORITY 10 216 | #define STM32_SPI_SPI3_IRQ_PRIORITY 10 217 | #define STM32_SPI_DMA_ERROR_HOOK(spip) chSysHalt() 218 | 219 | /* 220 | * UART driver system settings. 221 | */ 222 | #define STM32_UART_USE_USART1 FALSE 223 | #define STM32_UART_USE_USART2 FALSE 224 | #define STM32_UART_USE_USART3 FALSE 225 | #define STM32_UART_USE_USART6 FALSE 226 | #define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) 227 | #define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) 228 | #define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) 229 | #define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) 230 | #define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) 231 | #define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) 232 | #define STM32_UART_USART6_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) 233 | #define STM32_UART_USART6_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) 234 | #define STM32_UART_USART1_IRQ_PRIORITY 12 235 | #define STM32_UART_USART2_IRQ_PRIORITY 12 236 | #define STM32_UART_USART3_IRQ_PRIORITY 12 237 | #define STM32_UART_USART6_IRQ_PRIORITY 12 238 | #define STM32_UART_USART1_DMA_PRIORITY 0 239 | #define STM32_UART_USART2_DMA_PRIORITY 0 240 | #define STM32_UART_USART3_DMA_PRIORITY 0 241 | #define STM32_UART_USART6_DMA_PRIORITY 0 242 | #define STM32_UART_DMA_ERROR_HOOK(uartp) chSysHalt() 243 | 244 | /* 245 | * USB driver system settings. 246 | */ 247 | #define STM32_USB_USE_OTG1 FALSE 248 | #define STM32_USB_USE_OTG2 FALSE 249 | #define STM32_USB_OTG1_IRQ_PRIORITY 14 250 | #define STM32_USB_OTG2_IRQ_PRIORITY 14 251 | #define STM32_USB_OTG1_RX_FIFO_SIZE 512 252 | #define STM32_USB_OTG2_RX_FIFO_SIZE 1024 253 | #define STM32_USB_OTG_THREAD_PRIO LOWPRIO 254 | #define STM32_USB_OTG_THREAD_STACK_SIZE 128 255 | #define STM32_USB_OTGFIFO_FILL_BASEPRI 0 256 | 257 | 258 | -------------------------------------------------------------------------------- /test/sdcard.c: -------------------------------------------------------------------------------- 1 | 2 | #include "sdcard.h" 3 | #include 4 | #include 5 | #include 6 | 7 | /* SD card related */ 8 | 9 | /** @brief FS object */ 10 | static FATFS fatfs; 11 | 12 | #if HAL_USE_MMC_SPI 13 | 14 | static MMCDriver MMCD1; 15 | 16 | /* SPI_CR1_BR: 17 | * 000 = STM32_PCLK1 / 2 100 = STM32_PCLK1 / 32 18 | * 001 = STM32_PCLK1 / 4 101 = STM32_PCLK1 / 64 19 | * 010 = STM32_PCLK1 / 8 110 = STM32_PCLK1 / 128 20 | * 011 = STM32_PCLK1 / 16 111 = STM32_PCLK1 / 256 21 | */ 22 | 23 | /* Maximum speed SPI configuration (42MHz/2=21MHz, CPHA=0, CPOL=0, MSb first).*/ 24 | static SPIConfig hs_spicfg = {NULL, GPIOD, GPIOD_SPI3_CS, 0}; 25 | 26 | /* Low speed SPI configuration (42MHz/128=328kHz, CPHA=0, CPOL=0, MSb first).*/ 27 | static SPIConfig ls_spicfg = {NULL, GPIOD, GPIOD_SPI3_CS, 28 | SPI_CR1_BR_2 | SPI_CR1_BR_1}; 29 | 30 | /* MMC/SD over SPI driver configuration.*/ 31 | static MMCConfig mmccfg = {&SPID3, &ls_spicfg, &hs_spicfg}; 32 | 33 | #endif 34 | 35 | int flashMountSDCard() 36 | { 37 | /* Initializes the SDC or MMC driver */ 38 | #if HAL_USE_SDC 39 | sdcStart(&SDCD1, NULL); 40 | #elif HAL_USE_MMC_SPI 41 | mmcObjectInit(&MMCD1); 42 | mmcStart(&MMCD1, &mmccfg); 43 | #endif 44 | 45 | /* Wait for card */ 46 | #if HAL_USE_SDC 47 | if (!blkIsInserted(&SDCD1) || sdcConnect(&SDCD1) == CH_FAILED) 48 | return BOOTLOADER_ERROR_NOCARD; 49 | if (f_mount(0, &fatfs) != FR_OK) 50 | { 51 | sdcDisconnect(&SDCD1); 52 | return BOOTLOADER_ERROR_BADFS; 53 | } 54 | #elif HAL_USE_MMC_SPI 55 | if (!blkIsInserted(&MMCD1) || mmcConnect(&MMCD1) == CH_FAILED) 56 | return BOOTLOADER_ERROR_NOCARD; 57 | if (f_mount(0, &fatfs) != FR_OK) 58 | { 59 | mmcDisconnect(&MMCD1); 60 | return BOOTLOADER_ERROR_BADFS; 61 | } 62 | #endif 63 | 64 | return BOOTLOADER_SUCCESS; 65 | } 66 | -------------------------------------------------------------------------------- /test/sdcard.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef SDCARD_H 3 | #define SDCARD_H 4 | 5 | /** 6 | * @brief Init the correct SD card driver (MMC or SDC) and mount the filesystem 7 | * @return BOOTLOADER_SUCCESS on success 8 | * @return BOOTLOADER_ERROR_NOCARD if no SD card is inserted 9 | * @return BOOTLOADER_ERROR_BADFS if the filesystem could not be mounted 10 | */ 11 | int flashMountSDCard(); 12 | 13 | #endif /* SDCARD_H */ 14 | -------------------------------------------------------------------------------- /test/test.c: -------------------------------------------------------------------------------- 1 | 2 | #include "sdcard.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #define TEST_FIRST_FREE_SECTOR 5 11 | 12 | #define COLORIZE_GREEN(message) "\033[1;32m" message "\033[0m" 13 | #define COLORIZE_RED(message) "\033[1;31m" message "\033[0m" 14 | 15 | #define TEST_VERIFY(message, statement) \ 16 | do { \ 17 | chprintf(chStdout, "%s - " message "\r\n", \ 18 | statement ? COLORIZE_GREEN("PASS") : COLORIZE_RED("FAIL")); \ 19 | } while (0) 20 | 21 | static BaseSequentialStream* chStdout = (BaseSequentialStream*)&SD6; 22 | 23 | /** 24 | * @brief The flash_sector_def struct describes a flash sector 25 | */ 26 | struct flash_sector_def 27 | { 28 | flashsector_t index; ///< Index of the sector in the flash memory 29 | size_t size; ///< Size of the sector in bytes 30 | flashaddr_t beginAddress; ///< First address of the sector in memory (inclusive) 31 | flashaddr_t endAddress; ///< Last address of the sector in memory (exclusive) 32 | }; 33 | 34 | /** 35 | * @brief Definition of the stm32f407 sectors. 36 | */ 37 | const struct flash_sector_def f407_flash[FLASH_SECTOR_COUNT] = 38 | { 39 | { 0, 16 * 1024, 0x08000000, 0x08004000}, 40 | { 1, 16 * 1024, 0x08004000, 0x08008000}, 41 | { 2, 16 * 1024, 0x08008000, 0x0800C000}, 42 | { 3, 16 * 1024, 0x0800C000, 0x08010000}, 43 | { 4, 64 * 1024, 0x08010000, 0x08020000}, 44 | { 5, 128 * 1024, 0x08020000, 0x08040000}, 45 | { 6, 128 * 1024, 0x08040000, 0x08060000}, 46 | { 7, 128 * 1024, 0x08060000, 0x08080000}, 47 | { 8, 128 * 1024, 0x08080000, 0x080A0000}, 48 | { 9, 128 * 1024, 0x080A0000, 0x080C0000}, 49 | { 10, 128 * 1024, 0x080C0000, 0x080E0000}, 50 | { 11, 128 * 1024, 0x080E0000, 0x08100000} 51 | }; 52 | 53 | #define PRINTABLE_CHARACTER_FIRST 0x20 54 | #define PRINTABLE_CHARACTER_LAST 0x7e 55 | #define PRINTABLE_CHARACTER_COUNT (PRINTABLE_CHARACTER_LAST - PRINTABLE_CHARACTER_FIRST + 1) 56 | 57 | /** 58 | * @brief Fill @p buffer with a pattern 59 | * @param buffer Buffer to be filled 60 | * @param size Size of @p buffer 61 | */ 62 | static void fillWithPattern(char* buffer, size_t size) 63 | { 64 | /* Generate a pattern with printable characters to ease debugging) */ 65 | int c; 66 | for (c = 0; c < size; ++c) 67 | buffer[c] = (c % PRINTABLE_CHARACTER_COUNT) + PRINTABLE_CHARACTER_FIRST; 68 | } 69 | 70 | /** 71 | * @brief Tests related to the flash sectors 72 | */ 73 | static void testFlashSector() 74 | { 75 | flashsector_t i; 76 | for (i = 0; i < FLASH_SECTOR_COUNT; ++i) 77 | { 78 | const struct flash_sector_def* sector = &f407_flash[i]; 79 | 80 | chprintf(chStdout, "\r\n> test sector %u: 0x%x -> 0x%x (%u bytes)\r\n\r\n", 81 | sector->index, 82 | sector->beginAddress, 83 | sector->endAddress, 84 | sector->size); 85 | 86 | TEST_VERIFY("sector index", i == sector->index); 87 | TEST_VERIFY("sector size", flashSectorSize(i) == sector->size); 88 | TEST_VERIFY("sector begin address", flashSectorBegin(i) == sector->beginAddress); 89 | TEST_VERIFY("sector end address", flashSectorEnd(i) == sector->endAddress); 90 | TEST_VERIFY("sector lookup (begin address)", flashSectorAt(sector->beginAddress) == i); 91 | TEST_VERIFY("sector lookup (end address)", flashSectorAt(sector->endAddress - 1) == i); 92 | TEST_VERIFY("sector lookup (middle address)", flashSectorAt(sector->beginAddress + sector->size / 2) == i); 93 | if (i != 0) 94 | TEST_VERIFY("sector lookup (pre-begin address)", flashSectorAt(sector->beginAddress - 1) == i - 1); 95 | if (i != FLASH_SECTOR_COUNT - 1) 96 | TEST_VERIFY("sector lookup (post-end address)", flashSectorAt(sector->endAddress) == i + 1); 97 | } 98 | } 99 | 100 | /** 101 | * @brief The test_flashreadwrite_data struct defines a test case data for the read/write test. 102 | */ 103 | struct test_flashreadwrite_data 104 | { 105 | char* testName; ///< Name of the test case 106 | flashaddr_t from; ///< First address to be read/write (inclusive) 107 | flashaddr_t to; ///< Last address to be read/write (exclusive) 108 | }; 109 | 110 | #define TEST_BASE 0x08060000 111 | #define TEST_DATASIZE sizeof(flashdata_t) 112 | #define TEST_READWRITE_TESTCASE_COUNT 8 113 | 114 | /** 115 | * @brief Test cases for the read/write test. 116 | * 117 | * "big data" tests read/write more than sizeof(flashdata_t) bytes while 118 | * "tiny data" tests read/write sizeof(flashdata_t) bytes at most. 119 | */ 120 | struct test_flashreadwrite_data flashreadwrite_testcases[TEST_READWRITE_TESTCASE_COUNT] = 121 | { 122 | { "aligned start, aligned end, big data", TEST_BASE + 1 * TEST_DATASIZE + 0, TEST_BASE + 4 * TEST_DATASIZE + 0 }, 123 | { "aligned start, not aligned end, big data", TEST_BASE + 4 * TEST_DATASIZE + 0, TEST_BASE + 6 * TEST_DATASIZE + 1 }, 124 | { "not aligned start, not aligned end, big data", TEST_BASE + 6 * TEST_DATASIZE + 1, TEST_BASE + 9 * TEST_DATASIZE - 1 }, 125 | { "not aligned start, aligned end, big data", TEST_BASE + 9 * TEST_DATASIZE - 1, TEST_BASE + 11 * TEST_DATASIZE + 0 }, 126 | { "aligned start, aligned end, tiny data", TEST_BASE + 11 * TEST_DATASIZE + 0, TEST_BASE + 12 * TEST_DATASIZE + 0 }, 127 | { "aligned start, not aligned end, tiny data", TEST_BASE + 12 * TEST_DATASIZE + 0, TEST_BASE + 12 * TEST_DATASIZE + 1 }, 128 | { "not aligned start, not aligned end, tiny data", TEST_BASE + 12 * TEST_DATASIZE + 1, TEST_BASE + 13 * TEST_DATASIZE - 1 }, 129 | { "not aligned start, aligned end, tiny data", TEST_BASE + 13 * TEST_DATASIZE - 1, TEST_BASE + 13 * TEST_DATASIZE + 0 } 130 | }; 131 | 132 | /** 133 | * @brief Execute the read/write test cases. 134 | */ 135 | static void testFlashReadWrite() 136 | { 137 | /* Erase all sectors needed by the test cases */ 138 | flashsector_t sector; 139 | for (sector = TEST_FIRST_FREE_SECTOR; sector < FLASH_SECTOR_COUNT; ++sector) 140 | flashSectorErase(sector); 141 | 142 | /* Execute the test cases */ 143 | int i; 144 | for (i = 0; i < TEST_READWRITE_TESTCASE_COUNT; ++i) 145 | { 146 | const struct test_flashreadwrite_data* testcase = &flashreadwrite_testcases[i]; 147 | 148 | chprintf(chStdout, "\r\n> test flash read/write: %s\r\n\r\n", testcase->testName); 149 | 150 | char writeBuffer[testcase->to - testcase->from]; 151 | fillWithPattern(writeBuffer, testcase->to - testcase->from); 152 | char readBufferBefore[32]; 153 | char readBufferAfter[32]; 154 | TEST_VERIFY("read previous data (before target)", flashRead(testcase->from - sizeof(readBufferBefore), readBufferBefore, sizeof(readBufferBefore)) == FLASH_RETURN_SUCCESS); 155 | TEST_VERIFY("read previous data (after target)", flashRead(testcase->to, readBufferAfter, sizeof(readBufferAfter)) == FLASH_RETURN_SUCCESS); 156 | 157 | TEST_VERIFY("write data to flash", flashWrite(testcase->from, writeBuffer, testcase->to - testcase->from) == FLASH_RETURN_SUCCESS); 158 | TEST_VERIFY("previous data not overwritten (before target)", flashCompare(testcase->from - sizeof(readBufferBefore), readBufferBefore, sizeof(readBufferBefore)) == TRUE); 159 | TEST_VERIFY("previous data not overwritten (after target)", flashCompare(testcase->to, readBufferAfter, sizeof(readBufferAfter)) == TRUE); 160 | TEST_VERIFY("compare written data", flashCompare(testcase->from, writeBuffer, testcase->to - testcase->from) == TRUE); 161 | 162 | char readBuffer[testcase->to - testcase->from]; 163 | memset(readBuffer, '#', testcase->to - testcase->from); 164 | TEST_VERIFY("read back written data", flashRead(testcase->from, readBuffer, testcase->to - testcase->from) == FLASH_RETURN_SUCCESS); 165 | TEST_VERIFY("compare read and write data", memcmp(readBuffer, writeBuffer, testcase->to - testcase->from) == 0); 166 | } 167 | } 168 | 169 | /** 170 | * @brief The test_pattern_def struct defines what patterns are expected 171 | * where in the iHex flash to be flashed for the iHex flashing test. 172 | * 173 | * To be noted that the pattern's data is used as a circular buffer. 174 | * Thus, if size < (to - from), data we will be reread from the beginning (that is, the iHex pattern can be data repeated several times). 175 | */ 176 | struct test_pattern_def 177 | { 178 | flashaddr_t from; ///< First address of the pattern (inclusive) 179 | flashaddr_t to; ///< Last address of the pattern (exclusive) 180 | char* data; ///< Pattern's data 181 | size_t size; ///< Size of the pattern's data 182 | }; 183 | 184 | /** 185 | * @brief Pattern definitions 186 | */ 187 | #define TEST_IHEX_FILE "test-f407.ihex" 188 | #define TEST_IHEX_PATTERN_COUNT 3 189 | #define TEST_IHEX_PATTERN_1 "unit test: chunk 1 pattern" 190 | #define TEST_IHEX_PATTERN_2 "unit test: chunk 2 pattern" 191 | #define TEST_IHEX_PATTERN_3 "unit test: chunk 3 pattern" 192 | 193 | const struct test_pattern_def iHexPatterns[TEST_IHEX_PATTERN_COUNT] = 194 | { 195 | { 0x08030460, 0x08030500, TEST_IHEX_PATTERN_1, sizeof(TEST_IHEX_PATTERN_1) - 1 }, 196 | { 0x0803FF83, 0x08040011, TEST_IHEX_PATTERN_2, sizeof(TEST_IHEX_PATTERN_2) - 1 }, 197 | { 0x08040500, 0x08040507, TEST_IHEX_PATTERN_3, sizeof(TEST_IHEX_PATTERN_3) - 1 } 198 | }; 199 | 200 | /** 201 | * @brief Check that the sector is empty before the given address 202 | * @param address First address not checked 203 | * @return TRUE if erased, FALSE otherwise 204 | */ 205 | static bool_t checkSectorEmptyBefore(flashaddr_t address) 206 | { 207 | flashaddr_t sectorBegin = flashSectorBegin(flashSectorAt(address)); 208 | return flashIsErased(sectorBegin, address - sectorBegin); 209 | } 210 | 211 | /** 212 | * @brief Check the the sector is empty after the given address 213 | * @param address Last address not checked 214 | * @return TRUE if erased, FALSE otherwise 215 | */ 216 | static bool_t checkSectorEmptyAfter(flashaddr_t address) 217 | { 218 | ++address; 219 | flashaddr_t sectorEnd = flashSectorEnd(flashSectorAt(address)); 220 | return flashIsErased(address, sectorEnd - address); 221 | } 222 | 223 | /** 224 | * @brief Check that the pattern's data have be written correctly 225 | * @param pattern Pattern to be checked 226 | * @return TRUE if successfully written, FALSE otherwise 227 | */ 228 | static bool_t checkWrittenPattern(const struct test_pattern_def* pattern) 229 | { 230 | flashaddr_t address = pattern->from; 231 | while (address < pattern->to) 232 | { 233 | size_t count = (size_t)(pattern->to - address); 234 | if (count > pattern->size) 235 | count = pattern->size; 236 | if (flashCompare(address, pattern->data, count) == FALSE) 237 | return FALSE; 238 | 239 | address += count; 240 | } 241 | 242 | return TRUE; 243 | } 244 | 245 | /** 246 | * @brief Check that the data between two patterns are erased 247 | * @param first First pattern (lower bound) 248 | * @param second Second pattern (upper bound) 249 | * @return TRUE if the data in between are erased, FALSE otherwise 250 | */ 251 | static bool_t checkEmptyBetweenPatterns(const struct test_pattern_def* first, const struct test_pattern_def* second) 252 | { 253 | return flashIsErased(first->to, second->from - first->to); 254 | } 255 | 256 | /** 257 | * @brief Test case flashing a iHex file read from the SD card 258 | */ 259 | static void testIHex() 260 | { 261 | chprintf(chStdout, "\r\n > test iHex flashing: " TEST_IHEX_FILE "\r\n\r\n"); 262 | 263 | TEST_VERIFY("mount sd card", flashMountSDCard() == BOOTLOADER_SUCCESS); 264 | 265 | FIL firmwareFile; 266 | TEST_VERIFY("open iHex file", f_open(&firmwareFile, TEST_IHEX_FILE, FA_READ) == FR_OK); 267 | 268 | TEST_VERIFY("flash iHex file", flashIHexFile(&firmwareFile) == BOOTLOADER_SUCCESS); 269 | f_close(&firmwareFile); 270 | 271 | /* Written patterns check */ 272 | int patternIndex; 273 | for (patternIndex = 0; patternIndex < TEST_IHEX_PATTERN_COUNT; ++patternIndex) 274 | { 275 | TEST_VERIFY("pattern correctly written", 276 | checkWrittenPattern(&iHexPatterns[patternIndex]) == TRUE); 277 | } 278 | 279 | /* Erased data check */ 280 | TEST_VERIFY("no data written before first pattern", checkSectorEmptyBefore(iHexPatterns[0].from) == TRUE); 281 | for (patternIndex = 0; patternIndex < TEST_IHEX_PATTERN_COUNT - 1; ++patternIndex) 282 | { 283 | TEST_VERIFY("no data written between two patterns", 284 | checkEmptyBetweenPatterns( 285 | &iHexPatterns[patternIndex], 286 | &iHexPatterns[patternIndex + 1]) == TRUE); 287 | } 288 | TEST_VERIFY("no data written after last pattern", checkSectorEmptyAfter(iHexPatterns[TEST_IHEX_PATTERN_COUNT - 1].to - 1) == TRUE); 289 | } 290 | 291 | int main() 292 | { 293 | /* 294 | * System initializations. 295 | * - HAL initialization, this also initializes the configured device drivers 296 | * and performs the board-specific initializations. 297 | * - Kernel initialization, the main() function becomes a thread and the 298 | * RTOS is active. 299 | */ 300 | halInit(); 301 | chSysInit(); 302 | 303 | /* Activates the serial driver 3 using the driver default configuration */ 304 | sdStart((SerialDriver*)chStdout, NULL); 305 | 306 | /* Start the tests */ 307 | chprintf(chStdout, "\r\n=== test start ===\r\n\r\n"); 308 | testFlashSector(); 309 | testFlashReadWrite(); 310 | testIHex(); 311 | chprintf(chStdout, "\r\n=== test end ===\r\n\r\n"); 312 | 313 | return 0; 314 | } 315 | --------------------------------------------------------------------------------