extmem_flash.c 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840
  1. #define EXTMEM_FLASH_C
  2. #include "core/config.h"
  3. #include "drivers/flash/base/extmem_flash.h"
  4. #include "core/gpio.h"
  5. #include "core/main.h"
  6. #include "core/config_pins.h"
  7. #define pSPIHandle (&SPIHandle)
  8. #if AT45DBXXX_POWER_MANAGEMENT || W25QXXX_POWER_MANAGEMENT
  9. static void ExtMem_SetPinPowerOn();
  10. static void ExtMem_SetPinPowerOff();
  11. #endif
  12. #if AT45DBXXX_RESET_MANAGEMENT || W25QXXX_RESET_MANAGEMENT
  13. static void ExtMem_ResetPinAssert();
  14. static void ExtMem_ResetPinRelease();
  15. #endif
  16. #if AT45DBXXX_HW_WR_PROTECT || W25QXXX_HW_WR_PROTECT
  17. static void ExtMem_HwWrProtPinAssert();
  18. static void ExtMem_HwWrProtPinRelease();
  19. #endif
  20. static bool ExtMem_Write( flash_address_t address, __FLASH_BYTE * pBuffer, flash_address_t size );
  21. static bool ExtMem_Read( flash_address_t address, __FLASH_BYTE * pBuffer, flash_address_t size );
  22. static bool ExtMem_RangeCheck_Read( flash_address_t address, flash_address_t size );
  23. static bool ExtMem_RangeCheck_Write( flash_address_t address, flash_address_t size );
  24. static bool ExtMem_BankProtect( eExtMem_Bank_t bankId, bool protectStatus );
  25. static bool ExtMem_CheckBankProtect( eExtMem_Bank_t bankId, bool * pActualProtectStatus );
  26. static void ExtMem_Pins_Init();
  27. static void ExtMem_Pins_Deinit();
  28. static bool ExtMem_DeInit( bool bForce );
  29. static bool ExtMem_Init();
  30. // -----------------------------------------------------------------------------
  31. // Memory Banking Template
  32. // Divides the whole chip memory into the common banks
  33. // This structure describes the sectors mask included into the bank
  34. typedef struct
  35. {
  36. struct flash_sectors_st selectRegister;
  37. }
  38. sMemoryBankingTemplate_t;
  39. static void ExtMem_Internal_FillBankingTemplate( const ExtMem_Bank_Properties_t * pBankProperties, sMemoryBankingTemplate_t * pFactoryProtectionTemplate );
  40. // -----------------------------------------------------------------------------
  41. volatile bool bExtMemStatus = false;
  42. typedef struct
  43. {
  44. const flash_api_descriptor_t * api;
  45. }
  46. ExtMemDriver_t;
  47. // Supported flash-drivers
  48. static const ExtMemDriver_t flash_drivers[] =
  49. {
  50. { &W25Q16JV_API } // W25Q driver
  51. };
  52. static const ExtMemDriver_t * flashDriver = NULL; // active driver pointer
  53. #define EXTMEM_BANK0_SIZE (0x0E0000)
  54. #define EXTMEM_BANK1_SIZE (0x100000)
  55. // Dynamically filled Bank properties
  56. static ExtMem_Banks_Properties_t ActualBankProperties =
  57. {
  58. .factoryBank = { .bankSize = 0, .bankAddress = 0 },
  59. .userBank = { .bankSize = 0, .bankAddress = 0 },
  60. };
  61. #if AT45DBXXX_POWER_MANAGEMENT || AT45DBXXX_RESET_MANAGEMENT || AT45DBXXX_HW_WR_PROTECT
  62. const ExtMemPins_Handle_AT45_t ExtMemPinsHandle_AT45 =
  63. {
  64. #if AT45DBXXX_POWER_MANAGEMENT
  65. .SetPinPowerOn = ExtMem_SetPinPowerOn,
  66. .SetPinPowerOff = ExtMem_SetPinPowerOff,
  67. #endif
  68. #if AT45DBXXX_RESET_MANAGEMENT
  69. .ResetPinAssert = ExtMem_ResetPinAssert,
  70. .ResetPinRelease = ExtMem_ResetPinRelease,
  71. #endif
  72. #if AT45DBXXX_HW_WR_PROTECT
  73. .HwWrProtPinAssert = ExtMem_HwWrProtPinAssert,
  74. .HwWrProtPinRelease = ExtMem_HwWrProtPinRelease,
  75. #endif
  76. };
  77. #endif
  78. #if W25QXXX_POWER_MANAGEMENT || W25QXXX_RESET_MANAGEMENT || W25QXXX_HW_WR_PROTECT
  79. const ExtMemPins_Handle_W25Q_t ExtMemPinsHandle_W25Q =
  80. {
  81. #if W25QXXX_POWER_MANAGEMENT
  82. .SetPinPowerOn = ExtMem_SetPinPowerOn,
  83. .SetPinPowerOff = ExtMem_SetPinPowerOff,
  84. #endif
  85. #if W25QXXX_RESET_MANAGEMENT
  86. .ResetPinAssert = ExtMem_ResetPinAssert,
  87. .ResetPinRelease = ExtMem_ResetPinRelease,
  88. #endif
  89. #if W25QXXX_HW_WR_PROTECT
  90. .HwWrProtPinAssert = ExtMem_HwWrProtPinAssert,
  91. .HwWrProtPinRelease = ExtMem_HwWrProtPinRelease,
  92. #endif
  93. };
  94. #endif
  95. static const char Malfunction_FlashProperties_Description[] = "";
  96. static const flash_properties_t Malfunction_FlashProperties =
  97. {
  98. .minAddress = 0,
  99. .maxAddress = 0,
  100. .maxSectors = 0,
  101. .sectorSize = 0,
  102. .pChipDescription = Malfunction_FlashProperties_Description,
  103. };
  104. static const ExtMem_Banks_Properties_t Malfunction_BanksProperties =
  105. {
  106. .factoryBankSize = 0,
  107. .userBankSize = 0,
  108. .factoryBankAddress = 0,
  109. .userBankAddress = 0,
  110. };
  111. // Function stub
  112. static bool Malfunction_ExtMem_Write( flash_address_t address, __FLASH_BYTE * pBuffer, flash_address_t size )
  113. {
  114. return false;
  115. }
  116. // Function stub
  117. static bool Malfunction_ExtMem_Read( flash_address_t address, __FLASH_BYTE * pBuffer, flash_address_t size )
  118. {
  119. return false;
  120. }
  121. // Function stub
  122. static bool Malfunction_ExtMem_RangeCheck_Read( flash_address_t address, flash_address_t size )
  123. {
  124. return false;
  125. }
  126. // Function stub
  127. static bool Malfunction_ExtMem_RangeCheck_Write( flash_address_t address, flash_address_t size )
  128. {
  129. return false;
  130. }
  131. // Function stub
  132. static bool Malfunction_ExtMem_BankProtect( eExtMem_Bank_t bankId, bool protectStatus )
  133. {
  134. return false;
  135. }
  136. // Function stub
  137. static bool Malfunction_ExtMem_CheckBankProtect( eExtMem_Bank_t bankId, bool * pActualProtectStatus )
  138. {
  139. return false;
  140. }
  141. // Exporting External Memory descriptor
  142. ExtMem_Handle_t ExtMemHandle = {
  143. .Init = ExtMem_Init, // Always set to actual value
  144. .Write = Malfunction_ExtMem_Write, // will be set after Init()
  145. .Read = Malfunction_ExtMem_Read, // will be set after Init()
  146. .RangeCheck_Read = Malfunction_ExtMem_RangeCheck_Read, // will be set after Init()
  147. .RangeCheck_Write = Malfunction_ExtMem_RangeCheck_Write, // will be set after Init()
  148. .BankProtect = Malfunction_ExtMem_BankProtect, // will be set after Init()
  149. .CheckBankProtect = Malfunction_ExtMem_CheckBankProtect, // will be set after Init()
  150. .DeInit = ExtMem_DeInit, // Always set to actual value
  151. .pFlashProperties = &Malfunction_FlashProperties, // will be set after Init()
  152. .pBanksProperties = &Malfunction_BanksProperties // will be set after Init()
  153. };
  154. // // Current Model Memory Template: Bank 0 (Factory)
  155. // // [WRONG]
  156. // #warning Remove this line as soon as the following entity has been validated
  157. // const static sMemoryBankingTemplate_t ACMMemory_Bank0 = {
  158. //
  159. // .selectRegister = {
  160. // .loprotect = 0x000000FE, // First 4MBit (actually 7MBit, the bigger the better)
  161. // // First Sector 0 is skipped, and Sectors 1..7 is used as Bank0.
  162. // // Each sector = 128KBytes
  163. // .hiprotect = 0x00000000,
  164. // }
  165. //
  166. // };
  167. //
  168. // // 16MBit flash AT45DB161E is installed;
  169. // // But the application supposes that only 8MBit (4+4Mbits) is presents.
  170. // // So it adresses first 4MBit as a factory bank, and the second as
  171. // // a user bank. The rest part is useless.
  172. //
  173. // // Current Model Memory Template: Bank 1 (User)
  174. // // [WRONG]
  175. // #warning Remove this line as soon as the following entity has been validated
  176. // const static sMemoryBankingTemplate_t ACMMemory_Bank1 = {
  177. //
  178. // .selectRegister = {
  179. // .loprotect = 0x0000FF00, // Second 4MBit (actually 8MBit, the bigger the better)
  180. // // Sectors 8..15 is used as Bank1.
  181. // .hiprotect = 0x00000000,
  182. // }
  183. //
  184. // };
  185. // @ACMMemory_BankX: Dynamically filled template for sector protection operation
  186. static sMemoryBankingTemplate_t ACMMemory_BankX;
  187. // ExtMem_DeInit()
  188. // De-Initializes external memory driver.
  189. // Makes the chip fall asleep.
  190. // @bForce: if 'false' the function will detect if the chip
  191. // is busy and interrupt the operation with error.
  192. // If 'true', the function ignores current chip state and makes it
  193. // fall asleep instantly.
  194. // Returns 'true' in success case, and 'false' otherwise.
  195. bool ExtMem_DeInit( bool bForce )
  196. {
  197. // Clear status
  198. bExtMemStatus = false;
  199. // Check if the driver is loaded
  200. if( NULL != flashDriver )
  201. {
  202. #if EXTMEM_HIBERNATE_ENABLED
  203. // Make flash chip fall asleep
  204. if( FLASH_ERROR( flashDriver->api->routines.flashFinalize( true, bForce ) ) )
  205. #else
  206. // Deinitialize driver
  207. if( FLASH_ERROR( flashDriver->api->routines.flashFinalize( false, bForce ) ) )
  208. #endif
  209. {
  210. return false;
  211. }
  212. }
  213. // de-initialize SPI driver
  214. pSPIHandle->DeInit();
  215. // De-Initialize power- and reset- management pins
  216. ExtMem_Pins_Deinit();
  217. // clear routines and data
  218. ExtMemHandle.Write = Malfunction_ExtMem_Write;
  219. ExtMemHandle.Read = Malfunction_ExtMem_Read;
  220. ExtMemHandle.RangeCheck_Read = Malfunction_ExtMem_RangeCheck_Read;
  221. ExtMemHandle.RangeCheck_Write = Malfunction_ExtMem_RangeCheck_Write;
  222. ExtMemHandle.BankProtect = Malfunction_ExtMem_BankProtect;
  223. ExtMemHandle.CheckBankProtect = Malfunction_ExtMem_CheckBankProtect;
  224. ExtMemHandle.pFlashProperties = &Malfunction_FlashProperties;
  225. ExtMemHandle.pBanksProperties = &Malfunction_BanksProperties;
  226. // set status and return
  227. return true;
  228. }
  229. // ExtMem_DriverLoad
  230. // Detects the chip on the bus and returns the appropriate driver to control it
  231. static const ExtMemDriver_t * ExtMem_DriverLoad()
  232. {
  233. for( size_t flash_driver_active = 0; flash_driver_active < sizeof(flash_drivers)/sizeof(flash_drivers[0]); ++flash_driver_active )
  234. {
  235. if( FLASH_SUCCESS(flash_drivers[ flash_driver_active ].api->routines.flashInitialize( true ) ) )
  236. {
  237. return &flash_drivers[ flash_driver_active ];
  238. }
  239. }
  240. return NULL; // driver not found
  241. }
  242. // ExtMem_Init()
  243. // Initializes external memory driver.
  244. // Wakes the memory chip up if it is necessary.
  245. // Returns 'true' in success case, and 'false' otherwise.
  246. bool ExtMem_Init()
  247. {
  248. // Clear status
  249. bExtMemStatus = false;
  250. // Initialize power- and reset- management pins
  251. ExtMem_Pins_Init();
  252. // initialize SPI driver
  253. pSPIHandle->Init();
  254. // Detect chip and load driver
  255. flashDriver = ExtMem_DriverLoad();
  256. // Check if the driver is loaded
  257. if( NULL == flashDriver )
  258. {
  259. // deinitialize power- and reset- management pins
  260. ExtMem_Pins_Deinit();
  261. // de-initialize SPI driver
  262. pSPIHandle->DeInit();
  263. return false;
  264. }
  265. // Check boundaries
  266. if( flashDriver->api->flashProperties->minAddress >= flashDriver->api->flashProperties->maxAddress )
  267. return false;
  268. // Check sizes
  269. if( flashDriver->api->flashProperties->maxSectors == 0 || flashDriver->api->flashProperties->sectorSize == 0 )
  270. return false;
  271. // Update banks properties with actual values
  272. ActualBankProperties.factoryBankSize = EXTMEM_BANK0_SIZE;
  273. ActualBankProperties.userBankSize = EXTMEM_BANK1_SIZE;
  274. ActualBankProperties.factoryBankAddress = flashDriver->api->flashProperties->minAddress;
  275. ActualBankProperties.userBankAddress = flashDriver->api->flashProperties->minAddress + ActualBankProperties.factoryBankSize;
  276. // Check the Bank sizes:
  277. // the banks can not share one sector, the sector can be owned by only one bank.
  278. if( ((ActualBankProperties.factoryBankSize % flashDriver->api->flashProperties->sectorSize > 0 )?(flashDriver->api->flashProperties->sectorSize):(0))
  279. +((ActualBankProperties.userBankSize % flashDriver->api->flashProperties->sectorSize > 0 )?(flashDriver->api->flashProperties->sectorSize):(0))
  280. +( ActualBankProperties.factoryBankSize + ActualBankProperties.userBankSize)
  281. > flashDriver->api->flashProperties->maxSectors * flashDriver->api->flashProperties->sectorSize )
  282. {
  283. return false;
  284. }
  285. // initialize driver routines and data
  286. ExtMemHandle.Write = ExtMem_Write;
  287. ExtMemHandle.Read = ExtMem_Read;
  288. ExtMemHandle.RangeCheck_Read = ExtMem_RangeCheck_Read;
  289. ExtMemHandle.RangeCheck_Write = ExtMem_RangeCheck_Write;
  290. ExtMemHandle.BankProtect = ExtMem_BankProtect;
  291. ExtMemHandle.CheckBankProtect = ExtMem_CheckBankProtect;
  292. ExtMemHandle.pFlashProperties = flashDriver->api->flashProperties;
  293. ExtMemHandle.pBanksProperties = &ActualBankProperties;
  294. // Initialize flash driver
  295. if( FLASH_ERROR( flashDriver->api->routines.flashInitialize(false) ) )
  296. {
  297. // finalize after initialization fail
  298. flashDriver->api->routines.flashFinalize( false, true );
  299. // deinitialize power- and reset- management pins
  300. ExtMem_Pins_Deinit();
  301. // de-initialize SPI driver
  302. pSPIHandle->DeInit();
  303. // flash driver initialization error
  304. return false;
  305. }
  306. // set status and return
  307. return (bExtMemStatus = true);
  308. }
  309. // ExtMem_Internal_FillBankingTemplate
  310. // Calculates the sMemoryBankingTemplate_t structure during run-time.
  311. // Function relies on the bank properties passed in @pBankProperties.
  312. static void ExtMem_Internal_FillBankingTemplate( const ExtMem_Bank_Properties_t * pBankProperties, sMemoryBankingTemplate_t * pFactoryProtectionTemplate )
  313. {
  314. // The first bank's sector (including the sector)
  315. size_t factoryBankSectorBegin = __FLASH_ADDRESS2SECTOR_BEGIN(pBankProperties->bankAddress, ExtMemHandle.pFlashProperties->sectorSize);
  316. // The last bank's sector (including the sector)
  317. size_t factoryBankSectorEnd = __FLASH_ADDRESS2SECTOR_END(pBankProperties->bankAddress + pBankProperties->bankSize, ExtMemHandle.pFlashProperties->sectorSize);
  318. // Fill the structure with zeros before operation
  319. for( size_t nZero = 0; nZero < sizeof(pFactoryProtectionTemplate->selectRegister); ++nZero )
  320. {
  321. pFactoryProtectionTemplate->selectRegister.bytes[nZero] = 0;
  322. }
  323. // Mark the affected sectors in the output structure
  324. for( size_t nSector = factoryBankSectorBegin; nSector < factoryBankSectorEnd; ++nSector )
  325. {
  326. BITBUFFER_SET( pFactoryProtectionTemplate->selectRegister.bytes, nSector );
  327. }
  328. }
  329. // Initialize ExtMem power- and reset- management GPIO-pins
  330. static void ExtMem_Pins_Init()
  331. {
  332. #if W25QXXX_RESET_MANAGEMENT || AT45DBXXX_RESET_MANAGEMENT
  333. // Configure GPIO pins for AT45 IC : reset signal
  334. GPIO_InitTypeDef GPIO_InitStruct = {0};
  335. // Configure as input to detect actual level:
  336. GPIO_InitStruct.Pin = CONFIG_PIN__EXTMEM__RST;
  337. GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  338. GPIO_InitStruct.Pull = GPIO_NOPULL;
  339. HAL_GPIO_Init(CONFIG_PORT__EXTMEM__RST, &GPIO_InitStruct);
  340. // read actual level
  341. GPIO_PinState xPreservedState = HAL_GPIO_ReadPin( CONFIG_PORT__EXTMEM__RST, CONFIG_PIN__EXTMEM__RST );
  342. // Configure as analog
  343. GPIO_InitStruct.Pin = CONFIG_PIN__EXTMEM__RST;
  344. GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
  345. GPIO_InitStruct.Pull = GPIO_NOPULL;
  346. HAL_GPIO_Init(CONFIG_PORT__EXTMEM__RST, &GPIO_InitStruct);
  347. // prepare pin state:
  348. HAL_GPIO_WritePin( CONFIG_PORT__EXTMEM__RST, CONFIG_PIN__EXTMEM__RST, xPreservedState );
  349. // Configure as output:
  350. GPIO_InitStruct.Pin = CONFIG_PIN__EXTMEM__RST;
  351. GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
  352. GPIO_InitStruct.Pull = GPIO_PULLUP;
  353. HAL_GPIO_Init(CONFIG_PORT__EXTMEM__RST, &GPIO_InitStruct);
  354. #endif
  355. }
  356. // De-Initialize ExtMem power- and reset- management GPIO-pins
  357. static void ExtMem_Pins_Deinit()
  358. {
  359. #if W25QXXX_RESET_MANAGEMENT || AT45DBXXX_RESET_MANAGEMENT
  360. // Configure GPIO pins for AT45 IC : PB10=nWP (reset signal)
  361. GPIO_InitTypeDef GPIO_InitStruct = {0};
  362. GPIO_InitStruct.Pin = CONFIG_PIN__EXTMEM__RST;
  363. GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
  364. GPIO_InitStruct.Pull = GPIO_NOPULL;
  365. HAL_GPIO_Init(CONFIG_PORT__EXTMEM__RST, &GPIO_InitStruct);
  366. #endif
  367. }
  368. typedef struct
  369. {
  370. // Actual protection bits for all sectors:
  371. __FLASH_DWORD actual_protection_mask_lo;
  372. __FLASH_DWORD actual_protection_mask_hi;
  373. // Desired protection bits for selected sectors:
  374. __FLASH_DWORD desired_protection_mask_lo;
  375. __FLASH_DWORD desired_protection_mask_hi;
  376. union
  377. {
  378. bool globalProtectionStatus; // AT25
  379. bool anySectorProtectionStatus; // W25Q
  380. };
  381. bool individualProtectionStatus;
  382. }
  383. sProtectionEntry_t;
  384. // Queries actual protection information from the flash-memory and fills the [sProtectionEntry_t] structure.
  385. // If required, fills the protection register that can be used to set the protection information
  386. // @bankId = memory bank identifier;
  387. // @desiredProtectStatus = desired protecion state
  388. // @protEntry = pointer to the [sProtectionEntry_t] structure to fill, mandatory.
  389. // @setProtectRegister = pointer to the set-protection register to fill, optional, it then can be used by flash_protect_ex()
  390. // Returns the operaion status, true if succeded, false otherwise.
  391. // The actual protection state will be returned in @protEntry.
  392. static bool ExtMem_Internal_FillProtectionEntry( eExtMem_Bank_t bankId, bool desiredProtectStatus, sProtectionEntry_t * pProtEntry, flash_api_protect_t * setProtectRegister )
  393. {
  394. sMemoryBankingTemplate_t * pBankTemplate = NULL;
  395. flash_api_getprotect_t getProtectRegister;
  396. // Check if the driver is loaded
  397. if( NULL == flashDriver ) return false;
  398. if( NULL != pProtEntry )
  399. {
  400. // This function uses individual sector protecton
  401. //
  402. switch( bankId )
  403. {
  404. case extmem_bank_factory:
  405. {
  406. pBankTemplate = &ACMMemory_BankX;
  407. // use dynamic template for FACTORY bank
  408. ExtMem_Internal_FillBankingTemplate( &ExtMemHandle.pBanksProperties->factoryBank, pBankTemplate );
  409. }
  410. break;
  411. case extmem_bank_user:
  412. {
  413. pBankTemplate = &ACMMemory_BankX;
  414. // use dynamic template for USER bank
  415. ExtMem_Internal_FillBankingTemplate( &ExtMemHandle.pBanksProperties->userBank, pBankTemplate );
  416. }
  417. break;
  418. }
  419. if( NULL != pBankTemplate )
  420. {
  421. // Retrieve currect sector protection register:
  422. if( FLASH_SUCCESS( flashDriver->api->routines.flashGetProtect( &getProtectRegister ) ) )
  423. {
  424. // Get actual protection bits for all sectors:
  425. pProtEntry->actual_protection_mask_lo = getProtectRegister.sectors.loprotect;
  426. pProtEntry->actual_protection_mask_hi = getProtectRegister.sectors.hiprotect;
  427. // Initialize desired protection bits for selected sectors:
  428. pProtEntry->desired_protection_mask_lo = ((desiredProtectStatus)?0xFFFFFFFF:0x00000000);
  429. pProtEntry->desired_protection_mask_hi = ((desiredProtectStatus)?0xFFFFFFFF:0x00000000);
  430. // Filter only selected sectors (specified by selection register on memory bank template)
  431. pProtEntry->actual_protection_mask_lo &= pBankTemplate->selectRegister.loprotect;
  432. pProtEntry->actual_protection_mask_hi &= pBankTemplate->selectRegister.hiprotect;
  433. pProtEntry->desired_protection_mask_lo &= pBankTemplate->selectRegister.loprotect;
  434. pProtEntry->desired_protection_mask_hi &= pBankTemplate->selectRegister.hiprotect;
  435. // Compare actual and desired sector protection status:
  436. if( pProtEntry->actual_protection_mask_lo != pProtEntry->desired_protection_mask_lo
  437. ||
  438. pProtEntry->actual_protection_mask_hi != pProtEntry->desired_protection_mask_hi )
  439. {
  440. // PROTECTION STATUS: SOME SECTORS HAVE INCORRECT PROTECTION FLAGS
  441. pProtEntry->individualProtectionStatus = false;
  442. if( NULL != setProtectRegister )
  443. {
  444. // Do not change COMMON PROTECTION FLAG:
  445. setProtectRegister->protection_modify = flash_sector_protect_nomodify;
  446. // Mark selected sectors to be protected:
  447. setProtectRegister->protection_enabled = flash_sector_protect_pick;
  448. // Copy sectors selection mask:
  449. setProtectRegister->sectors.loprotect = pBankTemplate->selectRegister.loprotect;
  450. setProtectRegister->sectors.hiprotect = pBankTemplate->selectRegister.hiprotect;
  451. }
  452. }
  453. else
  454. {
  455. // PROTECTION STATUS: ALL SECTORS HAVE CORRECT PROTECTION FLAGS
  456. pProtEntry->individualProtectionStatus = true;
  457. }
  458. // QUERY GLOBAL PROTECTION FLAG
  459. switch( flashDriver->api->routines.flashGetProtect( NULL ) )
  460. {
  461. case FLERR_PROTECT_ENABLED:
  462. pProtEntry->globalProtectionStatus = true;
  463. return true;
  464. case FLERR_PROTECT_DISABLED:
  465. pProtEntry->globalProtectionStatus = false;
  466. return true;
  467. }
  468. }
  469. }
  470. }
  471. return false;
  472. }
  473. // ExtMem_BankProtect()
  474. // Implements external memory protection by Memory Bank Identifier
  475. // @bankId = memory bank identifier;
  476. // @desiredProtectStatus - protection status (true=protected, false=unprotected)
  477. // Returns the result of operation
  478. static bool ExtMem_BankProtect( eExtMem_Bank_t bankId, bool desiredProtectStatus )
  479. {
  480. sProtectionEntry_t protEntry_Bank0; // protection information for Bank0
  481. sProtectionEntry_t protEntry_Bank1; // protection information for Bank1
  482. // Check if the driver is loaded
  483. if( NULL == flashDriver ) return false;
  484. // --------------------
  485. if( extmem_bank_factory != bankId
  486. &&
  487. extmem_bank_user != bankId )
  488. {
  489. return false; // error
  490. }
  491. // --------------------
  492. // Query actual protection information for both banks
  493. // Argument ExtMem_Internal_FillProtectionEntry(... @desiredProtectStatus = true ...):
  494. // that ensures that all sectors are protected with individual protection flags.
  495. if( ExtMem_Internal_FillProtectionEntry( extmem_bank_factory, true, &protEntry_Bank0, NULL )
  496. &&
  497. ExtMem_Internal_FillProtectionEntry( extmem_bank_user, true, &protEntry_Bank1, NULL ) )
  498. {
  499. // Actual bank's protection state is depends on the global protection state and the individual protection state for bank
  500. bool stateBank0 = ( protEntry_Bank0.individualProtectionStatus && protEntry_Bank0.globalProtectionStatus );
  501. bool stateBank1 = ( protEntry_Bank1.individualProtectionStatus && protEntry_Bank1.globalProtectionStatus );
  502. // Check if current bank's protection state matchs to desired state
  503. if(
  504. (( extmem_bank_factory == bankId ) && ( desiredProtectStatus == stateBank0 ))
  505. ||
  506. (( extmem_bank_user == bankId ) && ( desiredProtectStatus == stateBank1 ))
  507. )
  508. {
  509. // All bank's protection statuses are correct, no operations are required
  510. return true; // success
  511. }
  512. else // Only if current state and the desired state mismatch:
  513. {
  514. // The global protection state must be set if at least one bank must be protected.
  515. bool requiredGlobalState = (( extmem_bank_factory == bankId )?desiredProtectStatus:stateBank0)
  516. ||
  517. (( extmem_bank_user == bankId )?desiredProtectStatus:stateBank1);
  518. if( requiredGlobalState )
  519. {
  520. // If global protection state will be set
  521. // Ensure that all banks have correct individual sector protection flags:
  522. // Remember: @requiredGlobalState is true
  523. if( protEntry_Bank0.individualProtectionStatus != (( extmem_bank_factory == bankId )?desiredProtectStatus:stateBank0) )
  524. {
  525. // @individualProtectionStatus does not match to the desired state
  526. flash_api_protect_t setProtectRegister; // set-protection register
  527. // new bank protection status
  528. stateBank0 = !protEntry_Bank0.individualProtectionStatus;
  529. // Query actual protection information for both banks
  530. // Specify argument ExtMem_Internal_FillProtectionEntry(... @desiredProtectStatus ...) to
  531. // the inverted @individualProtectionStatus state, because current @individualProtectionStatus value is wrong
  532. if( !ExtMem_Internal_FillProtectionEntry( extmem_bank_factory, stateBank0, &protEntry_Bank0, &setProtectRegister ) )
  533. {
  534. // query error
  535. return false;
  536. }
  537. // Execute operation: modify only individual sectors protection marks to the desired state
  538. if( FLASH_ERROR( flashDriver->api->routines.flashProtectEx( &setProtectRegister,
  539. (( stateBank0 )?(flash_sector_protected):(flash_sector_unprotected))
  540. ) ) )
  541. {
  542. // Error: can not modify individual sector protection flags
  543. return false;
  544. }
  545. }
  546. if( protEntry_Bank1.individualProtectionStatus != (( extmem_bank_user == bankId )?desiredProtectStatus:stateBank1) )
  547. {
  548. // @individualProtectionStatus does not match to the desired state
  549. flash_api_protect_t setProtectRegister; // set-protection register
  550. // new bank protection status
  551. stateBank1 = !protEntry_Bank1.individualProtectionStatus;
  552. // Query actual protection information for both banks
  553. // Specify argument ExtMem_Internal_FillProtectionEntry(... @desiredProtectStatus ...) to
  554. // the inverted @individualProtectionStatus state, because current @individualProtectionStatus value is wrong
  555. if( !ExtMem_Internal_FillProtectionEntry( extmem_bank_user, stateBank1, &protEntry_Bank1, &setProtectRegister ) )
  556. {
  557. // query error
  558. return false;
  559. }
  560. // Execute operation: modify only individual sectors protection marks to the desired state
  561. if( FLASH_ERROR( flashDriver->api->routines.flashProtectEx( &setProtectRegister,
  562. (( stateBank1 )?(flash_sector_protected):(flash_sector_unprotected))
  563. ) ) )
  564. {
  565. // Error: can not modify individual sector protection flags
  566. return false;
  567. }
  568. }
  569. // Modify global write-protection flag: protected
  570. // W25Q: stub call, always return FLERR_SUCCESS
  571. return FLASH_SUCCESS( flashDriver->api->routines.flashProtect( NULL ) );
  572. }
  573. else
  574. {
  575. // If global protection state will be reset: all banks must be unprotected
  576. // Modify global write-protection flag: unprotected
  577. return FLASH_SUCCESS( flashDriver->api->routines.flashUnprotect( NULL ) );
  578. }
  579. }
  580. }
  581. return false; // error
  582. }
  583. // ExtMem_CheckBankProtect()
  584. // Implements external memory protection by Memory Bank Identifier
  585. // @bankId = memory bank identifier;
  586. // @pActualProtectStatus - pointer to the boolean variable to receive actual protection status
  587. // Returns the result of operation
  588. static bool ExtMem_CheckBankProtect( eExtMem_Bank_t bankId, bool * pActualProtectStatus )
  589. {
  590. sProtectionEntry_t protEntry;
  591. if( NULL != pActualProtectStatus )
  592. {
  593. // Query current protection information
  594. if( ExtMem_Internal_FillProtectionEntry( bankId, true, &protEntry, NULL ) )
  595. {
  596. *pActualProtectStatus = (protEntry.globalProtectionStatus) && (protEntry.individualProtectionStatus);
  597. return true; // success, no operations are required
  598. }
  599. }
  600. return false; // error
  601. }
  602. #if AT45DBXXX_POWER_MANAGEMENT
  603. // Implement ExtMem power-management: set power enable pin
  604. static void ExtMem_SetPinPowerOn()
  605. {
  606. #error Not-implemented
  607. }
  608. // Implement ExtMem power-management: set power disable pin
  609. static void ExtMem_SetPinPowerOff()
  610. {
  611. #error Not-implemented
  612. }
  613. #endif
  614. #if AT45DBXXX_RESET_MANAGEMENT
  615. // Implement ExtMem reset-management: set reset enable pin
  616. static void ExtMem_ResetPinAssert()
  617. {
  618. HAL_GPIO_WritePin( CONFIG_PORT__EXTMEM__RST, CONFIG_PIN__EXTMEM__RST, GPIO_PIN_RESET );
  619. }
  620. // Implement ExtMem reset-management: set reset disable pin
  621. static void ExtMem_ResetPinRelease()
  622. {
  623. HAL_GPIO_WritePin( CONFIG_PORT__EXTMEM__RST, CONFIG_PIN__EXTMEM__RST, GPIO_PIN_SET );
  624. }
  625. #endif
  626. #if AT45DBXXX_HW_WR_PROTECT
  627. // Implement ExtMem hardware-write-protection: enable write protection
  628. static void ExtMem_HwWrProtPinAssert()
  629. {
  630. #error Not-implemented
  631. }
  632. // Implement ExtMem hardware-write-protection: disable write protection
  633. static void ExtMem_HwWrProtPinRelease()
  634. {
  635. #error Not-implemented
  636. }
  637. #endif
  638. #if CONFIG_EXTMEM_EMULATEWRITE
  639. static bool ExtMem_Write( flash_address_t address, __FLASH_BYTE * pBuffer, flash_address_t size )
  640. {
  641. return true;
  642. }
  643. #else
  644. static bool ExtMem_Write( flash_address_t address, __FLASH_BYTE * pBuffer, flash_address_t size )
  645. {
  646. // Check if the driver is loaded
  647. if( NULL == flashDriver ) return false;
  648. extern volatile bool bExtMemStatus;
  649. return bExtMemStatus && FLASH_SUCCESS( flashDriver->api->routines.flashWrite( flashDriver->api->flashProperties->minAddress + address, pBuffer, size, fwm_safewrite ) );
  650. }
  651. #endif
  652. #if CONFIG_EXTMEM_EMULATEREAD
  653. static bool ExtMem_Read( flash_address_t address, __FLASH_BYTE * pBuffer, flash_address_t size )
  654. {
  655. memset( pBuffer, 0xDE, size );
  656. return true;
  657. }
  658. #else
  659. static bool ExtMem_Read( flash_address_t address, __FLASH_BYTE * pBuffer, flash_address_t size )
  660. {
  661. // Check if the driver is loaded
  662. if( NULL == flashDriver ) return false;
  663. extern volatile bool bExtMemStatus;
  664. return bExtMemStatus && FLASH_SUCCESS( flashDriver->api->routines.flashRead( flashDriver->api->flashProperties->minAddress + address, pBuffer, size ) );
  665. }
  666. #endif
  667. static bool ExtMem_RangeCheck_Read( flash_address_t address, flash_address_t size )
  668. {
  669. // Check if the driver is loaded
  670. if( NULL == flashDriver ) return false;
  671. if( size <= (flashDriver->api->flashProperties->maxAddress - flashDriver->api->flashProperties->minAddress) )
  672. {
  673. if( address < flashDriver->api->flashProperties->maxAddress - flashDriver->api->flashProperties->minAddress - size )
  674. {
  675. return true;
  676. }
  677. }
  678. return false;
  679. }
  680. static bool ExtMem_RangeCheck_Write( flash_address_t address, flash_address_t size )
  681. {
  682. // Check if the driver is loaded
  683. if( NULL == flashDriver ) return false;
  684. if( size <= (flashDriver->api->flashProperties->maxAddress - flashDriver->api->flashProperties->minAddress) )
  685. {
  686. if( address < flashDriver->api->flashProperties->maxAddress - flashDriver->api->flashProperties->minAddress - size )
  687. {
  688. return true;
  689. }
  690. }
  691. return false;
  692. }
  693. // legacy compatibility
  694. flash_err_t flash_read( flash_address_t address, __FLASH_BYTE * pBuffer, flash_address_t size )
  695. {
  696. // Check if the driver is loaded
  697. if( NULL == flashDriver ) return FLERR_DEVICE_MALFUNCTION;
  698. extern volatile bool bExtMemStatus;
  699. if( bExtMemStatus )
  700. return flashDriver->api->routines.flashRead( address, pBuffer, size );
  701. return FLERR_DEVICE_MALFUNCTION; // !bExtMemStatus
  702. }
  703. // legacy compatibility
  704. flash_err_t flash_write( flash_address_t address, __FLASH_BYTE * pBuffer, flash_address_t size, flash_write_mode_t unused )
  705. {
  706. // Check if the driver is loaded
  707. if( NULL == flashDriver ) return FLERR_DEVICE_MALFUNCTION;
  708. extern volatile bool bExtMemStatus;
  709. (void)unused;
  710. if( bExtMemStatus )
  711. return flashDriver->api->routines.flashWrite( address, pBuffer, size, fwm_safewrite );
  712. return FLERR_DEVICE_MALFUNCTION; // !bExtMemStatus
  713. }