W25Q16JV_API.c 67 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623
  1. // Файл с API функциями работы с FLASH-чипом W25Q16JV
  2. // v 1.0 от 14/10/20
  3. // Автор: Сычев А.
  4. #define W25Q16JV_API_C
  5. #define W25Q16JV_APILEVEL // использование интерфейса низкоуровневых функций
  6. #include "drivers\flash\w25q\config\W25Q16JV_CONF.h"
  7. #include "drivers\flash\base\flash_api_error.h"
  8. #include "drivers\flash\base\flash_api_types.h"
  9. #include "drivers\flash\base\flash_api_base.h"
  10. #include "drivers\flash\w25q\lowlevel\W25Q16JV_GLOB.h"
  11. #include "drivers\flash\w25q\lowlevel\W25Q16JV_LL_func.h"
  12. #include "drivers\flash\w25q\common\W25Q_HAL.h"
  13. // внутренний дескриптор LL-буфера
  14. typedef struct
  15. {
  16. union
  17. {
  18. void * rawptr;
  19. __flash_sectorprotectionregister_t * pSectorProtectionRegister;
  20. __FLASH_BYTE * pageBuffer;
  21. };
  22. size_t size;
  23. }
  24. flash_LL_buf_t;
  25. static const char W25QFLASH_TEXTUAL_DESCRIPTION[] = "W25Q16JV";
  26. // дескриптор конфигурации памяти
  27. static const flash_properties_t FlashProperties_W25Q16JV =
  28. {
  29. .minAddress = W25QFLASH_MINIMUM_ADDRESS,
  30. .maxAddress = W25QFLASH_MAXIMUM_ADDRESS,
  31. .maxSectors = W25QFLASH_SECTORS,
  32. .sectorSize = (W25QFLASH_PAGES_PER_SECTOR * W25QFLASH_PAGE_SIZE),
  33. .pChipDescription = W25QFLASH_TEXTUAL_DESCRIPTION
  34. };
  35. // flash_api_initialize - инициализация драйвера и API работы с устройством
  36. static flash_err_t flash_api_initialize( bool detectOnly );
  37. // flash_api_getready - проверка готовности устройства (со стандартным таймаутом)
  38. static flash_err_t flash_api_getready();
  39. // flash_api_service - функция получения общих сведений об флеш-памяти.
  40. static flash_err_t flash_api_service( flash_service_info_t si, void * pdata, __FLASH_WORD * pbufsize );
  41. // flash_api_protect - установить защиту секторов
  42. static flash_err_t flash_api_protect( flash_api_protect_t * content );
  43. // flash_api_unprotect - снять защиту секторов
  44. static flash_err_t flash_api_unprotect( flash_api_protect_t * content );
  45. // flash_api_protect_ex - установить/снять защиту секторов
  46. static flash_err_t flash_api_protect_ex( flash_api_protect_t * content, flash_api_protect_bits mode );
  47. // flash_api_getprotect - получить информацию о защищенных секторах.
  48. static flash_err_t flash_api_getprotect( flash_api_getprotect_t * content );
  49. // flash_api_erase - мультирежимное стирание данных
  50. static flash_err_t flash_api_erase( flash_erase_mode_t mode, __FLASH_DWORD start, __FLASH_DWORD count );
  51. // flash_api_write - мультирежимная запись данных по адресу
  52. static flash_err_t flash_api_write( flash_address_t address, __FLASH_BYTE * pBuffer, flash_address_t size, flash_write_mode_t mode );
  53. // flash_api_read - чтение данных по адресу
  54. static flash_err_t flash_api_read( flash_address_t address, __FLASH_BYTE * pBuffer, flash_address_t size );
  55. // flash_api_sleepmode - переход в режим пониженного энергопотребления
  56. static flash_err_t flash_api_sleepmode();
  57. // flash_api_wakeup - выход из режима пониженного энергопотребления
  58. static flash_err_t flash_api_wakeup();
  59. // flash_api_finalize - деинициализация драйвера
  60. static flash_err_t flash_api_finalize( bool bHibernate, bool bForce );
  61. // дескриптор API
  62. const flash_api_descriptor_t W25Q16JV_API =
  63. {
  64. .routines = {
  65. .flashInitialize = flash_api_initialize,
  66. .flashGetReady = flash_api_getready,
  67. .flashService = flash_api_service,
  68. .flashProtect = flash_api_protect,
  69. .flashUnprotect = flash_api_unprotect,
  70. .flashProtectEx = flash_api_protect_ex,
  71. .flashGetProtect = flash_api_getprotect,
  72. .flashErase = flash_api_erase,
  73. .flashWrite = flash_api_write,
  74. .flashRead = flash_api_read,
  75. .flashSleepMode = flash_api_sleepmode,
  76. .flashWakeup = flash_api_wakeup,
  77. .flashFinalize = flash_api_finalize,
  78. },
  79. .flashProperties = &FlashProperties_W25Q16JV
  80. };
  81. // Enter() и Return(.) - макросы блокировки ресурса в многозадачных ОС
  82. // При входе в критический участок кода - выполнение API функции - вызывается Enter(),
  83. // блокируя ресурс, при выходе - Leave() или Return(.) ( для выхода из функции )
  84. #define Enter() { __FLASH_LOCK(); }
  85. #define Leave() { __FLASH_UNLOCK(); }
  86. #define Return(code) { __FLASH_UNLOCK(); return (code); }
  87. //#define ret __FLASH_UNLOCK(); return
  88. // Done:
  89. // flash_api_initialize(...) // Высокоуровневая инициализация памяти (установка размера страницы, установка параметров защиты секторов...)
  90. // flash_api_erase(...) // стирание памяти (блоками, страницами или секторами)
  91. // flash_api_read(...) // чтение памяти по адресу
  92. // flash_api_protect(...) // защита секторов (модификация конфигурации защищаемых секторов)
  93. // flash_api_unprotect(...) // снятие защиты (модификация конфигурации защищаемых секторов)
  94. // flash_api_service(...) // получение информации о производителе, расширенной информации, размере памяти, размере страницы, количестве секторов, блоков, страниц и т.п.
  95. // flash_api_write(...) // запись памяти по адресу
  96. // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
  97. // flash_api_getready - проверка готовности устройства (со стандартным таймаутом)
  98. //
  99. // # Функция возвращает FLERR_SUCCESS, еслиу устройство готово, иначе FLERR_TIMEOUT
  100. static flash_err_t flash_api_getready() // [W25Q OK]
  101. {
  102. Enter();
  103. if( W25Q_LL_Routines.ready.smartWaitms( W25QXXX_API_TIMEOUT ) )
  104. {
  105. Return(FLERR_SUCCESS);
  106. }
  107. Return(FLERR_TIMEOUT);
  108. }
  109. static flash_err_t flash_getready_time( __FLASH_WORD timeout ) // [W25Q OK]
  110. {
  111. Enter();
  112. if( W25Q_LL_Routines.ready.smartWaitms( timeout ) )
  113. {
  114. Return(FLERR_SUCCESS);
  115. }
  116. Return(FLERR_TIMEOUT);
  117. }
  118. // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
  119. // flash_modeSetup - Настройка общих параметров работы на этапе инициализации
  120. // - настройка режима SPI (Отключение Quad-режима)
  121. // - сброс режима комплиментарности групповой защиты (фактически выключение групповой защиты в купе со сбросом индикаторов BP)
  122. // - проверка блокировки статусных регистров
  123. // - проверка отсутствия режима suspend
  124. // - инициализация режима индивидуальной защиты секторов
  125. // - режим групповой защиты секторов будет отключен, т.к. он не удовлетворяет API
  126. // - настройка тока выходного драйвера
  127. // - настройка вывода управления ~WP: включение/отключение защиты по ~WP в зависимости от W25QXXX_HW_WR_PROTECT
  128. // - сброс индикаторов групповой защиты (BP)
  129. // * Достигается состояние, при котором при выборе режима групповой защиты (WPS=0) защита секторов выключается, что
  130. // позволяет использовать WPS как общий бит защиты секторов: при WPS=0 защита выключена, при WPS=1 включена индивидуально
  131. // # Функция возвращает FLERR_SUCCESS. Только в этом случае гарантируется нормальная работа.
  132. // # Функция возвращает ошибку инициализации при появлении сбоев или при непрохождении проверки
  133. static flash_err_t flash_modeSetup() // [W25Q OK]
  134. {
  135. flash_err_t success = FLERR_SUCCESS;
  136. // -------------------------------------------------------------------------
  137. // - настройка режима SPI (Отключение Quad-режима)
  138. // - проверка блокировки статусных регистров
  139. // - проверка отсутствия режима suspend
  140. {
  141. __flash_status2_t status;
  142. __flash_status2_t status_bak;
  143. // чтение текущего режима
  144. W25Q_LL_Routines.status.statusRead2( &status );
  145. // копируем состояние регистра для последующей сверки
  146. status_bak.status = status.status;
  147. // проверка блокировки регистров
  148. if( __FLASH_SRL_LOCKED == status.bStatLock )
  149. {
  150. // запись в статусные регистры запрещена по следующего цикла включения питания
  151. #if W25QXXX_POWER_MANAGEMENT
  152. // если разрешено управление питанием, пробуем разрешить проблему циклом подачи питания
  153. W25Q_LL_Routines.powerPulse();
  154. // повторное чтение регистра
  155. W25Q_LL_Routines.status.statusRead2( &status );
  156. // повторная проверка
  157. if( __FLASH_SRL_LOCKED == status.bStatLock )
  158. { // если без изменений - результат: ошибка
  159. #endif
  160. // ошибка настройки: регистры блокированы
  161. success = FLERR_DEVICE_MALFUNCTION;
  162. return(success);
  163. #if W25QXXX_POWER_MANAGEMENT
  164. }
  165. #endif
  166. }
  167. // проверка режима suspend
  168. if( __FLASH_SYS_ENABLED == status.bSuspended )
  169. {
  170. // задействован режим suspend, нужно сбросить
  171. #if W25QXXX_POWER_MANAGEMENT
  172. // если разрешено управление питанием, пробуем разрешить проблему циклом подачи питания
  173. W25Q_LL_Routines.powerPulse();
  174. // повторное чтение регистра
  175. W25Q_LL_Routines.status.statusRead2( &status );
  176. // повторная проверка
  177. if( __FLASH_SYS_ENABLED == status.bSuspended )
  178. { // если без изменений - результат: ошибка
  179. #endif
  180. // ошибка настройки: регистры блокированы
  181. success = FLERR_DEVICE_MALFUNCTION;
  182. return(success);
  183. #if W25QXXX_POWER_MANAGEMENT
  184. }
  185. #endif
  186. }
  187. // отключение режима Quad, если возможно.
  188. // На чипах IQ и JQ (W25QFLASH_FAMILYDATAFLASHQ) режим Quad заблокирован от выключения.
  189. __FLASH_DWORD flashID = W25Q_LL_Routines.id.manufacturerIdRead(0);
  190. if( W25QFLASH_FAMILYDATAFLASHQ != ((__flash_rvid_t*) &flashID)->DevId.Family )
  191. {
  192. // проверка режима Quad
  193. if( __FLASH_QUAD_ENABLED == status.bQuadEn )
  194. {
  195. // отключаем режим QUAD
  196. status.bQuadEn = __FLASH_QUAD_DISABLED;
  197. }
  198. }
  199. // сброс режима комплиментарности групповой защиты (фактически выключение групповой защиты)
  200. if( __FLASH_QUAD_ENABLED == status.bCmpProt )
  201. {
  202. // отключаем режим комплиментарности
  203. status.bCmpProt = __FLASH_CMP_DISABLE;
  204. }
  205. // проверка, есть ли измененные настройки, которые нужно записать?
  206. if( status_bak.status ^ status.status )
  207. {
  208. // включение разрешения инструкций записи
  209. W25Q_LL_Routines.operations.writeEnable();
  210. // запись регистра (сохранение параметров режима защиты)
  211. W25Q_LL_Routines.status.statusWrite2( &status );
  212. // проверка результата: повторное чтение
  213. W25Q_LL_Routines.status.statusRead2( &status_bak );
  214. }
  215. // проверка установленных параметров
  216. if( status_bak.status ^ status.status )
  217. {
  218. // ошибка настройки: не удалось записать требуемые настройки
  219. success = FLERR_DEVICE_MALFUNCTION;
  220. return(success);
  221. }
  222. }
  223. // -------------------------------------------------------------------------
  224. // - инициализация режима индивидуальной защиты секторов
  225. // - режим групповой защиты секторов будет отключен, т.к. он не удовлетворяет API
  226. // - настройка тока выходного драйвера
  227. {
  228. __flash_status3_t status;
  229. __flash_status3_t status_bak;
  230. // чтение текущего режима
  231. W25Q_LL_Routines.status.statusRead3( &status );
  232. // копируем состояние регистра для последующей сверки
  233. status_bak.status = status.status;
  234. if( __FLASH_WPS_GROUP_PROTECT == status.bWPSel )
  235. {
  236. // выбран групповой режим защиты: вЫключаем его
  237. status.bWPSel = __FLASH_WPS_INDIVIDUAL_PROTECT; // переключение режима защиты от записи: индивидуальная защита
  238. }
  239. if( __FLASH_DRS_DEFAULT != status.cDrvStr )
  240. {
  241. // выбрано неверное значение тока ключа
  242. status.cDrvStr = __FLASH_DRS_DEFAULT; // переключение выходного тока ключа
  243. }
  244. // проверка, есть ли измененные настройки, которые нужно записать?
  245. if( status_bak.status ^ status.status )
  246. {
  247. // включение разрешения инструкций записи
  248. W25Q_LL_Routines.operations.writeEnable();
  249. // запись регистра (сохранение параметров режима защиты)
  250. W25Q_LL_Routines.status.statusWrite3( &status );
  251. // проверка результата: повторное чтение
  252. W25Q_LL_Routines.status.statusRead3( &status_bak );
  253. }
  254. // проверка установленных параметров
  255. if( status_bak.status ^ status.status )
  256. {
  257. // ошибка настройки: не удалось записать требуемые настройки
  258. success = FLERR_DEVICE_MALFUNCTION;
  259. return(success);
  260. }
  261. }
  262. // -------------------------------------------------------------------------
  263. // - настройка вывода управления ~WP: включение/отключение защиты по ~WP в зависимости от W25QXXX_HW_WR_PROTECT
  264. // - сброс индикаторов групповой защиты
  265. {
  266. __flash_status1_t status;
  267. __flash_status1_t status_bak;
  268. // чтение текущего режима
  269. W25Q_LL_Routines.status.statusRead1( &status );
  270. // копируем состояние регистра для последующей сверки
  271. status_bak.status = status.status;
  272. if( __FLASH_SRP_WP_DEFAULT != status.bStatProt )
  273. {
  274. // Настройка выводв ~WP отличается от требуемой
  275. status.bStatProt = __FLASH_SRP_WP_DEFAULT; // переключение режима ~WP
  276. }
  277. if( __FLASH_BP_RESET != status.cBlkProt )
  278. {
  279. // сброс индикаторов групповой защиты
  280. status.cBlkProt = __FLASH_BP_RESET; // переключение режима защиты
  281. }
  282. // проверка, есть ли измененные настройки, которые нужно записать?
  283. if( status_bak.status ^ status.status )
  284. {
  285. // включение разрешения инструкций записи
  286. W25Q_LL_Routines.operations.writeEnable();
  287. // запись регистра (сохранение параметров режима защиты)
  288. W25Q_LL_Routines.status.statusWrite1( &status );
  289. // проверка результата: повторное чтение
  290. W25Q_LL_Routines.status.statusRead1( &status_bak );
  291. }
  292. // проверка установленных параметров
  293. if( status_bak.status ^ status.status )
  294. {
  295. // ошибка настройки: не удалось записать требуемые настройки
  296. success = FLERR_DEVICE_MALFUNCTION;
  297. return(success);
  298. }
  299. }
  300. return success;
  301. }
  302. // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
  303. // flash_api_initialize - инициализация драйвера и API работы с устройством
  304. // * Если @detectOnly=true, производится только детектирование наличия чипа!
  305. // # Функция возвращает FLERR_SUCCESS. Только в этом случае гарантируется нормальная работа.
  306. // # Функция возвращает ошибку инициализации при появлении сбоев или при непрохождении проверки (см файл конфигурации AT45DB161E_CONF.h)
  307. static flash_err_t flash_api_initialize( bool detectOnly ) // [W25Q OK]
  308. {
  309. // производится определение наличия чипа на шине
  310. if( detectOnly )
  311. {
  312. return W25Q_LL_Routines.service.startupDetect();
  313. }
  314. // производим нисзкоуровневую инициализацию: подаем питание и будим, проверяем наличие чипа, серию, производителя, размер...
  315. flash_err_t success = W25Q_LL_Routines.service.initialize();
  316. if( FLASH_ERROR(success) )
  317. {
  318. // что-то пошло не так: ай печаль-печаль.
  319. return(success);
  320. }
  321. // -------------------------------------------------------------------------
  322. // конфигурирование режима работы
  323. success = flash_modeSetup();
  324. if( FLASH_ERROR(success) )
  325. {
  326. // что-то пошло не так: ай печаль-печаль.
  327. return(success);
  328. }
  329. // -------------------------------------------------------------------------
  330. // отключаем защиту секторов при инициализации (разрешение записи во все сектора)
  331. success = flash_api_unprotect( NULL );
  332. if( FLASH_ERROR(success) )
  333. {
  334. // что-то пошло не так: ай печаль-печаль.
  335. return(success);
  336. }
  337. // считываем статус
  338. if( ! W25Q_LL_Routines.ready.smartWaitms( W25QXXX_API_TIMEOUT ) )
  339. {
  340. // что-то пошло не так: ай печаль-печаль.
  341. return(success);
  342. }
  343. return(FLERR_SUCCESS);
  344. }
  345. // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
  346. // flash_api_finalize - безопасная де-инициализация драйвера
  347. // Функция завершает работу с флеш-памятью, отключаяя ее или переводя в режим гибернации
  348. // @bHibernate: булевый флаг, показывает, что нужно перевести флеш-память в режим гибернации,
  349. // если false - драйвер попытается отключить питание микросхемы, если разрешено управление питанием (AT45DBXXX_POWER_MANAGEMENT)
  350. // если false и управление питанием запрещено, будет возвращена ошибка FLERR_INVALID_PARAMETER.
  351. // @bForce: насильное выполнение финализации в случае, если флеш-память занята незаконченной операцией.
  352. // если false и драйвер детектирует незаконченную операцию, будет возвращена ошибка FLERR_UNEXPECTED_BUSY.
  353. // Если выбран режим гибернации, после выдачи команды функция проверяет, уснула ли микросхема через чтение статуса.
  354. // Если в этом случае обнаруживается, что статус все еще считывается, генерируется ошибка FLERR_GENERIC_ERROR.
  355. // Данную проверку можно отключить опцией W25QXXX_DONOTCHECK_HIBERNATE=1.
  356. // Внимание: проверка не реализуется если bHibernate=false.
  357. // # Функция возвращает FLERR_SUCCESS всегда, за исключением вышеописанных случаев.
  358. static flash_err_t flash_api_finalize( bool bHibernate, bool bForce ) // [W25Q OK]
  359. {
  360. Enter();
  361. // подготовка к деинициализации
  362. flash_err_t status = W25Q_LL_Routines.service.finalizePrepare();
  363. if( FLASH_ERROR(status) )
  364. {
  365. // ошибка, обнаружена проблема - устройство не готово
  366. // проверяем, разрешено ли принудительное завершение?
  367. if( bForce )
  368. {
  369. // разрешено, сначала производим сброс
  370. // доступно управление сигналом сброса?
  371. #if W25QXXX_RESET_MANAGEMENT
  372. // да, производим сброс чипа
  373. W25Q_LL_Routines.reset.resetPulse();
  374. #else
  375. // нет, а доступно управление питанием?
  376. #if W25QXXX_POWER_MANAGEMENT
  377. // да, производим быстрый сброс чипа по питанию
  378. W25Q_LL_Routines.power.powerPulse( 0, 0 );
  379. #else
  380. // нет, управление питанием тоже недоступно
  381. // возвращаем ошибку FLERR_INVALID_PARAMETER - невозможно выполнить принудительное отключение
  382. Return(FLERR_INVALID_PARAMETER);
  383. #endif
  384. #endif
  385. }
  386. else
  387. {
  388. // нет, принудительное завершение запрещено
  389. // возвращаем ошибку
  390. Return(status);
  391. }
  392. }
  393. // все нормально, продолжаем
  394. // выбран режим гибернации?
  395. if( bHibernate )
  396. {
  397. // отправляем микросхему поспать
  398. W25Q_LL_Routines.sleep.sleepMode();
  399. #if W25QXXX_DONOTCHECK_HIBERNATE == 0
  400. // проверяем, ответит ли микросхема?
  401. if( W25Q_LL_Routines.ready.smartWaitms( W25QXXX_API_TIMEOUT ) )
  402. {
  403. // отвечает - бит готовности прочитался...
  404. // Может это просто подтянутый сигнал к +VCC?
  405. // попробуем по другому:
  406. if( FLASH_SUCCESS(W25Q_LL_Routines.service.detect()) )
  407. {
  408. // ответила! значит точно не ложилась спать - ошибка
  409. Return(FLERR_DEVICE_MALFUNCTION);
  410. }
  411. }
  412. #endif
  413. }
  414. else
  415. {
  416. // доступно управление питанием?
  417. #if W25QXXX_POWER_MANAGEMENT == 0
  418. // нет, недоступно, нечего делать, генерируем ошибку
  419. Return(FLERR_INVALID_PARAMETER);
  420. #else
  421. // Доступно, отключаем питание.
  422. W25Q_LL_Routines.power_off();
  423. // не проверяем доступность, доверяем функции отключения питания
  424. #endif
  425. }
  426. Return(FLERR_SUCCESS);
  427. }
  428. // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
  429. // flash_api_service - функция получения общих сведений об флеш-памяти.
  430. // Полный список возможных запросов приведен ниже:
  431. // ЗАПРОС РАЗМЕР ТИП ТИП ИНФОРМАИИ
  432. // БУФЕРА ЗНАЧНИЯ
  433. // fsvc_getVendorId 2 __FLASH_WORD ID производителя
  434. // fsvc_getDeviceId 2 flash_deviceid_t ID устройства
  435. // fsvc_getExtInfo * __FLASH_BYTE[] расширенную информацию производителя
  436. // fsvc_getExtInfoLen 1 __FLASH_BYTE длинну расширенной информации производителя
  437. // fsvc_getCapacity 4 __FLASH_DWORD заявляемая по документации емкость устройства (MBit-s)
  438. // fsvc_getFullCapacity 4 __FLASH_DWORD полная емкость устройства (в байтах)
  439. // fsvc_getDataCapacity 4 __FLASH_DWORD доступная емкость устройства (в байтах)
  440. // fsvc_getProtect 1 __FLASH_BYTE информацию о защите секторов (общий бит защиты 0x00 или 0x01)
  441. // fsvc_getSectorsCount 2 __FLASH_WORD количество секторов
  442. // fsvc_getPagesCount 2 __FLASH_WORD количество страниц
  443. // fsvc_getBlocksCount 2 __FLASH_WORD количество блоков
  444. // fsvc_getPageSize 2 __FLASH_WORD размер страницы
  445. // fsvc_getReadyState 1 __FLASH_BYTE готовность устройства
  446. // fsvc_getMinAddress 4 __FLASH_DWORD минимально возможный линейный адрес
  447. // fsvc_getMaxAddress 4 __FLASH_DWORD максимально возможный линейный адрес
  448. //
  449. // * Параметр @si задает тип запроса (см. flash_service_info_t)
  450. // * Параметр @pdata должен указывать на заранее выделенный буфер памяти для сохранения
  451. // получаемых данных. Размер буфера зависит от типа запроса. Параметр не может быть NULL
  452. // * Параметр @pbufsize должен указывать на размер буфера, на который указывает pdata.
  453. // Параметр не может быть 0. Значение по указателю @pbufsize не может быть 0.
  454. // При успешном выполнении функции, по указателю @pbufsize будет записано фактическое количество
  455. // записанных в буфер данных.
  456. //
  457. // * Функция НЕ ОБНУЛЯЕТ память по указателю @pdata в случае, если передан слишком большой буфер.
  458. //
  459. // # Функция вернет ошибку FLERR_INVALID_PARAMETER при некорректном запросе @si
  460. // # Функция вернет ошибку FLERR_INVALID_PARAMETER если @pdata или @bufsize равны 0.
  461. // # Функция вернет ошибку FLERR_INVALID_BUFFER если размер буфера @size не достаточен для сохранения данных
  462. //
  463. // # Функция вернет FLERR_SUCCESS при отсутствии ошибок
  464. //
  465. static flash_err_t flash_api_service( flash_service_info_t si, void * pdata, __FLASH_WORD * pbufsize ) // [W25Q OK]
  466. {
  467. if( !pdata || !pbufsize || !*pbufsize ) return(FLERR_INVALID_PARAMETER);
  468. Enter();
  469. switch( si )
  470. {
  471. case fsvc_getVendorId: // ID производителя
  472. case fsvc_getDeviceId: // ID устройства
  473. case fsvc_getCapacity: // заявляемая по документации емкость устройства (MBit-s)
  474. case fsvc_getDataCapacity: // доступная емкость устройства
  475. case fsvc_getFullCapacity: // полная емкость устройства
  476. {
  477. __FLASH_DWORD flashID = W25Q_LL_Routines.id.manufacturerIdRead( 0 );
  478. switch( si )
  479. {
  480. case fsvc_getVendorId: if( sizeof( __FLASH_WORD ) > *pbufsize )
  481. Return(FLERR_INVALID_BUFFER);
  482. *((__FLASH_WORD*)(pdata)) = ((__flash_rvid_t*) &flashID)->FullId;
  483. *pbufsize = sizeof(__FLASH_WORD);
  484. Return(FLERR_SUCCESS);
  485. //-------------------------
  486. case fsvc_getDeviceId: if( sizeof( __FLASH_WORD ) > *pbufsize )
  487. Return(FLERR_INVALID_BUFFER);
  488. *((flash_deviceid_t*)(pdata)) = ((__flash_rvid_t*) &flashID)->DevId;
  489. *pbufsize = sizeof(__FLASH_WORD);
  490. Return(FLERR_SUCCESS);
  491. //-------------------------
  492. case fsvc_getCapacity: if( sizeof( __FLASH_DWORD ) > *pbufsize )
  493. Return(FLERR_INVALID_BUFFER);
  494. *((__FLASH_DWORD*)(pdata)) = __FLASH_DENSITY2CAPACITY( ((flash_deviceid_t*)&((__flash_rvid_t*) &flashID)->DevId)->Density );
  495. *pbufsize = sizeof(__FLASH_DWORD);
  496. Return(FLERR_SUCCESS);
  497. //-------------------------
  498. case fsvc_getDataCapacity: if( sizeof( __FLASH_DWORD ) > *pbufsize )
  499. Return(FLERR_INVALID_BUFFER);
  500. *((__FLASH_DWORD*)(pdata)) = (W25QFLASH_MAXIMUM_ADDRESS - W25QFLASH_MINIMUM_ADDRESS);
  501. *pbufsize = sizeof(__FLASH_DWORD);
  502. Return(FLERR_SUCCESS);
  503. //-------------------------
  504. case fsvc_getFullCapacity: if( sizeof( __FLASH_DWORD ) > *pbufsize )
  505. Return(FLERR_INVALID_BUFFER);
  506. *((__FLASH_DWORD*)(pdata)) = (W25QFLASH_MAXIMUM_ADDRESS);
  507. *pbufsize = sizeof(__FLASH_DWORD);
  508. Return(FLERR_SUCCESS);
  509. }
  510. }
  511. break;
  512. case fsvc_getMinAddress:
  513. {
  514. if( sizeof( __FLASH_DWORD ) > *pbufsize )
  515. Return(FLERR_INVALID_BUFFER);
  516. *((__FLASH_DWORD*)(pdata)) = (W25QFLASH_MINIMUM_ADDRESS);
  517. *pbufsize = sizeof(__FLASH_DWORD);
  518. Return(FLERR_SUCCESS);
  519. }
  520. break;
  521. case fsvc_getMaxAddress:
  522. {
  523. if( sizeof( __FLASH_DWORD ) > *pbufsize )
  524. Return(FLERR_INVALID_BUFFER);
  525. *((__FLASH_DWORD*)(pdata)) = (W25QFLASH_MAXIMUM_ADDRESS);
  526. *pbufsize = sizeof(__FLASH_DWORD);
  527. Return(FLERR_SUCCESS);
  528. }
  529. break;
  530. //-------------------------
  531. case fsvc_getExtInfoLen: // длинну расширенной информации производителя
  532. case fsvc_getExtInfo: // расширенную информацию производителя
  533. {
  534. __flash_id_t mid;
  535. switch( si )
  536. {
  537. case fsvc_getExtInfoLen:
  538. if( sizeof( __FLASH_BYTE ) > *pbufsize )
  539. Return(FLERR_INVALID_BUFFER);
  540. mid.pExtBf = 0;
  541. mid.ExtLen = 0;
  542. // получение ДЛИННЫ расширенной информации
  543. W25Q_LL_Routines.id.manufacturerIdRead( &mid );
  544. *((__FLASH_BYTE*)(pdata)) = mid.ExtLen;
  545. *pbufsize = sizeof(__FLASH_BYTE);
  546. Return(FLERR_SUCCESS);
  547. case fsvc_getExtInfo:
  548. if( 1 * sizeof( __FLASH_BYTE ) > *pbufsize )
  549. Return(FLERR_INVALID_BUFFER);
  550. mid.pExtBf = pdata;
  551. mid.ExtLen = *pbufsize;
  552. // получение расширенной информации
  553. W25Q_LL_Routines.id.manufacturerIdRead( &mid );
  554. *pbufsize = mid.ExtLen;
  555. Return(FLERR_SUCCESS);
  556. }
  557. }
  558. Return(FLERR_INVALID_BUFFER);
  559. case fsvc_getReadyState: // готовность устройства
  560. {
  561. if( sizeof( __FLASH_BYTE ) <= *pbufsize )
  562. {
  563. *((__FLASH_BYTE*)(pdata)) = ( FLASH_SUCCESS( W25Q_LL_Routines.ready.getReadyFast() ) )? 0x01: 0x00;
  564. *pbufsize = sizeof(__FLASH_BYTE);
  565. Return(FLERR_SUCCESS);
  566. }
  567. }
  568. Return(FLERR_INVALID_BUFFER);
  569. case fsvc_getProtect: // информацию о защите секторов
  570. {
  571. if( sizeof( __FLASH_BYTE ) <= *pbufsize )
  572. {
  573. flash_api_getprotect_t content;
  574. flash_err_t status = flash_api_getprotect( &content );
  575. if( FLASH_SUCCESS(status) )
  576. {
  577. // любой из секторов защищен?
  578. if( content.sectors.hiprotect != 0 && content.sectors.loprotect != 0 )
  579. {
  580. // как минимум один из секторов защищен
  581. *pbufsize = sizeof(__FLASH_BYTE);
  582. *((__FLASH_BYTE*)(pdata)) = 1;
  583. }
  584. else
  585. {
  586. // ни один из секторов не защищен
  587. *pbufsize = sizeof(__FLASH_BYTE);
  588. *((__FLASH_BYTE*)(pdata)) = 0;
  589. }
  590. Return(FLERR_SUCCESS);
  591. }
  592. Return(status); // Ошибка?
  593. }
  594. }
  595. Return(FLERR_INVALID_BUFFER);
  596. case fsvc_getPageSize: // размер страницы
  597. {
  598. if( sizeof( __FLASH_WORD ) >= *pbufsize )
  599. {
  600. *((__FLASH_WORD*)(pdata)) = W25QFLASH_PAGE_SIZE;
  601. *pbufsize = sizeof(__FLASH_WORD);
  602. Return(FLERR_SUCCESS);
  603. }
  604. }
  605. Return(FLERR_INVALID_BUFFER);
  606. case fsvc_getSectorsCount: // количество секторов
  607. {
  608. if( sizeof( __FLASH_WORD ) <= *pbufsize )
  609. {
  610. *((__FLASH_WORD*)(pdata)) = W25QFLASH_SECTORS;
  611. *pbufsize = sizeof(__FLASH_WORD);
  612. Return(FLERR_SUCCESS);
  613. }
  614. }
  615. Return(FLERR_INVALID_BUFFER);
  616. case fsvc_getPagesCount: // количество страниц
  617. {
  618. if( sizeof( __FLASH_WORD ) >= *pbufsize )
  619. {
  620. *((__FLASH_WORD*)(pdata)) = W25QFLASH_PAGES;
  621. *pbufsize = sizeof(__FLASH_WORD);
  622. Return(FLERR_SUCCESS);
  623. }
  624. }
  625. Return(FLERR_INVALID_BUFFER);
  626. case fsvc_getBlocksCount: // количество блоков
  627. {
  628. if( sizeof( __FLASH_WORD ) >= *pbufsize )
  629. {
  630. *((__FLASH_WORD*)(pdata)) = W25QFLASH_BLOCKS;
  631. *pbufsize = sizeof(__FLASH_WORD);
  632. Return(FLERR_SUCCESS);
  633. }
  634. }
  635. Return(FLERR_INVALID_BUFFER);
  636. }
  637. Return(FLERR_INVALID_PARAMETER);
  638. }
  639. // -----
  640. static flash_err_t flash_api_sectorprotectregister_read( __flash_sectorprotectionregister_t * contents );
  641. static flash_err_t flash_api_sectorprotectregister_write( __flash_sectorprotectionregister_t * contents );
  642. static flash_err_t flash_api_writeprotection_disable();
  643. // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
  644. // flash_api_protect_ex - установить/снять защиту секторов
  645. // Поробности см. описание flash_api_protect() / flash_api_unprotect()
  646. //
  647. // @mode: flash_sector_unprotected - вызов из flash_api_unprotect()
  648. // @mode: flash_sector_protected - вызов из flash_api_protect()
  649. //
  650. static flash_err_t flash_api_protect_ex( flash_api_protect_t * content, flash_api_protect_bits mode ) // [W25Q WRONG]
  651. {
  652. Enter();
  653. // проверяем устройство на занятость
  654. if( FLERR_TIMEOUT == flash_api_getready() ) Return(FLERR_TIMEOUT);
  655. // проверяем на NULL переданный параметр
  656. if( NULL == content )
  657. {
  658. // попытка вызова без указания схемы защиты
  659. // допустимо только если mode===flash_sector_unprotected
  660. // НЕ допустимо, если mode===flash_sector_protected
  661. // проверка режима:
  662. if( mode == flash_sector_protected )
  663. {
  664. // параметр NULL, схема защиты не указана, нужно бы вернуть ошибку, т.к.
  665. // неизвестно, какие сектора нужно защищать, но для совместимости с драйверами чипов,
  666. // имеющих глобальный флаг защиты, здесь возвращается УСПЕХ, т.к. предполагается
  667. // что индивидуальные флаги защиты уже были проставлены на предыдущем этапе.
  668. // Для W25Q именно индивидуальные флаги будут использованы, а данный вызов - лишь заглушка
  669. // оставленная для совместимости
  670. Return(FLERR_SUCCESS);
  671. }
  672. // снятие защиты: если схема не указана (content=null), разрешаем запись во все сектора
  673. Return(flash_api_writeprotection_disable());
  674. }
  675. else
  676. {
  677. // указана схема модификации индивидуальных битов защиты секторов (content != NULL)
  678. // проверка режима модификации общего бита защиты
  679. switch( content->protection_modify )
  680. {
  681. // без модификации общего бита защиты
  682. case flash_sector_protect_nomodify:
  683. // не трогаем общий бит защиты
  684. break;
  685. // модификация общего бита защиты
  686. case flash_sector_protect_modify:
  687. if( mode != flash_sector_unprotected )
  688. {
  689. // модификация общего бита защиты при установке защиты
  690. // с указанием схемы - недоступна.
  691. Return(FLERR_INVALID_PARAMETER);
  692. }
  693. // flash_sector_protected
  694. if( content->protection_enabled )
  695. {
  696. // попытка установки общего флага защиты вместе с указанием схемы защиты
  697. // не поддерживается
  698. Return(FLERR_INVALID_PARAMETER);
  699. }
  700. // flash_sector_unprotected
  701. else
  702. {
  703. // попытка снятия общего флага защиты вместе с указанием схемы защиты
  704. // схема защиты - игнорируются
  705. // разрешается запись во все сектора
  706. Return(flash_api_writeprotection_disable());
  707. }
  708. break;
  709. default:
  710. // неправильный параметр в поле protection_modify
  711. Return(FLERR_INVALID_PARAMETER);
  712. }
  713. // LL-буфер
  714. flash_LL_buf_t buf;
  715. // получаем указатель на буфер драйвера
  716. // зануляем память (буфер занулен по умолчанию)
  717. buf.rawptr = W25Q_LL_Routines.service.getBuf( fibufSectorFlags, &buf.size );
  718. // считываем флаги защиты секторов
  719. flash_api_sectorprotectregister_read( buf.pSectorProtectionRegister );
  720. //------------------------------------------------------
  721. // модифицируем флаги защиты
  722. for( size_t nSector = 0; nSector < __SECTORS; ++nSector )
  723. {
  724. if( FLASH_PROTECTION_REGISTER_CHECK( content->sectors.bytes, nSector ) )
  725. {
  726. // сектор выбран: устанавливаем или снимаем флаги защиты
  727. if( mode == flash_sector_unprotected )
  728. {
  729. FLASH_PROTECTION_REGISTER_CLEAR( buf.pSectorProtectionRegister->bSectors, nSector );
  730. }
  731. else
  732. {
  733. FLASH_PROTECTION_REGISTER_SET( buf.pSectorProtectionRegister->bSectors, nSector );
  734. }
  735. } else { /* не модифицировать статус защиты сектора */ }
  736. }
  737. //------------------------------------------------------
  738. // записываем флаги защиты секторов
  739. flash_api_sectorprotectregister_write( buf.pSectorProtectionRegister );
  740. //------------------------------------------------------
  741. { // №№№№№№ ПРОВЕРКА №№№№№№
  742. // считываем флаги защиты секторов обратно для сравнения
  743. flash_api_sectorprotectregister_read( buf.pSectorProtectionRegister );
  744. // проверяем флаги защиты
  745. for( size_t nSector = 0; nSector < __SECTORS_TYPICAL; ++nSector )
  746. {
  747. if( FLASH_PROTECTION_REGISTER_CHECK( content->sectors.bytes, nSector ) )
  748. {
  749. // сектор выбран: проверяем биты защиты
  750. if( mode == flash_sector_unprotected )
  751. {
  752. if( FLASH_PROTECTION_REGISTER_CHECK( buf.pSectorProtectionRegister->bSectors, nSector ) )
  753. Return(FLERR_GENERIC_ERROR);
  754. }
  755. else
  756. {
  757. if( ! FLASH_PROTECTION_REGISTER_CHECK( buf.pSectorProtectionRegister->bSectors, nSector ) )
  758. Return(FLERR_GENERIC_ERROR);
  759. }
  760. }
  761. }
  762. }
  763. //------------------------------------------------------
  764. // успех.
  765. Return(FLERR_SUCCESS);
  766. }
  767. }
  768. // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
  769. // flash_api_protect - установить защиту секторов
  770. //
  771. // Функция модифицирует флаги защиты сектров выбранных пользователем в состояние "защищен".
  772. // Установите соответствующие флаги в структуре @content в состояние "1" для защиты сектора.
  773. // Функция не обрабатывает модификацию общего флага защиты, т.к. в W25QXXX он отсутствует.
  774. // Функция не может защитить выбранные сектора без указания схемы защиты, поскольку регистры индивидуальной
  775. // защиты секторов не сохраняются при отключении питания. Поэтому передача схемы защиты при вызове функции
  776. // обязательна, в отличие от flash_api_unprotect, которая просто разрешает запись во все сектора сразу.
  777. // Поскольку схема защиты обязательна, общий флаг защиты при вызове функции упразднен, т.к. не имеет смысла.
  778. // Для сохранения сингатуры вызова функции (совместимость с драйвером AT45), поле protection_modify должно
  779. // быть установлено в значение flash_sector_protect_nomodify, в противном случае функция вернет
  780. // ошибку FLERR_INVALID_PARAMETER. Значение protection_enabled будет игнорироваться.
  781. //
  782. // * установите поле protection_modify в состояние "flash_sector_protect_nomodify".
  783. // * поле protection_enabled игнорируется
  784. // * параметр @content может быть равен NULL (совместимость с драйверами с общим флагом защиты)
  785. // * если @content равен NULL, функция всегда возвращает FLERR_SUCCESS для совместимости драйвера с драйверами
  786. // чипов, имеющих общий флаг защиты. Предполагается, что этому предшествовал вызов с @content!=NULL,
  787. // где указана схема защиты, которая и будет использована.
  788. //
  789. // # Функция вернет FLERR_SUCCESS, если в процессе операции не произошло ошибок.
  790. // # Функция вернет FLERR_INVALID_PARAMETER в случае, если обнаружит ошибку в переданном параметре
  791. // # Функция вернет FLERR_UNEXPECTED_BUSY в случае, если процесс выполнения был прерван из-за неожиданного отказа устройства
  792. // # Функция вернет FLERR_GENERIC_ERROR в случае, если общий бит защиты не был установлен из-за ошибки
  793. // # Функция вернет FLERR_GENERIC_ERROR в случае, если хотя бы один из выбранных битов защиты не был установлен/сброшен
  794. //
  795. static flash_err_t flash_api_protect( flash_api_protect_t * content ) // [W25Q OK]
  796. {
  797. return( flash_api_protect_ex( content, flash_sector_protected ));
  798. }
  799. // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
  800. // flash_api_unprotect - снять защиту секторов. Функция аналогичная flash_api_protect(),
  801. // только имеет обратный эффект - снятие защиты с выбранных секторов.
  802. //
  803. // Функция модифицирует флаги защиты сектров выбранных пользователем в состояние "не защищен".
  804. // Установите соответствующие флаги в структуре @content в состояние "1" для снятия защиты сектора.
  805. // Функция также обрабатывает модификацию общего флага защиты выбранных секторов, но особым образом.
  806. // Т.к. в W25QXXX отсутствует общий флаг защиты, функция просто разрешает запись во все секторы при попытке
  807. // сброса общего бита защиты. Установка общего бита защиты недоступна.
  808. // При вызове поддерживается сочетание protection_modify=flash_sector_protect_modify и protection_enabled=0,
  809. // либо protection_modify=flash_sector_protect_nomodify, в противном случае будет возвращена ошибка FLERR_INVALID_PARAMETER.
  810. //
  811. // * Флаги защиты секторов могут быть сброшены индивидуально, либо все сразу (сбросом изменения общего флага защиты)
  812. // * Для сброса защиты всех секторов установите поле protection_modify в состояние "flash_sector_protect_modify", а
  813. // а поле protection_enabled=0, при этом значения частных флагов защиты секторов игнорируются
  814. //
  815. // * параметр @content может быть равен NULL, в этом случае разрешается запись во все сектора
  816. //
  817. // * Для снятия частных флагов защиты сектров:
  818. // - установите поля частных флагов защиты требуемых секторов (s0...s63) в состояние flash_sector_protect_modify,
  819. // и установите protection_modify в значение "flash_sector_protect_nomodify". Поле protection_enabled игнорируется.
  820. //
  821. // # Функция вернет FLERR_SUCCESS, если в процессе операции не произошло ошибок.
  822. // # Функция вернет FLERR_INVALID_PARAMETER в случае, если обнаружит ошибку в переданном параметре
  823. // # Функция вернет FLERR_UNEXPECTED_BUSY в случае, если процесс выполнения был прерван из-за неожиданного отказа устройства
  824. // # Функция вернет FLERR_GENERIC_ERROR в случае, если общий бит защиты не был установлен из-за ошибки
  825. // # Функция вернет FLERR_GENERIC_ERROR в случае, если хотя бы один из выбранных битов защиты не был установлен/сброшен
  826. //
  827. static flash_err_t flash_api_unprotect( flash_api_protect_t * content ) // [W25Q OK]
  828. {
  829. return( flash_api_protect_ex( content, flash_sector_unprotected ));
  830. }
  831. // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
  832. // flash_api_getprotect - получить информацию о защищенных секторах.
  833. // * Указатель @content может быть NULL.
  834. // # Возвращаемое значение - FLERR_PROTECT_ENABLED если хотя бы один из секторов защищен от записи.
  835. // Если @content не NULL, то в @content будет записана структура типа flash_api_getprotect_t, содержащая детальную
  836. // информацию о защите сектора (один сектор на один бит), 1b значит, что сектор защищен, 0b - не защищен, а поле
  837. // protection_enabled будет равняться возвращаемому значению
  838. static flash_err_t flash_api_getprotect( flash_api_getprotect_t * content ) // [W25Q OK]
  839. {
  840. flash_err_t retVal = FLERR_INVALID_PARAMETER;
  841. Enter();
  842. {
  843. if( FLERR_TIMEOUT == flash_api_getready() ) Return(FLERR_TIMEOUT);
  844. // LL-буфер
  845. flash_LL_buf_t buf;
  846. // получаем указатель на буфер драйвера
  847. // зануляем память (буфер занулен по умолчанию)
  848. buf.rawptr = W25Q_LL_Routines.service.getBuf( fibufSectorFlags, &buf.size );
  849. // считываем флаги защиты секторов
  850. flash_api_sectorprotectregister_read( buf.pSectorProtectionRegister );
  851. retVal = FLERR_PROTECT_DISABLED;
  852. if( NULL != content )
  853. {
  854. content->protection_enabled = flash_sector_unprotected;
  855. }
  856. // проверяем флаги защиты
  857. for( size_t nSector = 0; nSector < __SECTORS; ++nSector )
  858. {
  859. // проверяем биты защиты
  860. if( FLASH_PROTECTION_REGISTER_CHECK( buf.pSectorProtectionRegister->bSectors, nSector ) )
  861. {
  862. retVal = FLERR_PROTECT_ENABLED;
  863. if( NULL != content )
  864. {
  865. content->protection_enabled = flash_sector_protected;
  866. FLASH_PROTECTION_REGISTER_SET( content->sectors.bytes, nSector );
  867. }
  868. else
  869. break; // код @retVal установлен, content=NULL, здесь больше нечего делать
  870. }
  871. else
  872. {
  873. if( NULL != content )
  874. {
  875. FLASH_PROTECTION_REGISTER_CLEAR( content->sectors.bytes, nSector );
  876. }
  877. }
  878. }
  879. }
  880. Return(retVal);
  881. }
  882. // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
  883. // flash_api_erase - мультирежимное стирание данных
  884. // * Параметр @mode задает режим стирания:
  885. // mode==fem_byaddress - начальное смещение задается адресом в параметре @start, длинна отрезка - @count в байтах
  886. // При этом минимальный стираемый диапазон - размер страницы.
  887. // Страница, которой принадлежит адрес @start стирается полностью
  888. // Страница, которой принадлежит адрес @start + @count также стирается полность
  889. // mode==fem_bypage - начальное смещение задается номером страницы в параметре @start.
  890. // Количество стираемых страниц задается параметром @count
  891. //
  892. // mode==fem_byblock - не поддерживается в W25Q. установка этого значения эквивалентна fem_bypage
  893. //
  894. // mode==fem_bysector - начальное смещение задается номером сектора в параметре @start
  895. // Количество стираемых секторов задается параметром @count.
  896. //
  897. //
  898. // * Параметр @count не может быть 0.
  899. //
  900. // ! Функция НЕ проверяет защиту секторов !
  901. //
  902. // # Функция возвращает FLERR_SUCCESS если не произошло ошибок.
  903. // # Функция вернет FLERR_INVALID_PARAMETER если диапазон стирания выходит за границу адресного пространства
  904. // # Функция вернет FLERR_INVALID_PARAMETER если @count равняется 0.
  905. // # Функция вернет FLERR_INVALID_PARAMETER если @mode имеет значение, отличное от перечисленных.
  906. // # Функция вернет FLERR_UNEXPECTED_BUSY если во время операции устройство перестало отвечать
  907. //
  908. static flash_err_t flash_api_erase( flash_erase_mode_t mode, __FLASH_DWORD start, __FLASH_DWORD count ) // [W25Q WRONG]
  909. {
  910. if( 0 == count ) return(FLERR_INVALID_PARAMETER);
  911. Enter();
  912. switch( mode )
  913. {
  914. case fem_byaddress: // стирание по адресу
  915. #if W25QFLASH_MINIMUM_ADDRESS > 0
  916. if( start < W25QFLASH_MINIMUM_ADDRESS ) Return(FLERR_INVALID_PARAMETER);
  917. #endif
  918. if( start + count > W25QFLASH_MAXIMUM_ADDRESS ) Return(FLERR_INVALID_PARAMETER);
  919. case fem_bypage: // стирание по страницам
  920. case fem_byblock: // стирание по блокам (не поддерживается, эквивалентно fem_bypage)
  921. {
  922. __FLASH_DWORD PagesToErase=0;
  923. __FLASH_DWORD PageBegin =0;
  924. if( mode == fem_byaddress )
  925. {
  926. // стирание по адресу
  927. PagesToErase = __FLASH_PAGESINRANGE( start , count );
  928. PageBegin = __FLASH_ADDRESS2PAGE( start );
  929. }
  930. else
  931. {
  932. // стирание по страницам
  933. #if W25QFLASH_MINIMUM_ADDRESS > 0
  934. if( start < __FLASH_ADDRESS2PAGE(W25QFLASH_MINIMUM_ADDRESS) ) Return(FLERR_INVALID_PARAMETER);
  935. #endif
  936. if( start + count > __FLASH_ADDRESS2PAGE(W25QFLASH_MAXIMUM_ADDRESS) ) Return(FLERR_INVALID_PARAMETER);
  937. PagesToErase = count;
  938. PageBegin = start;
  939. }
  940. while( PagesToErase )
  941. {
  942. // команда разрешения операций стирания/записи
  943. W25Q_LL_Routines.operations.writeEnable();
  944. // проверяем, нельзя ли использовать секторное стирание?
  945. if( __FLASH_PAGE_ARRAGED_BY_SECTOR ( PageBegin ) && // проверяем выравниваение
  946. ( PagesToErase >= W25QFLASH_PAGES_PER_SECTOR ) ) // проверяем количество страниц
  947. {
  948. // можно!
  949. // стираем сектор - это быстрее
  950. W25Q_LL_Routines.data.sectorErase( __FLASH_PAGE2SECTOR( PageBegin ) );
  951. #if W25QXXX_BKGOPERATIONS
  952. if( FLERR_TIMEOUT == flash_getready_time( _TIME_SCERS_ms ) )
  953. #else
  954. if( FLERR_TIMEOUT == flash_api_getready() )
  955. #endif
  956. {
  957. // фатальная ошибка: устройство занято дольше обычного
  958. Return(FLERR_UNEXPECTED_BUSY);
  959. }
  960. PageBegin += __PAGES_PER_SECTOR;
  961. PagesToErase -= __PAGES_PER_SECTOR;
  962. }
  963. else
  964. {
  965. // нельзя
  966. W25Q_LL_Routines.data.pageErase( PageBegin );
  967. #if W25QXXX_BKGOPERATIONS
  968. if( FLERR_TIMEOUT == flash_getready_time( _TIME_PGERS_ms ) )
  969. #else
  970. if( FLERR_TIMEOUT == flash_api_getready() )
  971. #endif
  972. {
  973. // фатальная ошибка: устройство занято дольше обычного
  974. Return(FLERR_UNEXPECTED_BUSY);
  975. }
  976. PageBegin ++;
  977. PagesToErase --;
  978. }
  979. }
  980. }
  981. break;
  982. case fem_bysector: // стирание по секторам
  983. {
  984. if( start <= __FLASH_ADDRESS2SECTOR(W25QFLASH_MINIMUM_ADDRESS) ) Return(FLERR_INVALID_PARAMETER);
  985. if( start + count > __FLASH_ADDRESS2SECTOR(W25QFLASH_MAXIMUM_ADDRESS) ) Return(FLERR_INVALID_PARAMETER);
  986. while( count )
  987. {
  988. // команда разрешения операций стирания/записи
  989. W25Q_LL_Routines.operations.writeEnable();
  990. W25Q_LL_Routines.data.sectorErase( start );
  991. #if W25QXXX_BKGOPERATIONS
  992. if( FLERR_TIMEOUT == flash_getready_time( _TIME_SCERS_ms ) )
  993. #else
  994. if( FLERR_TIMEOUT == flash_api_getready() )
  995. #endif
  996. {
  997. // фатальная ошибка: устройство занято дольше обычного
  998. Return(FLERR_UNEXPECTED_BUSY);
  999. }
  1000. start ++;
  1001. count --;
  1002. }
  1003. }
  1004. break;
  1005. default: Return(FLERR_INVALID_PARAMETER);
  1006. }
  1007. // успех.
  1008. Return(FLERR_SUCCESS);
  1009. }
  1010. // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
  1011. // flash_api_write - мультирежимная запись данных по адресу
  1012. //
  1013. // * Параметр @address - указывает линейный адрес в адресном пространстве чипа.
  1014. // * Параметр @pBuffer - должен указывать на буфер-источник данных для записи. Не может быть NULL.
  1015. // * Параметр @size - должен указывать на размер данных на запись. Не может быть равен 0.
  1016. // * Параметр @mode - задает режим записи. Доступны следующий режимы:
  1017. // - fwm_safewrite - режим безопасной записи. Медленный режим, когда запись/стирание происходит
  1018. // постранично с верификацией. В случае ошибки верификации запись прекращается,
  1019. // остальная (незаписанная) часть данных не переписывается/не стрирается,
  1020. // при этом функция возвращает ошибку FLERR_VERIFY_ERROR
  1021. //
  1022. // - fwm_fastwrite - режим быстрой записи. Стирание происходит по блокам (8 станиц, см. заголовочный файл)
  1023. // Запись постраничная. Верификация данных не проводится.
  1024. //
  1025. // - fwm_compatible НЕ ПОДДЕРЖИВАЕТСЯ, возвращается ошибка FLERR_INVALID_PARAMETER
  1026. //
  1027. //
  1028. // # Функция возвращает FLERR_SUCCESS, если не произшло никаких ошибок.
  1029. // # Функция возвращает FLERR_UNEXPECTED_BUSY, если во время записи произошел отказ устройства.
  1030. // # Функция возвращает FLERR_VERIFY_ERROR, если обнаружена ошибка верификации данных.
  1031. // # Функция возвращает FLERR_INVALID_PARAMETER, если указан неверный параметр:
  1032. // - @address указывает на зарезервированную область, либо область записи выходит за границу адресного пространства;
  1033. // - @pBuffer или @size равны 0;
  1034. // - @mode имеет значение, отличное от перечисленных
  1035. //
  1036. // # Для быстрой работы требует включения режима W25QXXX_BKGOPERATIONS
  1037. // Функция использует две различные монорежимные функции записи:
  1038. //----------
  1039. static flash_err_t flash_api_buffer_programm( flash_LL_buf_t * buf, __FLASH_DWORD page );
  1040. //----------
  1041. static flash_err_t flash_api_write( flash_address_t address, __FLASH_BYTE * pBuffer, flash_address_t size, flash_write_mode_t mode ) // [W25Q OK]
  1042. {
  1043. #if W25QFLASH_MINIMUM_ADDRESS > 0
  1044. if( address < W25QFLASH_MINIMUM_ADDRESS ) return(FLERR_INVALID_PARAMETER);
  1045. #endif
  1046. if( !size || !pBuffer ) return(FLERR_INVALID_PARAMETER);
  1047. if( address + size > W25QFLASH_MAXIMUM_ADDRESS ) return(FLERR_INVALID_PARAMETER);
  1048. bool verify = false;;
  1049. switch( mode )
  1050. {
  1051. case fwm_safewrite: //режим безопасной записи.
  1052. // > Данные страницы кешируются в низкоуровневом программном буфере
  1053. // > Производится модификация данных в буфере (запись в буфер со смещением)
  1054. // > Используется команда стирание страницы
  1055. // > Используется команда запись страницы
  1056. // > Производится чтение данных по смещению в буфер
  1057. // > Производится данных буфера и переданных данных
  1058. // > Если данные совпадают - запись без ошибок
  1059. /* ______________________
  1060. / \
  1061. | Slow Moderate Fast |
  1062. | \ | / |
  1063. | \ |
  1064. | \ |
  1065. | \ |
  1066. | __\____ |
  1067. \_____________________/
  1068. */
  1069. verify = true;
  1070. break;
  1071. case fwm_fastwrite: //режим быстрой записи.
  1072. // > Данные страницы кешируются в низкоуровневом программном буфере
  1073. // > Производится модификация данных в буфере (запись в буфер со смещением)
  1074. // > Используется команда стирание страницы/сектора
  1075. // > Постранично записываем данные в чип
  1076. // > Готово.
  1077. /* ______________________
  1078. / \
  1079. | Slow Moderate Fast |
  1080. | \ | / |
  1081. | / |
  1082. | / |
  1083. | / |
  1084. | _____/_ [!] |
  1085. \_____________________/
  1086. */
  1087. break;
  1088. default: return(FLERR_INVALID_PARAMETER);
  1089. }
  1090. // > Данные страницы кешируются в низкоуровневом программном буфере
  1091. // > Производится модификация данных в буфере (запись в буфер со смещением)
  1092. // > Используется команда стирание страницы
  1093. // > Используется команда запись страницы
  1094. // > Если включена верификация {
  1095. // >>> Производится чтение данных по смещению в буфер
  1096. // >>> Производится данных буфера и переданных данных
  1097. // > }
  1098. // > Если данные совпадают - запись без ошибок
  1099. __FLASH_DWORD pageBegin = __FLASH_ADDRESS2PAGE( address ); // вычисляем номер первой страницы
  1100. __FLASH_DWORD PagesToWrite = __FLASH_PAGESINRANGE( address, size ); // вычисляем количество затрагиваемых страниц
  1101. __FLASH_DWORD BytesToWrite = __FLASH_DATAREMAININGINPAGE( address ); // вычисляем для первой страницы
  1102. Enter();
  1103. flash_LL_buf_t buf;
  1104. // запрос буфера драйвера LL
  1105. buf.rawptr = W25Q_LL_Routines.service.getBuf( fibufPageIO, &buf.size );
  1106. do
  1107. {
  1108. if( size < BytesToWrite ) BytesToWrite = size;
  1109. //---------------------
  1110. // ПЕРВАЯ и ПОСЛЕДНЯЯ страницы могут записываться частично: требуется предварительное чтение
  1111. if( __FLASH_ADDRESSOFFSETPAGE( address ) || PagesToWrite<=1 )
  1112. {
  1113. // буферизация страницы в программном буфере
  1114. W25Q_LL_Routines.data.arrayRead( address - __FLASH_ADDRESSOFFSETPAGE(address),
  1115. buf.pageBuffer,
  1116. buf.size );
  1117. // Производится модификация данных в буфере (запись в буфер со смещением)
  1118. __imp_sys_memcpy( buf.pageBuffer + __FLASH_ADDRESSOFFSETPAGE( address ),
  1119. pBuffer,
  1120. BytesToWrite );
  1121. }
  1122. //---------------------
  1123. // идет запись: разрешение стирания страницы
  1124. W25Q_LL_Routines.operations.writeEnable();
  1125. // идет запись: СТИРАНИЕ
  1126. W25Q_LL_Routines.data.pageErase( pageBegin );
  1127. if( FLASH_ERROR( W25Q_LL_Routines.ready.smartWaitms( _TIME_PGERS_ms ) ) )
  1128. Return(FLERR_UNEXPECTED_BUSY);
  1129. // идет запись: ПРОГРАММИРОВАНИЕ
  1130. if( FLASH_ERROR( flash_api_buffer_programm( &buf, pageBegin ) ) )
  1131. Return(FLERR_UNEXPECTED_BUSY);
  1132. //---------------------
  1133. if( verify )
  1134. {
  1135. // чтение записанного куска в буфер
  1136. W25Q_LL_Routines.data.arrayRead( address,
  1137. buf.pageBuffer,
  1138. BytesToWrite );
  1139. //---------------------
  1140. // Производится сравнение записанной страницы с буфером
  1141. if( 0 != __imp_sys_memcmp( buf.pageBuffer, pBuffer, BytesToWrite ) )
  1142. Return(FLERR_VERIFY_ERROR);
  1143. }
  1144. //---------------------
  1145. pageBegin++;
  1146. address += BytesToWrite;
  1147. pBuffer += BytesToWrite;
  1148. size -= BytesToWrite;
  1149. BytesToWrite = __FLASH_DATAREMAININGINPAGE( address );
  1150. }
  1151. while( --PagesToWrite );
  1152. Return(FLERR_SUCCESS);
  1153. }
  1154. //----------
  1155. // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
  1156. // flash_api_read - чтение данных по адресу
  1157. //
  1158. // * Функция проверяет правильность переданных параметров
  1159. // * Параметр @address задает линейный адрес внутри адресного пространства устройства.
  1160. // Параметр @pvBuffer должен указывать на буфер-приемник для прочитанных данных.
  1161. // Параметр @size должен указывать на размер буфер-приемника. Параметр показывает
  1162. // количество байт для чтения в буфер.
  1163. // # Если параметр @address указывает на адрес в диапазоне 0...W25QFLASH_MINIMUM_ADDRESS, функция вернет ошибку FLERR_INVALID_PARAMETER
  1164. // # Если параметр @pvBuffer равен NULL, функция вернет ошибку FLERR_INVALID_PARAMETER
  1165. // # Если параметр @size равен 0, функция вернет ошибку FLERR_INVALID_PARAMETER
  1166. static flash_err_t flash_api_read( flash_address_t address, __FLASH_BYTE * pBuffer, flash_address_t size ) // [W25Q OK]
  1167. {
  1168. // проверяем входные параметры
  1169. #if W25QFLASH_MINIMUM_ADDRESS > 0
  1170. if( address < W25QFLASH_MINIMUM_ADDRESS ) return(FLERR_INVALID_PARAMETER);
  1171. #endif
  1172. if( NULL == pBuffer || 0 == size ) return(FLERR_INVALID_PARAMETER);
  1173. if( address + size > __FULL_CHIP_SIZE ) return(FLERR_INVALID_PARAMETER);
  1174. Enter();
  1175. // проверям готовность устройства
  1176. if( FLERR_TIMEOUT == flash_api_getready() ) Return(FLERR_TIMEOUT);
  1177. W25Q_LL_Routines.data.arrayRead( address, pBuffer, size );
  1178. Return(FLERR_SUCCESS);
  1179. }
  1180. // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
  1181. // flash_api_sleepmode - переход в режим пониженного энергопотребления
  1182. // # переводит устройство в режим, когда все команды, кроме flash_api_wakeup игнорируются
  1183. static flash_err_t flash_api_sleepmode() // [W25Q OK]
  1184. {
  1185. Enter();
  1186. W25Q_LL_Routines.sleep.sleepMode();
  1187. Return(FLERR_SUCCESS);
  1188. }
  1189. // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
  1190. // flash_api_wakeup - выход из режима пониженного энергопотребления
  1191. // # выводит устройство из режима, когда все команды, кроме flash_api_wakeup игнорируются
  1192. static flash_err_t flash_api_wakeup() // [W25Q OK]
  1193. {
  1194. Enter();
  1195. W25Q_LL_Routines.sleep.wakeUp();
  1196. if( W25Q_LL_Routines.ready.smartWaitms( W25QXXX_API_TIMEOUT ) )
  1197. {
  1198. Return(FLERR_SUCCESS);
  1199. }
  1200. Return(FLERR_TIMEOUT);
  1201. }
  1202. // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
  1203. /*
  1204. // --------------------------------------------------------------------------------------------------------
  1205. // __flash_hal__protectregister_write - записывает регистр защиты (биты индивидуальной защиты секторов/блоков)
  1206. //
  1207. // * потоко-небезопасная функция
  1208. // * параметр @contents не может быть NULL - укажите содержимое регистра защиты (см. __flash_protectionregister_t)
  1209. // * задерживает выполнение на ДЕСЯТКИ МИЛЛИСЕКУНД
  1210. static void __flash_hal__protectregister_write( __flash_protectionregister_t * contents // содержимое регистра защиты для записи
  1211. ) // [W25Q WRONG]
  1212. {
  1213. if( !contents ) return;
  1214. for( size_t nProtSector = 0; nProtSector < __PROT_SECTOR_FLAGS; ++nProtSector )
  1215. {
  1216. __flash_hal__protectStateWrite( nProtSector, contents->Sectors[ nProtSector ] );
  1217. }
  1218. }
  1219. // --------------------------------------------------------------------------------------------------------
  1220. */
  1221. /*
  1222. // --------------------------------------------------------------------------------------------------------
  1223. // __flash_hal__protectregister_read - прочитывает регистр защиты (биты индивидуальной защиты секторов/блоков)
  1224. //
  1225. // * потоко-небезопасная функция
  1226. // * параметр @contents не может быть NULL - укажите буфер для содержимого регистра защиты (см. __flash_protectionregister_t)
  1227. static void __flash_hal__protectregister_read( __flash_protectionregister_t * contents // буфер-приемник содержимого регистра защиты
  1228. ) // [W25Q WRONG]
  1229. {
  1230. if( !contents ) return;
  1231. for( size_t nProtSector = 0; nProtSector < __PROT_SECTOR_FLAGS; ++nProtSector )
  1232. {
  1233. contents->Sectors[ nProtSector ] = __flash_hal__protectStateRead( nProtSector );
  1234. }
  1235. }
  1236. // --------------------------------------------------------------------------------------------------------
  1237. */
  1238. // --------------------------------------------------------------------------------------------------------
  1239. // flash_api_sectorprotectregister_write - записывает регистр защиты (биты индивидуальной защиты СЕКТОРОВ 64К)
  1240. //
  1241. // * потоко-небезопасная функция
  1242. // * параметр @contents не может быть NULL - укажите содержимое регистра защиты (см. __flash_sectorprotectionregister_t)
  1243. // * задерживает выполнение на ДЕСЯТКИ МИЛЛИСЕКУНД
  1244. static flash_err_t flash_api_sectorprotectregister_write( __flash_sectorprotectionregister_t * contents // содержимое регистра защиты для записи
  1245. ) // [W25Q OK]
  1246. {
  1247. if( NULL == contents ) return FLERR_INVALID_PARAMETER;
  1248. // цикл по секторам 64КБ
  1249. for( size_t nSector = 0; nSector < __SECTORS; ++nSector )
  1250. {
  1251. size_t nProtSectorCount = 0;
  1252. size_t nProtSectorStart = __SECTOR_TO_PROTSECTOR(nSector, nProtSectorCount);
  1253. // цикл по индивидуальным битам блоков/секторов внутри сектора 64КБ
  1254. for( size_t nProtSector = nProtSectorStart; nProtSector < nProtSectorStart + nProtSectorCount; ++nProtSector )
  1255. {
  1256. bool state = FLASH_PROTECTION_REGISTER_CHECK( contents->bSectors, nSector );
  1257. W25Q_LL_Routines.operations.writeEnable();
  1258. W25Q_LL_Routines.protection.protectStateWrite( nProtSector, state );
  1259. // проверяем готовность устройства
  1260. #if W25QXXX_BKGOPERATIONS
  1261. if( FLERR_TIMEOUT == flash_getready_time( _TIME_PGPRG_ms ) )
  1262. #else
  1263. if( FLERR_TIMEOUT == flash_api_getready() )
  1264. #endif
  1265. return FLERR_TIMEOUT;
  1266. }
  1267. }
  1268. return FLERR_SUCCESS;
  1269. }
  1270. // --------------------------------------------------------------------------------------------------------
  1271. // --------------------------------------------------------------------------------------------------------
  1272. // flash_api_sectorprotectregister_read - прочитывает регистр защиты (биты индивидуальной защиты СЕКТОРОВ 64К)
  1273. //
  1274. // * потоко-небезопасная функция
  1275. // * параметр @contents не может быть NULL - укажите буфер для содержимого регистра защиты (см. __flash_sectorprotectionregister_t)
  1276. static flash_err_t flash_api_sectorprotectregister_read( __flash_sectorprotectionregister_t * contents // буфер-приемник содержимого регистра защиты
  1277. ) // [W25Q OK]
  1278. {
  1279. if( NULL == contents ) return FLERR_INVALID_PARAMETER;
  1280. // цикл по секторам 64КБ
  1281. for( size_t nSector = 0; nSector < __SECTORS; ++nSector )
  1282. {
  1283. size_t nProtSectorCount = 0;
  1284. size_t nProtSectorStart = __SECTOR_TO_PROTSECTOR(nSector, nProtSectorCount);
  1285. bool state = false;
  1286. // цикл по индивидуальным битам блоков/секторов внутри сектора 64КБ
  1287. for( size_t nProtSector = nProtSectorStart; nProtSector < nProtSectorStart + nProtSectorCount; ++nProtSector )
  1288. {
  1289. if( W25Q_LL_Routines.protection.protectStateRead(( nProtSector ) ) )
  1290. {
  1291. state = true; // как минимум один блок особенного сектора защищен
  1292. break;
  1293. }
  1294. }
  1295. if( state )
  1296. FLASH_PROTECTION_REGISTER_SET(contents->bSectors, nSector);
  1297. else
  1298. FLASH_PROTECTION_REGISTER_CLEAR(contents->bSectors, nSector);
  1299. }
  1300. return FLERR_SUCCESS;
  1301. }
  1302. // --------------------------------------------------------------------------------------------------------
  1303. // flash_api_writeprotection_disable - снимает защиту от записи во всех секторах
  1304. //
  1305. // * потоко-небезопасная функция
  1306. static flash_err_t flash_api_writeprotection_disable() // [W25Q OK]
  1307. {
  1308. // разрешаем опрерации записи/стирания
  1309. W25Q_LL_Routines.operations.writeEnable();
  1310. // команда снятия защиты со всех секторов/блоков
  1311. W25Q_LL_Routines.protection.globalUnlock();
  1312. #if W25QXXX_BKGOPERATIONS // Global Unlock требует ожидания?
  1313. if( FLERR_TIMEOUT == flash_getready_time( _TIME_PGPRG_ms ) )
  1314. #else
  1315. if( FLERR_TIMEOUT == flash_api_getready() )
  1316. #endif
  1317. return FLERR_TIMEOUT;
  1318. flash_LL_buf_t buf;
  1319. // запрос буфера драйвера LL
  1320. buf.rawptr = W25Q_LL_Routines.service.getBuf( fibufSectorFlags, &buf.size );
  1321. // проверка буфера
  1322. if( NULL == buf.pSectorProtectionRegister ||
  1323. buf.size < sizeof(__flash_sectorprotectionregister_t) )
  1324. {
  1325. Return(FLERR_INVALID_BUFFER);
  1326. }
  1327. // чтение флагов защиты секторов
  1328. flash_api_sectorprotectregister_read( buf.pSectorProtectionRegister );
  1329. // проверка флагов всех секторов
  1330. for( size_t nSector = 0; nSector < __SECTORS; ++nSector )
  1331. {
  1332. if( FLASH_PROTECTION_REGISTER_CHECK( buf.pSectorProtectionRegister->bSectors, nSector ) )
  1333. {
  1334. // найден защищенный сектор, хотя такого быть не должно: ошибка выполнения
  1335. Return(FLERR_GENERIC_ERROR);
  1336. }
  1337. }
  1338. // теперь защита от записи снята для всех секторов. команда выполнена
  1339. Return(FLERR_SUCCESS);
  1340. }
  1341. // --------------------------------------------------------------------------------------------------------
  1342. // flash_api_buffer_programm - запись страничного буфера (4K)
  1343. // * внутренняя функция
  1344. // * не стирает страницу перед записью буфера
  1345. // * не проверяет переданные параметры
  1346. // * потоко-небезопасная функция
  1347. // # Возвращает либо FLERR_SUCCESS если ошибок не произошло, либо FLERR_UNEXPECTED_BUSY
  1348. // если чип непредвиденно занят до или после операции записи
  1349. static flash_err_t flash_api_buffer_programm( flash_LL_buf_t * buf, __FLASH_DWORD page )
  1350. {
  1351. __flash_pageprogramptr_t chunkBuffer = (__flash_pageprogramptr_t)buf->rawptr;
  1352. __FLASH_DWORD w24Address = __FLASH_PAGE2ADDRESS(page);
  1353. // проверка занятости
  1354. if( FLASH_ERROR( W25Q_LL_Routines.ready.getReadyFast() ) ) Return(FLERR_UNEXPECTED_BUSY);
  1355. for( __FLASH_DWORD byteWritten = 0; byteWritten < buf->size; )
  1356. {
  1357. // разрешаем опрерации записи/стирания
  1358. W25Q_LL_Routines.operations.writeEnable();
  1359. // производится запись
  1360. W25Q_LL_Routines.data.chunkProgram( chunkBuffer, w24Address );
  1361. #if W25QXXX_BKGOPERATIONS
  1362. if( FLASH_ERROR( W25Q_LL_Routines.ready.smartWaitms( _TIME_PGPRG_ms ) ) ) Return(FLERR_UNEXPECTED_BUSY);
  1363. #else
  1364. if( FLASH_ERROR( W25Q_LL_Routines.ready.getReadyFast() ) ) Return(FLERR_UNEXPECTED_BUSY);
  1365. #endif
  1366. w24Address += sizeof(*chunkBuffer);
  1367. byteWritten += sizeof(*chunkBuffer);
  1368. chunkBuffer ++; // переход к следующему куску (chunk, 256bytes)
  1369. }
  1370. return FLERR_SUCCESS;
  1371. }