AT45DB161E_API.c 62 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466
  1. // Файл с API функциями работы с FLASH-чипом AT45DB161E
  2. // v 1.61 от 14/10/19
  3. // Автор: Сычев А.
  4. #define AT45DB161E_API_C
  5. #define AT45DB161E_APILEVEL // использование интерфейса низкоуровневых функций
  6. #include "drivers\flash\at45\config\AT45DB161E_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\at45\lowlevel\AT45DB161E_GLOB.h"
  11. #include "drivers\flash\at45\lowlevel\AT45DB161E_LL_func.h"
  12. #include "drivers\flash\at45\common\AT45DBXXX_HAL.h"
  13. static const char AT45FLASH_TEXTUAL_DESCRIPTION[] = "AT45DB161E";
  14. static const flash_properties_t FlashProperties_AT45DB161E =
  15. {
  16. .minAddress = AT45FLASH_MINIMUM_ADDRESS,
  17. .maxAddress = AT45FLASH_MAXIMUM_ADDRESS,
  18. .maxSectors = AT45FLASH_SECTORS,
  19. .sectorSize = (AT45FLASH_PAGES_PER_SECTOR * AT45FLASH_PAGE_SIZE),
  20. .pChipDescription = AT45FLASH_TEXTUAL_DESCRIPTION
  21. };
  22. // flash_api_initialize - инициализация драйвера и API работы с устройством
  23. static flash_err_t flash_api_initialize( bool detectOnly );
  24. // flash_api_getready - проверка готовности устройства (со стандартным таймаутом)
  25. static flash_err_t flash_api_getready();
  26. // flash_api_service - функция получения общих сведений об флеш-памяти.
  27. static flash_err_t flash_api_service( flash_service_info_t si, void * pdata, __FLASH_WORD * pbufsize );
  28. // flash_api_protect - установить защиту секторов
  29. static flash_err_t flash_api_protect( flash_api_protect_t * content );
  30. // flash_api_protect - снять защиту секторов
  31. static flash_err_t flash_api_unprotect( flash_api_protect_t * content );
  32. // flash_api_protect_ex - установить/снять защиту секторов
  33. static flash_err_t flash_api_protect_ex( flash_api_protect_t * content, flash_api_protect_bits mode );
  34. // flash_api_getprotect - получить информацию о защищенных секторах.
  35. static flash_err_t flash_api_getprotect( flash_api_getprotect_t * content );
  36. // flash_api_erase - мультирежимное стирание данных
  37. static flash_err_t flash_api_erase( flash_erase_mode_t mode, __FLASH_DWORD start, __FLASH_DWORD count );
  38. // flash_api_write - мультирежимная запись данных по адресу
  39. static flash_err_t flash_api_write( flash_address_t address, __FLASH_BYTE * pBuffer, flash_address_t size, flash_write_mode_t mode );
  40. // flash_api_read - чтение данных по адресу
  41. static flash_err_t flash_api_read( flash_address_t address, __FLASH_BYTE * pBuffer, flash_address_t size );
  42. // flash_api_sleepmode - переход в режим пониженного энергопотребления
  43. static flash_err_t flash_api_sleepmode();
  44. // flash_api_wakeup - выход из режима пониженного энергопотребления
  45. static flash_err_t flash_api_wakeup();
  46. // flash_api_finalize - деинициализация драйвера
  47. static flash_err_t flash_api_finalize( bool bHibernate, bool bForce );
  48. // дескриптор API
  49. const flash_api_descriptor_t AT45DB161E_API =
  50. {
  51. .routines = {
  52. .flashInitialize = flash_api_initialize,
  53. .flashGetReady = flash_api_getready,
  54. .flashService = flash_api_service,
  55. .flashProtect = flash_api_protect,
  56. .flashUnprotect = flash_api_unprotect,
  57. .flashProtectEx = flash_api_protect_ex,
  58. .flashGetProtect = flash_api_getprotect,
  59. .flashErase = flash_api_erase,
  60. .flashWrite = flash_api_write,
  61. .flashRead = flash_api_read,
  62. .flashSleepMode = flash_api_sleepmode,
  63. .flashWakeup = flash_api_wakeup,
  64. .flashFinalize = flash_api_finalize,
  65. },
  66. .flashProperties = &FlashProperties_AT45DB161E
  67. };
  68. // Enter() и Return(.) - макросы блокировки ресурса в многозадачных ОС
  69. // При входе в критический участок кода - выполнение API функции - вызывается Enter(),
  70. // блокируя ресурс, при выходе - Leave() или Return(.) ( для выхода из функции )
  71. #define Enter() { __FLASH_LOCK(); }
  72. #define Leave() { __FLASH_UNLOCK(); }
  73. #define Return(code) { __FLASH_UNLOCK(); return (code); }
  74. //#define ret __FLASH_UNLOCK(); return
  75. // Done:
  76. // flash_api_initialize(...) // Высокоуровневая инициализация памяти (установка размера страницы, установка параметров защиты секторов...)
  77. // flash_api_erase(...) // стирание памяти (блоками, страницами или секторами)
  78. // flash_api_read(...) // чтение памяти по адресу
  79. // flash_api_protect(...) // защита секторов (модификация конфигурации защищаемых секторов)
  80. // flash_api_unprotect(...) // снятие защиты (модификация конфигурации защищаемых секторов)
  81. // flash_api_service(...) // получение информации о производителе, расширенной информации, размере памяти, размере страницы, количестве секторов, блоков, страниц и т.п.
  82. // flash_api_write(...) // запись памяти по адресу
  83. // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
  84. // flash_api_getready - проверка готовности устройства (со стандартным таймаутом)
  85. //
  86. // # Функция возвращает FLERR_SUCCESS, еслиу устройство готово, иначе FLERR_TIMEOUT
  87. static flash_err_t flash_api_getready()
  88. {
  89. Enter();
  90. if( AT45_LL_Routines.smart_waitms( AT45DBXXX_API_TIMEOUT ) )
  91. {
  92. Return(FLERR_SUCCESS);
  93. }
  94. Return(FLERR_TIMEOUT);
  95. }
  96. static flash_err_t flash_api_getready_time( __FLASH_WORD timeout )
  97. {
  98. Enter();
  99. if( AT45_LL_Routines.smart_waitms( timeout ) )
  100. {
  101. Return(FLERR_SUCCESS);
  102. }
  103. Return(FLERR_TIMEOUT);
  104. }
  105. // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
  106. // flash_api_initialize - инициализация драйвера и API работы с устройством
  107. // * Если @detectOnly=true, производится только детектирование наличия чипа!
  108. // # Функция возвращает FLERR_SUCCESS. Только в этом случае гарантируется нормальная работа.
  109. // # Функция возвращает ошибку инициализации при появлении сбоев или при непрохождении проверки (см файл конфигурации AT45DB161E_CONF.h)
  110. static flash_err_t flash_api_initialize( bool detectOnly )
  111. {
  112. // производится определение наличия чипа на шине
  113. if( detectOnly )
  114. {
  115. return AT45_LL_Routines.startupDetect();
  116. }
  117. // производим нисзкоуровневую инициализацию: подаем питание и будим, проверяем наличие чипа, серию, производителя, размер...
  118. flash_err_t success = AT45_LL_Routines.initialize();
  119. if( FLASH_ERROR(success) )
  120. {
  121. // что-то пошло не так: ай печаль-печаль.
  122. return(success);
  123. }
  124. // отключаем защиту секторов при инициализации (общий бит защиты)
  125. success = flash_api_unprotect( NULL );
  126. if( FLASH_ERROR(success) )
  127. {
  128. // что-то пошло не так: ай печаль-печаль.
  129. return(success);
  130. }
  131. // считываем статус
  132. if( ! AT45_LL_Routines.smart_waitms( AT45DBXXX_API_TIMEOUT ) )
  133. {
  134. // что-то пошло не так: ай печаль-печаль.
  135. return(success);
  136. }
  137. return(FLERR_SUCCESS);
  138. }
  139. // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
  140. // flash_api_finalize - безопасная де-инициализация драйвера
  141. // Функция завершает работу с флеш-памятью, отключаяя ее или переводя в режим гибернации
  142. // @bHibernate: булевый флаг, показывает, что нужно перевести флеш-память в режим гибернации,
  143. // если false - драйвер попытается отключить питание микросхемы, если разрешено управление питанием (AT45DBXXX_POWER_MANAGEMENT)
  144. // если false и управление питанием запрещено, будет возвращена ошибка FLERR_INVALID_PARAMETER.
  145. // @bForce: насильное выполнение финализации в случае, если флеш-память занята незаконченной операцией.
  146. // если false и драйвер детектирует незаконченную операцию, будет возвращена ошибка FLERR_UNEXPECTED_BUSY.
  147. // Если выбран режим гибернации, после выдачи команды функция проверяет, уснула ли микросхема через чтение статуса.
  148. // Если в этом случае обнаруживается, что статус все еще считывается, генерируется ошибка FLERR_GENERIC_ERROR.
  149. // Данную проверку можно отключить опцией AT45DBXXX_DONOTCHECK_HIBERNATE=1.
  150. // Внимание: проверка не реализуется если bHibernate=false.
  151. // # Функция возвращает FLERR_SUCCESS всегда, за исключением вышеописанных случаев.
  152. static flash_err_t flash_api_finalize( bool bHibernate, bool bForce )
  153. {
  154. Enter();
  155. // подготовка к деинициализации
  156. flash_err_t status = AT45_LL_Routines.finalize_prepare();
  157. if( FLASH_ERROR(status) )
  158. {
  159. // ошибка, обнаружена проблема - устройство не готово
  160. // проверяем, разрешено ли принудительное завершение?
  161. if( bForce )
  162. {
  163. // разрешено, сначала производим сброс
  164. // доступно управление сигналом сброса?
  165. #if AT45DBXXX_RESET_MANAGEMENT
  166. // да, производим сброс чипа
  167. AT45_LL_Routines.reset_pulse();
  168. #else
  169. // нет, а доступно управление питанием?
  170. #if AT45DBXXX_POWER_MANAGEMENT
  171. // да, производим быстрый сброс чипа по питанию
  172. AT45_LL_Routines.power_pulse( 0, 0 );
  173. #else
  174. // нет, управление питанием тоже недоступно
  175. // возвращаем ошибку FLERR_INVALID_PARAMETER - невозможно выполнить принудительное отключение
  176. Return(FLERR_INVALID_PARAMETER);
  177. #endif
  178. #endif
  179. }
  180. else
  181. {
  182. // нет, принудительное завершение запрещено
  183. // возвращаем ошибку
  184. Return(status);
  185. }
  186. }
  187. // все нормально, продолжаем
  188. // выбран режим гибернации?
  189. if( bHibernate )
  190. {
  191. // отправляем микросхему поспать
  192. AT45_LL_Routines.sleepmode();
  193. #if AT45DBXXX_DONOTCHECK_HIBERNATE == 0
  194. // проверяем, ответит ли микросхема?
  195. if( AT45_LL_Routines.smart_waitms( AT45DBXXX_API_TIMEOUT ) )
  196. {
  197. // отвечает - бит готовности прочитался...
  198. // Может это просто подтянутый сигнал к +VCC?
  199. // попробуем по другому:
  200. if( FLASH_SUCCESS(AT45_LL_Routines.dirtyDetect()) )
  201. {
  202. // ответила! значит точно не ложилась спать - ошибка
  203. Return(FLERR_DEVICE_MALFUNCTION);
  204. }
  205. }
  206. #endif
  207. }
  208. else
  209. {
  210. // доступно управление питанием?
  211. #if AT45DBXXX_POWER_MANAGEMENT == 0
  212. // нет, недоступно, нечего делать, генерируем ошибку
  213. Return(FLERR_INVALID_PARAMETER);
  214. #else
  215. // Доступно, отключаем питание.
  216. AT45_LL_Routines.power_off();
  217. // не проверяем доступность, доверяем функции отключения питания
  218. #endif
  219. }
  220. Return(FLERR_SUCCESS);
  221. }
  222. // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
  223. // flash_api_service - функция получения общих сведений об флеш-памяти.
  224. // Полный список возможных запросов приведен ниже:
  225. // ЗАПРОС РАЗМЕР ТИП ТИП ИНФОРМАИИ
  226. // БУФЕРА ЗНАЧНИЯ
  227. // fsvc_getVendorId 2 __FLASH_WORD ID производителя
  228. // fsvc_getDeviceId 2 flash_deviceid_t ID устройства
  229. // fsvc_getExtInfo * __FLASH_BYTE[] расширенную информацию производителя
  230. // fsvc_getExtInfoLen 1 __FLASH_BYTE длинну расширенной информации производителя
  231. // fsvc_getCapacity 4 __FLASH_DWORD заявляемая по документации емкость устройства (MBit-s)
  232. // fsvc_getFullCapacity 4 __FLASH_DWORD полная емкость устройства (в байтах)
  233. // fsvc_getDataCapacity 4 __FLASH_DWORD доступная емкость устройства (в байтах)
  234. // fsvc_getProtect 1 __FLASH_BYTE информацию о защите секторов (общий бит защиты 0x00 или 0x01)
  235. // fsvc_getSectorsCount 2 __FLASH_WORD количество секторов
  236. // fsvc_getPagesCount 2 __FLASH_WORD количество страниц
  237. // fsvc_getBlocksCount 2 __FLASH_WORD количество блоков
  238. // fsvc_getPageSize 2 __FLASH_WORD размер страницы
  239. // fsvc_getReadyState 1 __FLASH_BYTE готовность устройства
  240. // fsvc_getMinAddress 4 __FLASH_DWORD минимально возможный линейный адрес
  241. // fsvc_getMaxAddress 4 __FLASH_DWORD максимально возможный линейный адрес
  242. //
  243. // * Параметр @si задает тип запроса (см. flash_service_info_t)
  244. // * Параметр @pdata должен указывать на заранее выделенный буфер памяти для сохранения
  245. // получаемых данных. Размер буфера зависит от типа запроса. Параметр не может быть NULL
  246. // * Параметр @pbufsize должен указывать на размер буфера, на который указывает pdata.
  247. // Параметр не может быть 0. Значение по указателю @pbufsize не может быть 0.
  248. // При успешном выполнении функции, по указателю @pbufsize будет записано фактическое количество
  249. // записанных в буфер данных.
  250. //
  251. // * Функция НЕ ОБНУЛЯЕТ память по указателю @pdata в случае, если передан слишком большой буфер.
  252. //
  253. // # Функция вернет ошибку FLERR_INVALID_PARAMETER при некорректном запросе @si
  254. // # Функция вернет ошибку FLERR_INVALID_PARAMETER если @pdata или @bufsize равны 0.
  255. // # Функция вернет ошибку FLERR_INVALID_BUFFER если размер буфера @size не достаточен для сохранения данных
  256. //
  257. // # Функция вернет FLERR_SUCCESS при отсутствии ошибок
  258. //
  259. static flash_err_t flash_api_service( flash_service_info_t si, void * pdata, __FLASH_WORD * pbufsize )
  260. {
  261. if( !pdata || !pbufsize || !*pbufsize ) return(FLERR_INVALID_PARAMETER);
  262. Enter();
  263. switch( si )
  264. {
  265. case fsvc_getVendorId: // ID производителя
  266. case fsvc_getDeviceId: // ID устройства
  267. case fsvc_getCapacity: // заявляемая по документации емкость устройства (MBit-s)
  268. case fsvc_getDataCapacity: // доступная емкость устройства
  269. case fsvc_getFullCapacity: // полная емкость устройства
  270. {
  271. __FLASH_DWORD flashID = AT45_LL_Routines.manufactureridread( 0 );
  272. switch( si )
  273. {
  274. case fsvc_getVendorId: if( sizeof( __FLASH_WORD ) > *pbufsize )
  275. Return(FLERR_INVALID_BUFFER);
  276. *((__FLASH_WORD*)(pdata)) = ((__flash_rvid_t*) &flashID)->FullId;
  277. *pbufsize = sizeof(__FLASH_WORD);
  278. Return(FLERR_SUCCESS);
  279. //-------------------------
  280. case fsvc_getDeviceId: if( sizeof( __FLASH_WORD ) > *pbufsize )
  281. Return(FLERR_INVALID_BUFFER);
  282. *((flash_deviceid_t*)(pdata)) = ((__flash_rvid_t*) &flashID)->DevId;
  283. *pbufsize = sizeof(__FLASH_WORD);
  284. Return(FLERR_SUCCESS);
  285. //-------------------------
  286. case fsvc_getCapacity: if( sizeof( __FLASH_DWORD ) > *pbufsize )
  287. Return(FLERR_INVALID_BUFFER);
  288. *((__FLASH_DWORD*)(pdata)) = __FLASH_DENSITY2CAPACITY( ((flash_deviceid_t*)&((__flash_rvid_t*) &flashID)->DevId)->Density );
  289. *pbufsize = sizeof(__FLASH_DWORD);
  290. Return(FLERR_SUCCESS);
  291. //-------------------------
  292. case fsvc_getDataCapacity: if( sizeof( __FLASH_DWORD ) > *pbufsize )
  293. Return(FLERR_INVALID_BUFFER);
  294. *((__FLASH_DWORD*)(pdata)) = (AT45FLASH_MAXIMUM_ADDRESS - AT45FLASH_MINIMUM_ADDRESS);
  295. *pbufsize = sizeof(__FLASH_DWORD);
  296. Return(FLERR_SUCCESS);
  297. //-------------------------
  298. case fsvc_getFullCapacity: if( sizeof( __FLASH_DWORD ) > *pbufsize )
  299. Return(FLERR_INVALID_BUFFER);
  300. *((__FLASH_DWORD*)(pdata)) = (AT45FLASH_MAXIMUM_ADDRESS);
  301. *pbufsize = sizeof(__FLASH_DWORD);
  302. Return(FLERR_SUCCESS);
  303. }
  304. }
  305. break;
  306. case fsvc_getMinAddress:
  307. {
  308. if( sizeof( __FLASH_DWORD ) > *pbufsize )
  309. Return(FLERR_INVALID_BUFFER);
  310. *((__FLASH_DWORD*)(pdata)) = (AT45FLASH_MINIMUM_ADDRESS);
  311. *pbufsize = sizeof(__FLASH_DWORD);
  312. Return(FLERR_SUCCESS);
  313. }
  314. break;
  315. case fsvc_getMaxAddress:
  316. {
  317. if( sizeof( __FLASH_DWORD ) > *pbufsize )
  318. Return(FLERR_INVALID_BUFFER);
  319. *((__FLASH_DWORD*)(pdata)) = (AT45FLASH_MAXIMUM_ADDRESS);
  320. *pbufsize = sizeof(__FLASH_DWORD);
  321. Return(FLERR_SUCCESS);
  322. }
  323. break;
  324. //-------------------------
  325. case fsvc_getExtInfoLen: // длинну расширенной информации производителя
  326. case fsvc_getExtInfo: // расширенную информацию производителя
  327. {
  328. __flash_id_t mid;
  329. switch( si )
  330. {
  331. case fsvc_getExtInfoLen:
  332. if( sizeof( __FLASH_BYTE ) > *pbufsize )
  333. Return(FLERR_INVALID_BUFFER);
  334. mid.pExtBf = 0;
  335. mid.ExtLen = 0;
  336. // получение ДЛИННЫ расширенной информации
  337. AT45_LL_Routines.manufactureridread( &mid );
  338. *((__FLASH_BYTE*)(pdata)) = mid.ExtLen;
  339. *pbufsize = sizeof(__FLASH_BYTE);
  340. Return(FLERR_SUCCESS);
  341. case fsvc_getExtInfo:
  342. if( 1 * sizeof( __FLASH_BYTE ) > *pbufsize )
  343. Return(FLERR_INVALID_BUFFER);
  344. mid.pExtBf = pdata;
  345. mid.ExtLen = *pbufsize;
  346. // получение расширенной информации
  347. AT45_LL_Routines.manufactureridread( &mid );
  348. *pbufsize = mid.ExtLen;
  349. Return(FLERR_SUCCESS);
  350. }
  351. }
  352. Return(FLERR_INVALID_BUFFER);
  353. case fsvc_getReadyState: // готовность устройства
  354. {
  355. if( sizeof( __FLASH_BYTE ) <= *pbufsize )
  356. {
  357. *((__FLASH_BYTE*)(pdata)) = ( FLASH_SUCCESS( AT45_LL_Routines.getreadyfast() ) )? 0x01: 0x00;
  358. *pbufsize = sizeof(__FLASH_BYTE);
  359. Return(FLERR_SUCCESS);
  360. }
  361. }
  362. Return(FLERR_INVALID_BUFFER);
  363. case fsvc_getProtect: // информацию о защите секторов
  364. {
  365. if( sizeof( __FLASH_BYTE ) <= *pbufsize )
  366. {
  367. flash_err_t status = flash_api_getprotect(0);
  368. switch( status )
  369. {
  370. case FLERR_PROTECT_DISABLED:
  371. *pbufsize = sizeof(__FLASH_BYTE);
  372. *((__FLASH_BYTE*)(pdata)) = 0;
  373. Return(FLERR_SUCCESS);
  374. case FLERR_PROTECT_ENABLED:
  375. *pbufsize = sizeof(__FLASH_BYTE);
  376. *((__FLASH_BYTE*)(pdata)) = 1;
  377. Return(FLERR_SUCCESS);
  378. }
  379. Return(status); // Ошибка?
  380. }
  381. }
  382. Return(FLERR_INVALID_BUFFER);
  383. case fsvc_getPageSize: // размер страницы
  384. {
  385. if( sizeof( __FLASH_WORD ) >= *pbufsize )
  386. {
  387. *((__FLASH_WORD*)(pdata)) = AT45FLASH_PAGE_SIZE;
  388. *pbufsize = sizeof(__FLASH_WORD);
  389. Return(FLERR_SUCCESS);
  390. }
  391. }
  392. Return(FLERR_INVALID_BUFFER);
  393. case fsvc_getSectorsCount: // количество секторов
  394. {
  395. if( sizeof( __FLASH_WORD ) <= *pbufsize ) // 16.04.19 Bug Fixed: changed condition ">=" to "<="
  396. {
  397. *((__FLASH_WORD*)(pdata)) = AT45FLASH_SECTORS;
  398. *pbufsize = sizeof(__FLASH_WORD);
  399. Return(FLERR_SUCCESS);
  400. }
  401. }
  402. Return(FLERR_INVALID_BUFFER);
  403. case fsvc_getPagesCount: // количество страниц
  404. {
  405. if( sizeof( __FLASH_WORD ) >= *pbufsize )
  406. {
  407. *((__FLASH_WORD*)(pdata)) = AT45FLASH_PAGES;
  408. *pbufsize = sizeof(__FLASH_WORD);
  409. Return(FLERR_SUCCESS);
  410. }
  411. }
  412. Return(FLERR_INVALID_BUFFER);
  413. case fsvc_getBlocksCount: // количество блоков
  414. {
  415. if( sizeof( __FLASH_WORD ) >= *pbufsize )
  416. {
  417. *((__FLASH_WORD*)(pdata)) = AT45FLASH_BLOCKS;
  418. *pbufsize = sizeof(__FLASH_WORD);
  419. Return(FLERR_SUCCESS);
  420. }
  421. }
  422. Return(FLERR_INVALID_BUFFER);
  423. }
  424. Return(FLERR_INVALID_PARAMETER);
  425. }
  426. // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
  427. // flash_api_protect_ex - установить/снять защиту секторов
  428. // Поробности см. описание flash_api_protect() / flash_api_unprotect()
  429. //
  430. // @mode: flash_sector_unprotected - вызов из flash_api_unprotect()
  431. // @mode: flash_sector_protected - вызов из flash_api_protect()
  432. //
  433. static flash_err_t flash_api_protect_ex( flash_api_protect_t * content, flash_api_protect_bits mode )
  434. {
  435. Enter();
  436. // проверяем устройство на занятость
  437. if( FLERR_TIMEOUT == flash_api_getready() ) Return(FLERR_TIMEOUT);
  438. // проверяем на NULL переданный параметр
  439. if( !content )
  440. {
  441. if( mode == flash_sector_unprotected )
  442. {
  443. // параметр NULL - значит СНИМАЕМ общий бит защиты
  444. AT45_LL_Routines.writeprotect_disable();
  445. // проверяем, сборсился ли бит защиты
  446. if( AT45_LL_Routines.getprotectstate() != FLERR_PROTECT_DISABLED )
  447. Return(FLERR_GENERIC_ERROR);
  448. }
  449. else
  450. {
  451. // параметр NULL - значит УСТАНАВЛИВАЕМ общий бит защиты
  452. AT45_LL_Routines.writeprotect_enable();
  453. // проверяем, установился ли бит защиты
  454. if( AT45_LL_Routines.getprotectstate() != FLERR_PROTECT_ENABLED )
  455. Return(FLERR_GENERIC_ERROR);
  456. }
  457. Return(FLERR_SUCCESS);
  458. }
  459. else
  460. {
  461. // режим модификации общего бита защиты
  462. switch( content->protection_modify )
  463. {
  464. case flash_sector_protect_nomodify:
  465. // не трогаем общий бит защиты
  466. break;
  467. case flash_sector_protect_modify:
  468. // flash_sector_protected
  469. if( content->protection_enabled )
  470. {
  471. // устанавливаем защиту
  472. AT45_LL_Routines.writeprotect_enable();
  473. if( AT45_LL_Routines.getprotectstate() != FLERR_PROTECT_ENABLED )
  474. Return(FLERR_GENERIC_ERROR);
  475. }
  476. // flash_sector_unprotected
  477. else
  478. {
  479. // снимаем защиту
  480. AT45_LL_Routines.writeprotect_disable();
  481. if( AT45_LL_Routines.getprotectstate() != FLERR_PROTECT_DISABLED )
  482. Return(FLERR_GENERIC_ERROR);
  483. }
  484. break;
  485. default:
  486. // неправильный параметр в поле protection_modify
  487. Return(FLERR_INVALID_PARAMETER);
  488. }
  489. // получаем указатель на буфер драйвера
  490. __flash_protectionregister_t * pReg = AT45_LL_Routines.internal_getbuffer_protect();
  491. // зануляем память
  492. __FLASH_ZEROMEMORY( pReg, sizeof(__flash_protectionregister_t) );
  493. // считываем байты защиты
  494. AT45_LL_Routines.protectregister_read( pReg );
  495. //------------------------------------------------------
  496. // модифицируем значения регистра защиты
  497. // индивидуально для сектора 0a,0b
  498. if( content->sectors.s0 ) // flash_sector_protect_pick
  499. {
  500. // сектор выбран: устанавливаем или снимаем биты защиты
  501. if( mode == flash_sector_unprotected )
  502. {
  503. pReg->Sector0.prot_0a = __FLASH_PROTECTION_REG_S0_DISABLE;
  504. pReg->Sector0.prot_0b = __FLASH_PROTECTION_REG_S0_DISABLE;
  505. }
  506. else
  507. {
  508. pReg->Sector0.prot_0a = __FLASH_PROTECTION_REG_S0_ENABLE;
  509. pReg->Sector0.prot_0b = __FLASH_PROTECTION_REG_S0_ENABLE;
  510. }
  511. pReg->Sector0.reserved= 0;
  512. } else { /* не модифицировать статус защиты сектора */ }
  513. // модифицируем байты защиты
  514. for( int s = 1; s < __SECTORS_TYPICAL; ++s )
  515. {
  516. if( (content->sectors.bytes[ s/8 ]) & ( 1<<(s%8)) )
  517. {
  518. // сектор выбран: устанавливаем или снимаем биты защиты
  519. if( mode == flash_sector_unprotected )
  520. pReg->Sectors[ s ] = __FLASH_PROTECTION_REG_DISABLE;
  521. else
  522. pReg->Sectors[ s ] = __FLASH_PROTECTION_REG_ENABLE;
  523. } else { /* не модифицировать статус защиты сектора */ }
  524. }
  525. //------------------------------------------------------
  526. //
  527. // стираем регистр защиты
  528. AT45_LL_Routines.protectregister_erase();
  529. // проверяем готовность устройства
  530. #if AT45DB161E_BKGOPERATIONS
  531. if( FLERR_TIMEOUT == flash_api_getready_time( _TIME_PGERS_ms ) )
  532. #else
  533. if( FLERR_TIMEOUT == flash_api_getready() )
  534. #endif
  535. {
  536. // фатальная ошибка: регистр защиты стерт
  537. // устройство занято. продолжать не можем
  538. //
  539. // для восстановления регистра защиты необходимо
  540. // вызвать функцию flash_error_restore()
  541. //
  542. Return(FLERR_UNEXPECTED_BUSY);
  543. }
  544. // записываем регистр защиты
  545. AT45_LL_Routines.protectregister_write( pReg );
  546. //------------------------------------------------------
  547. //
  548. // проверяем готовность устройства
  549. #if AT45DB161E_BKGOPERATIONS
  550. if( FLERR_TIMEOUT == flash_api_getready_time( _TIME_PGPRG_ms ) )
  551. #else
  552. if( FLERR_TIMEOUT == flash_api_getready() )
  553. #endif
  554. {
  555. // Ошибка: запись длится дольше положенного времени
  556. Return(FLERR_TIMEOUT);
  557. }
  558. //------------------------------------------------------
  559. { // №№№№№№ ПРОВЕРКА №№№№№№
  560. // считываем байты защиты
  561. AT45_LL_Routines.protectregister_read( pReg );
  562. // индивидуально для сектора 0a,0b
  563. if( content->sectors.s0 ) // flash_sector_protect_pick
  564. {
  565. // сектор выбран: проверяем биты защиты
  566. if( mode == flash_sector_unprotected )
  567. {
  568. if( pReg->Sector0.prot_0a != __FLASH_PROTECTION_REG_S0_DISABLE ||
  569. pReg->Sector0.prot_0b != __FLASH_PROTECTION_REG_S0_DISABLE )
  570. {
  571. Return(FLERR_GENERIC_ERROR);
  572. }
  573. }
  574. else
  575. {
  576. if( pReg->Sector0.prot_0a != __FLASH_PROTECTION_REG_S0_ENABLE ||
  577. pReg->Sector0.prot_0b != __FLASH_PROTECTION_REG_S0_ENABLE )
  578. {
  579. Return(FLERR_GENERIC_ERROR);
  580. }
  581. }
  582. }
  583. // проверяем байты защиты
  584. for( int s = 1; s < __SECTORS_TYPICAL; ++s )
  585. {
  586. if( (content->sectors.bytes[ s/8 ]) & ( 1<<(s%8)) )
  587. {
  588. // сектор выбран: проверяем биты защиты
  589. if( mode == flash_sector_unprotected )
  590. {
  591. if( pReg->Sectors[ s ] != __FLASH_PROTECTION_REG_DISABLE )
  592. Return(FLERR_GENERIC_ERROR);
  593. }
  594. else
  595. {
  596. if( pReg->Sectors[ s ] != __FLASH_PROTECTION_REG_ENABLE )
  597. Return(FLERR_GENERIC_ERROR);
  598. }
  599. }
  600. }
  601. }
  602. //------------------------------------------------------
  603. // успех.
  604. Return(FLERR_SUCCESS);
  605. }
  606. }
  607. // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
  608. // flash_api_protect - установить защиту секторов
  609. //
  610. // Функция модифицирует флаги защиты сектров выбранных пользователем в состояние "защищен".
  611. // Установите соответствующие флаги в структуре @content в состояние "1" для защиты сектора.
  612. // Функция также может модифицировать общий флаг защиты выбранных секторов. Для этого установите
  613. // желаемое состояние защиты в поле protection_enabled ( 0 - не защищено, 1 - защищено ) и установите поле
  614. // protection_modify в состояние "flash_sector_protect_modify" для того, чтобы общий флаг защиты был
  615. // изменен.
  616. //
  617. // * Для того, чтобы модифицировать только флаги защиты секторов без изменения общего флага защиты,
  618. // установите поле protection_modify в состояние "flash_sector_protect_nomodify".
  619. //
  620. // * параметр @content может быть равен NULL
  621. //
  622. // * Для того, чтобы модифицировать только общий бит защиты
  623. // БЕЗ модификации частных флагов защиты сектров:
  624. // - Для УСТАНОВКИ общего бита защиты передайте NULL вместо параметра @content
  625. // - Для УСТАНОВКИ/СНЯТИЯ общего бита защиты установите ВСЕ поля частных флагов защиты
  626. // секторов (s0...s63) в состояние flash_sector_protect_nomodify, поле protection_modify
  627. // установите в "flash_sector_protect_modify", а поле protection_enabled в желаемое
  628. // состояние флага защиты: flash_sector_protected или flash_sector_unprotected
  629. //
  630. // # Функция вернет FLERR_SUCCESS, если в процессе операции не произошло ошибок.
  631. // # Функция вернет FLERR_INVALID_PARAMETER в случае, если обнаружит ошибку в переданном параметре
  632. // # Функция вернет FLERR_UNEXPECTED_BUSY в случае, если процесс выполнения был прерван из-за неожиданного отказа устройства
  633. // # Функция вернет FLERR_GENERIC_ERROR в случае, если общий бит защиты не был установлен из-за ошибки
  634. // # Функция вернет FLERR_GENERIC_ERROR в случае, если хотя бы один из выбранных битов защиты не был установлен/сброшен
  635. //
  636. static flash_err_t flash_api_protect( flash_api_protect_t * content )
  637. {
  638. return( flash_api_protect_ex( content, flash_sector_protected ));
  639. }
  640. // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
  641. // flash_api_unprotect - снять защиту секторов. Функция аналогичная flash_api_protect(),
  642. // только имеет обратный эффект - снятие защиты с выбранных секторов.
  643. //
  644. // Функция модифицирует флаги защиты сектров выбранных пользователем в состояние "не защищен".
  645. // Установите соответствующие флаги в структуре @content в состояние "1" для снятия защиты сектора.
  646. // Функция также может модифицировать общий флаг защиты выбранных секторов. Для этого установите
  647. // желаемое состояние защиты в поле protection_enabled ( 0 - не защищено, 1 - защищено ) и установите поле
  648. // protection_modify в состояние "flash_sector_protect_modify" для того, чтобы общий флаг защиты был
  649. // изменен.
  650. //
  651. // * Для того, чтобы модифицировать только флаги защиты секторов без изменения общего флага защиты,
  652. // установите поле protection_modify в состояние "flash_sector_protect_nomodify".
  653. //
  654. // * параметр @content может быть равен NULL
  655. //
  656. // * Для того, чтобы модифицировать только общий бит защиты
  657. // БЕЗ модификации частных флагов защиты сектров:
  658. // - Для СНЯТИЯ общего бита защиты передайте NULL вместо параметра @content
  659. // - Для УСТАНОВКИ/СНЯТИЯ общего бита защиты установите ВСЕ поля частных флагов защиты
  660. // секторов (s0...s63) в состояние flash_sector_protect_nomodify, поле protection_modify
  661. // установите в "flash_sector_protect_modify", а поле protection_enabled в желаемое
  662. // состояние флага защиты: flash_sector_protected или flash_sector_unprotected
  663. //
  664. // # Функция вернет FLERR_SUCCESS, если в процессе операции не произошло ошибок.
  665. // # Функция вернет FLERR_INVALID_PARAMETER в случае, если обнаружит ошибку в переданном параметре
  666. // # Функция вернет FLERR_UNEXPECTED_BUSY в случае, если процесс выполнения был прерван из-за неожиданного отказа устройства
  667. // # Функция вернет FLERR_GENERIC_ERROR в случае, если общий бит защиты не был установлен из-за ошибки
  668. // # Функция вернет FLERR_GENERIC_ERROR в случае, если хотя бы один из выбранных битов защиты не был установлен/сброшен
  669. //
  670. static flash_err_t flash_api_unprotect( flash_api_protect_t * content )
  671. {
  672. return( flash_api_protect_ex( content, flash_sector_unprotected ));
  673. }
  674. // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
  675. // flash_api_getprotect - получить информацию о защищенных секторах.
  676. // * Указатель @content может быть NULL.
  677. // # Возвращаемое значение - общий бит защиты protection_enabled.
  678. // Если защита установлена - будет возвращен код FLERR_PROTECT_ENABLED
  679. // Если защита снята - будет возвращен код FLERR_PROTECT_DISABLED
  680. // Если указатель @content не NULL, по адресу будет записана структура типа flash_api_getprotect_t,
  681. // содержащая информацию о защите сектора (один сектор на один бит), а поле protection_enabled
  682. // будет содержать общий бит защиты - flash_sector_protected (установлена) или flash_sector_unprotected (снята).
  683. static flash_err_t flash_api_getprotect( flash_api_getprotect_t * content )
  684. {
  685. Enter();
  686. __flash_status_t status;
  687. // пользователь хочет получить детализацию по защите секторов
  688. if( content )
  689. {
  690. if( FLERR_TIMEOUT == flash_api_getready() ) Return(FLERR_TIMEOUT);
  691. // получаем указатель на буфер драйвера
  692. __flash_protectionregister_t * pReg = AT45_LL_Routines.internal_getbuffer_protect();
  693. // зануляем память
  694. __FLASH_ZEROMEMORY( pReg, sizeof(__flash_protectionregister_t) );
  695. // считываем байты защиты
  696. AT45_LL_Routines.protectregister_read( pReg );
  697. if( pReg->Sector0.prot_0a == __FLASH_PROTECTION_REG_S0_ENABLE ||
  698. pReg->Sector0.prot_0b == __FLASH_PROTECTION_REG_S0_ENABLE )
  699. content->sectors.s0 = 1;
  700. else content->sectors.s0 = 0;
  701. for( int s = 1; s < __SECTORS_TYPICAL; ++s )
  702. {
  703. if( pReg->Sectors[ s ] == __FLASH_PROTECTION_REG_ENABLE )
  704. content->sectors.bytes[ s/8 ] |= ( 1<<(s%8) );
  705. else
  706. content->sectors.bytes[ s/8 ] &= ~( 1<<(s%8) );
  707. }
  708. }
  709. AT45_LL_Routines.statusread(&status);
  710. if( status.bProtect )
  711. {
  712. if( NULL != content ) // fixed: 22/05/19
  713. content->protection_enabled = flash_sector_protected;
  714. Return(FLERR_PROTECT_ENABLED);
  715. }
  716. if( NULL != content ) // fixed: 22/05/19
  717. content->protection_enabled = flash_sector_unprotected;
  718. Return(FLERR_PROTECT_DISABLED);
  719. }
  720. // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
  721. // flash_api_erase - мультирежимное стирание данных
  722. // * Параметр @mode задает режим стирания:
  723. // mode==fem_byaddress - начальное смещение задается адресом в параметре @start, длинна отрезка - @count в байтах
  724. // При этом минимальный стираемый диапазон - размер страницы.
  725. // Страница, которой принадлежит адрес @start стирается полностью
  726. // Страница, которой принадлежит адрес @start + @count также стирается полность
  727. // @start не может быть меньше AT45FLASH_MINIMUM_ADDRESS
  728. // mode==fem_bypage - начальное смещение задается номером страницы в параметре @start.
  729. // Количество стираемых страниц задается параметром @count
  730. // @start не может быть меньше AT45FLASH_PAGES_PER_SECTOR
  731. //
  732. // mode==fem_byblock - начальное смещение задается номером блока в параметре @start
  733. // Количество стираемых блоков задается параметром @count
  734. // @start не может быть меньше AT45FLASH_BLOCKS_PER_SECTOR
  735. //
  736. // mode==fem_bysector - начальное смещение задается номером сектора в параметре @start
  737. // Количество стираемых секторов задается параметром @count.
  738. // @start не может быть равен 0.
  739. //
  740. // Адресное пространство с 0 по AT45FLASH_MINIMUM_ADDRESS является зарезервированным. Попытка стирания элементов
  741. // в этом диапазоне приведет к ошибке.
  742. //
  743. // * Параметр @count не может быть 0.
  744. // Параметр @start не должен указывать на зарезервированную область.
  745. //
  746. // ! Функция НЕ проверяет защиту секторов !
  747. //
  748. // # Функция возвращает FLERR_SUCCESS если не произошло ошибок.
  749. // # Функция вернет FLERR_INVALID_PARAMETER если @start указывает на зарезервированную область.
  750. // # Функция вернет FLERR_INVALID_PARAMETER если диапазон стирания выходит за границу адресного пространства
  751. // # Функция вернет FLERR_INVALID_PARAMETER если @count равняется 0.
  752. // # Функция вернет FLERR_INVALID_PARAMETER если @mode имеет значение, отличное от перечисленных.
  753. // # Функция вернет FLERR_UNEXPECTED_BUSY если во время операции устройство перестало отвечать
  754. //
  755. static flash_err_t flash_api_erase( flash_erase_mode_t mode, __FLASH_DWORD start, __FLASH_DWORD count )
  756. {
  757. if( !count || !start ) return(FLERR_INVALID_PARAMETER);
  758. Enter();
  759. switch( mode )
  760. {
  761. case fem_byaddress: // стирание по адресу
  762. if( start < AT45FLASH_MINIMUM_ADDRESS ) Return(FLERR_INVALID_PARAMETER);
  763. if( start + count > AT45FLASH_MAXIMUM_ADDRESS ) Return(FLERR_INVALID_PARAMETER);
  764. case fem_bypage: // стирание по страницам
  765. {
  766. __FLASH_DWORD PagesToErase=0;
  767. __FLASH_DWORD PageBegin =0;
  768. if( mode == fem_byaddress )
  769. {
  770. // стирание по адресу
  771. PagesToErase = __FLASH_PAGESINRANGE( start , count );
  772. PageBegin = __FLASH_ADDRESS2PAGE( start );
  773. }
  774. else
  775. {
  776. // стирание по страницам
  777. if( start < AT45FLASH_PAGES_PER_SECTOR ) Return(FLERR_INVALID_PARAMETER);
  778. if( start + count > __FULL_PAGES ) Return(FLERR_INVALID_PARAMETER);
  779. PagesToErase = count;
  780. PageBegin = start;
  781. }
  782. while( PagesToErase )
  783. {
  784. // проверяем, нельзя ли использовать блочное стирание?
  785. if( __FLASH_PAGE_ARRAGED_BY_BLOCK ( PageBegin ) && // проверяем выравниваение
  786. ( PagesToErase >= AT45FLASH_PAGES_PER_BLOCK ) ) // проверяем количество страниц
  787. {
  788. // можно!
  789. // стираем блок - это быстрее
  790. AT45_LL_Routines.block_erase( __FLASH_PAGE2BLOCK( PageBegin ) );
  791. #if AT45DB161E_BKGOPERATIONS
  792. if( FLERR_TIMEOUT == flash_api_getready_time( _TIME_BKERS_ms ) )
  793. #else
  794. if( FLERR_TIMEOUT == flash_api_getready() )
  795. #endif
  796. {
  797. // фатальная ошибка: устройство занято дольше обычного
  798. Return(FLERR_UNEXPECTED_BUSY);
  799. }
  800. PageBegin += __PAGES_PER_BLOCK;
  801. PagesToErase -= __PAGES_PER_BLOCK;
  802. }
  803. else
  804. {
  805. // нельзя
  806. AT45_LL_Routines.page_erase( PageBegin );
  807. #if AT45DB161E_BKGOPERATIONS
  808. if( FLERR_TIMEOUT == flash_api_getready_time( _TIME_PGERS_ms ) )
  809. #else
  810. if( FLERR_TIMEOUT == flash_api_getready() )
  811. #endif
  812. {
  813. // фатальная ошибка: устройство занято дольше обычного
  814. Return(FLERR_UNEXPECTED_BUSY);
  815. }
  816. PageBegin ++;
  817. PagesToErase --;
  818. }
  819. }
  820. }
  821. break;
  822. case fem_byblock: // стирание по блокам
  823. {
  824. if( start < AT45FLASH_PAGES_PER_SECTOR ) Return(FLERR_INVALID_PARAMETER);
  825. if( start + count > __BLOCKS ) Return(FLERR_INVALID_PARAMETER);
  826. while( count )
  827. {
  828. AT45_LL_Routines.block_erase( start );
  829. #if AT45DB161E_BKGOPERATIONS
  830. if( FLERR_TIMEOUT == flash_api_getready_time( _TIME_BKERS_ms ) )
  831. #else
  832. if( FLERR_TIMEOUT == flash_api_getready() )
  833. #endif
  834. {
  835. // фатальная ошибка: устройство занято дольше обычного
  836. Return(FLERR_UNEXPECTED_BUSY);
  837. }
  838. start ++;
  839. count --;
  840. }
  841. }
  842. break;
  843. case fem_bysector: // стирание по секторам
  844. {
  845. if( start == 0 ) Return(FLERR_INVALID_PARAMETER); // сектор 0 - зарезервирован
  846. if( start + count > __SECTORS ) Return(FLERR_INVALID_PARAMETER);
  847. while( count )
  848. {
  849. AT45_LL_Routines.sector_erase( start );
  850. #if AT45DB161E_BKGOPERATIONS
  851. if( FLERR_TIMEOUT == flash_api_getready_time( _TIME_SCERS_ms ) )
  852. #else
  853. if( FLERR_TIMEOUT == flash_api_getready() )
  854. #endif
  855. {
  856. // фатальная ошибка: устройство занято дольше обычного
  857. Return(FLERR_UNEXPECTED_BUSY);
  858. }
  859. start ++;
  860. count --;
  861. }
  862. }
  863. break;
  864. default: Return(FLERR_INVALID_PARAMETER);
  865. }
  866. // успех.
  867. Return(FLERR_SUCCESS);
  868. }
  869. // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
  870. // flash_api_write - мультирежимная запись данных по адресу
  871. //
  872. // * Параметр @address указывает линейный адрес в адресном пространстве чипа.
  873. // Область 0 - AT45FLASH_MINIMUM_ADDRESS является зарезервированной, все попытки записи в эту область вызовут ошибку.
  874. // * Параметр @pBuffer - должен указывать на буфер-источник данных для записи. Не может быть NULL.
  875. // * Параметр @size - должен указывать на размер данных на запись. Не может быть равен 0.
  876. // * Параметр @mode - задает режим записи. Доступны следующий режимы:
  877. // - fwm_safewrite - режим безопасной записи. Медленный режим, когда запись/стирание происходит
  878. // постранично с верификацией. В случае ошибки верификации запись прекращается,
  879. // остальная (незаписанная) часть данных не переписывается/не стрирается,
  880. // При этом функция возвращает ошибку FLERR_VERIFY_ERROR
  881. //
  882. // - fwm_fastwrite - режим быстрой записи. Стирание происходит по блокам (8 станиц, см. заголовочный файл)
  883. // Запись постраничная. Верификация данных не проводится.
  884. //
  885. // - fwm_compatible режим ускоренной записи. НЕ РЕАЛИЗОВАН. ИСПОЛЬЗУЕТСЯ fwm_fastwrite.
  886. // Нечто среднее между режимамаи безопасной и быстрой записи.
  887. // Стирание происходит по блокам, запись по страницам. По завершении записи/стирания
  888. // всего объема данных происходит верификация. При обнаружении ошибки возвращается код FLERR_VERIFY_ERROR.
  889. //
  890. //
  891. // # Функция возвращает FLERR_SUCCESS, если не произшло никаких ошибок.
  892. // # Функция возвращает FLERR_UNEXPECTED_BUSY, если во время записи произошел отказ устройства.
  893. // # Функция возвращает FLERR_VERIFY_ERROR, если обнаружена ошибка верификации данных.
  894. // # Функция возвращает FLERR_INVALID_PARAMETER, если указан неверный параметр:
  895. // - @address указывает на зарезервированную область, либо область записи выходит за границу адресного пространства;
  896. // - @pBuffer или @size равны 0;
  897. // - @mode имеет значение, отличное от перечисленных
  898. //
  899. // # Для быстрой работы требует включения режима AT45DB161E_BKGOPERATIONS
  900. // Функция использует три различные монорежимные функции записи:
  901. static flash_err_t flash_write_fast( flash_address_t address, __FLASH_BYTE * pBuffer, flash_address_t size );
  902. static flash_err_t flash_write_safe( flash_address_t address, __FLASH_BYTE * pBuffer, flash_address_t size );
  903. static flash_err_t flash_write_comp( flash_address_t address, __FLASH_BYTE * pBuffer, flash_address_t size );
  904. static flash_err_t flash_api_write( flash_address_t address, __FLASH_BYTE * pBuffer, flash_address_t size, flash_write_mode_t mode )
  905. {
  906. if( address < AT45FLASH_MINIMUM_ADDRESS ) return(FLERR_INVALID_PARAMETER);
  907. if( !size || !pBuffer ) return(FLERR_INVALID_PARAMETER);
  908. if( address + size > AT45FLASH_MAXIMUM_ADDRESS ) return(FLERR_INVALID_PARAMETER);
  909. switch( mode )
  910. {
  911. case fwm_safewrite: //режим безопасной записи.
  912. // > Данные страницы прочитываются в буфер 1 чипа ( если запись страницы неполная )
  913. // > Данные страницы прочитываются в буфер 2 чипа ( если запись страницы неполная )
  914. // > Производится модификация данных в буфере 1 (запись в буфер со смещением)
  915. // > Используется команда стирание+запись страницы (буфер 1)
  916. // > Производится модификация данных в буфере 2 (пока идет запись)
  917. // > Производится сравнение записанной страницы с буфером 2
  918. // > Если данные совпадают - запись без ошибок
  919. /* ______________________
  920. / \
  921. | Slow Moderate Fast |
  922. | \ | / |
  923. | \ |
  924. | \ |
  925. | \ |
  926. | __\____ |
  927. \_____________________/
  928. */
  929. return(flash_write_safe( address, pBuffer, size ));
  930. case fwm_compatible: //режим ускоренной записи
  931. // > Данные блока считываются во временный буфер контроллера
  932. // > Производится стирание блока
  933. // > Пока блок стирается, модифицируем данные в буфере
  934. // > Постранично записываем данные в чип
  935. // > Поочередно загружаем в буфер 1 и буфер 2 страницы для сравнения
  936. // > Пока один буфер производит сравнение, записываем данные во второй
  937. // > При обнаружении расхождения генерируется ошибка
  938. /* ______________________
  939. / \
  940. | Slow Moderate Fast |
  941. | \ | / |
  942. | | |
  943. | | |
  944. | | |
  945. | ___|___ |
  946. \_____________________/
  947. */
  948. return(flash_write_comp( address, pBuffer, size ));
  949. case fwm_fastwrite: //режим быстрой записи.
  950. // > Данные страницы прочитываются в буфер 1 чипа ( если запись страницы неполная )
  951. // > Если возможно, производится стирание блока
  952. // > Пока блок стирается, модифицируем данные в буфере 1
  953. // > Постранично записываем данные в чип (если требуется, стриание+запись)
  954. // > Готово.
  955. /* ______________________
  956. / \
  957. | Slow Moderate Fast |
  958. | \ | / |
  959. | / |
  960. | / |
  961. | / |
  962. | _____/_ [!] |
  963. \_____________________/
  964. */
  965. return(flash_write_fast( address, pBuffer, size ));
  966. default:;
  967. }
  968. return(FLERR_INVALID_PARAMETER);
  969. }
  970. //----------
  971. // flash_write_safe() - обеспечивает режим записи fwm_safewrite
  972. // # НЕ ПРОВЕРЯЕТ ПЕРЕДАННЫЕ ПАРАМЕТРЫ
  973. // # Для быстрой работы требует включения режима AT45DB161E_BKGOPERATIONS
  974. static flash_err_t flash_write_safe( flash_address_t address, __FLASH_BYTE * pBuffer, flash_address_t size )
  975. {
  976. // > Данные страницы прочитываются в буфер 1 чипа ( если запись страницы неполная )
  977. // > Данные страницы прочитываются в буфер 2 чипа ( если запись страницы неполная )
  978. // > Производится модификация данных в буфере 1 (запись в буфер со смещением)
  979. // > Используется команда стирание+запись страницы (буфер 1)
  980. // > Производится модификация данных в буфере 2 (пока идет запись)
  981. // > Производится сравнение записанной страницы с буфером 2
  982. // > Если данные совпадают - запись без ошибок
  983. __FLASH_DWORD pageBegin = __FLASH_ADDRESS2PAGE( address ); // вычисляем номер первой страницы
  984. __FLASH_DWORD PagesToWrite = __FLASH_PAGESINRANGE( address, size ); // вычисляем количество затрагиваемых страниц
  985. __FLASH_DWORD BytesToWrite = __FLASH_DATAREMAININGINPAGE( address ); // вычисляем для первой страницы
  986. Enter();
  987. do
  988. {
  989. //---------------------
  990. // ПЕРВАЯ и ПОСЛЕДНЯЯ страницы могут записываться частично: требуется предварительное чтение
  991. if( __FLASH_ADDRESSOFFSETPAGE( address ) || PagesToWrite<=1 )
  992. {
  993. // Данные страницы прочитываются в буфер 1 чипа
  994. AT45_LL_Routines.pagetobuffer1( pageBegin );
  995. #if AT45DB161E_BKGOPERATIONS
  996. __FLASH_WAITus( _TIME_BLDCM_us );
  997. #endif
  998. if( FLASH_ERROR( AT45_LL_Routines.getreadyfast() ) ) Return(FLERR_UNEXPECTED_BUSY);
  999. // Данные страницы прочитываются в буфер 2 чипа
  1000. AT45_LL_Routines.pagetobuffer2( pageBegin );
  1001. #if AT45DB161E_BKGOPERATIONS
  1002. __FLASH_WAITus( _TIME_BLDCM_us );
  1003. #endif
  1004. if( FLASH_ERROR( AT45_LL_Routines.getreadyfast() ) ) Return(FLERR_UNEXPECTED_BUSY);
  1005. }
  1006. //---------------------
  1007. if( size < BytesToWrite ) BytesToWrite = size;
  1008. //---------------------
  1009. // Производится модификация данных в буфере 1 (запись в буфер со смещением)
  1010. AT45_LL_Routines.buffer1_write( __FLASH_ADDRESSOFFSETPAGE( address ), // смещение в буфере
  1011. pBuffer, // данные
  1012. BytesToWrite ); // количество данных на запись
  1013. //---------------------
  1014. // идет запись: СТИРАНИЕ + ПРОГРАММИРОВАНИЕ
  1015. AT45_LL_Routines.buffer1_program( pageBegin );
  1016. #if AT45DB161E_BKGOPERATIONS == 0
  1017. if( FLASH_ERROR( AT45_LL_Routines.getreadyfast() ) ) Return(FLERR_UNEXPECTED_BUSY);
  1018. #endif
  1019. //---------------------
  1020. // Производится модификация данных в буфере 2 (запись в буфер со смещением)
  1021. AT45_LL_Routines.buffer2_write( __FLASH_ADDRESSOFFSETPAGE( address ), // смещение в буфере
  1022. pBuffer, // данные
  1023. BytesToWrite ); // количество данных на запись
  1024. //---------------------
  1025. // дожидаемся завершения записи
  1026. #if AT45DB161E_BKGOPERATIONS
  1027. if( FLASH_ERROR( flash_api_getready_time( _TIME_PGEPR_ms ) ) ) Return(FLERR_UNEXPECTED_BUSY);
  1028. #endif
  1029. //---------------------
  1030. // Производится сравнение записанной страницы с буфером 2
  1031. AT45_LL_Routines.buffer1_compare( pageBegin );
  1032. #if AT45DB161E_BKGOPERATIONS
  1033. __FLASH_WAITus( _TIME_BLDCM_us );
  1034. #endif
  1035. //---------------------
  1036. // Если данные совпадают - запись без ошибок
  1037. if( FLASH_ERROR( AT45_LL_Routines.getcompareresult() ) ) Return(FLERR_VERIFY_ERROR);
  1038. //---------------------
  1039. pageBegin++;
  1040. address += BytesToWrite;
  1041. pBuffer += BytesToWrite;
  1042. size -= BytesToWrite;
  1043. BytesToWrite = __FLASH_DATAREMAININGINPAGE( address );
  1044. }
  1045. while( --PagesToWrite );
  1046. Return(FLERR_SUCCESS);
  1047. }
  1048. //----------
  1049. // flash_write_safe() - обеспечивает режим записи fwm_fastwrite
  1050. // # НЕ ПРОВЕРЯЕТ ПЕРЕДАННЫЕ ПАРАМЕТРЫ
  1051. // # Для быстрой работы требует включения режима AT45DB161E_BKGOPERATIONS
  1052. static flash_err_t flash_write_fast( flash_address_t address, __FLASH_BYTE * pBuffer, flash_address_t size )
  1053. {
  1054. // > Данные страницы прочитываются в буфер 1 чипа ( если запись страницы неполная )
  1055. // > Если возможно, производится стирание блока
  1056. // > Пока блок стирается, модифицируем данные в буфере 1
  1057. // > Постранично записываем данные в чип (если требуется, стриание+запись)
  1058. // > Готово.
  1059. __FLASH_DWORD pageBegin = __FLASH_ADDRESS2PAGE( address ); // вычисляем номер первой страницы
  1060. __FLASH_DWORD PagesToWrite = __FLASH_PAGESINRANGE( address, size ); // вычисляем количество затрагиваемых страниц
  1061. __FLASH_DWORD BytesToWrite = __FLASH_DATAREMAININGINPAGE( address ); // вычисляем для первой страницы
  1062. __FLASH_DWORD PagesErased = 0; // количество заранее стретых страниц (блочное стирание)
  1063. Enter();
  1064. do
  1065. {
  1066. //---------------------
  1067. // ПЕРВАЯ и ПОСЛЕДНЯЯ страницы могут записываться частично: требуется предварительное чтение
  1068. if( __FLASH_ADDRESSOFFSETPAGE( address ) || PagesToWrite<=1 )
  1069. {
  1070. // Данные страницы прочитываются в буфер 1 чипа
  1071. AT45_LL_Routines.pagetobuffer1( pageBegin );
  1072. #if AT45DB161E_BKGOPERATIONS
  1073. __FLASH_WAITus( _TIME_BLDCM_us );
  1074. #endif
  1075. if( FLASH_ERROR( AT45_LL_Routines.getreadyfast() ) ) Return(FLERR_UNEXPECTED_BUSY);
  1076. }
  1077. //---------------------
  1078. if( size < BytesToWrite ) BytesToWrite = size;
  1079. //---------------------
  1080. // Производится стирание блока
  1081. if( __FLASH_PAGE_ARRAGED_BY_BLOCK( pageBegin ) && PagesToWrite >= AT45FLASH_PAGES_PER_BLOCK )
  1082. {
  1083. AT45_LL_Routines.block_erase( __FLASH_PAGE2BLOCK( pageBegin ) );
  1084. PagesErased = AT45FLASH_PAGES_PER_BLOCK; // запоминаем, что много-много страниц стерто
  1085. }
  1086. //---------------------
  1087. // Производится модификация данных в буфере 1 (запись в буфер со смещением)
  1088. AT45_LL_Routines.buffer1_write( __FLASH_ADDRESSOFFSETPAGE( address ), // смещение в буфере
  1089. pBuffer, // данные
  1090. BytesToWrite ); // количество данных на запись
  1091. #if AT45DB161E_BKGOPERATIONS
  1092. //---------------------
  1093. // дожидаемся окончания стирания блока
  1094. if( AT45FLASH_PAGES_PER_BLOCK == PagesErased ) // Только если только что стерли.
  1095. if( FLASH_ERROR( flash_api_getready_time( _TIME_BKERS_ms ) ) ) Return(FLERR_UNEXPECTED_BUSY);
  1096. #endif
  1097. //---------------------
  1098. // если стерто много страниц (блочное стирание )
  1099. if( PagesErased )
  1100. // идет запись: ПРОГРАММИРОВАНИЕ БЕЗ СТИРАНИЯ
  1101. {
  1102. AT45_LL_Routines.buffer1_program_wo_erase( pageBegin );
  1103. PagesErased--;
  1104. }
  1105. else
  1106. // идет запись: СТИРАНИЕ + ПРОГРАММИРОВАНИЕ
  1107. AT45_LL_Routines.buffer1_program( pageBegin );
  1108. #if AT45DB161E_BKGOPERATIONS == 0
  1109. if( FLASH_ERROR( AT45_LL_Routines.getreadyfast() ) ) Return(FLERR_UNEXPECTED_BUSY);
  1110. #endif
  1111. //---------------------
  1112. // дожидаемся завершения записи
  1113. #if AT45DB161E_BKGOPERATIONS
  1114. if( FLASH_ERROR( flash_api_getready_time( _TIME_PGEPR_ms ) ) ) Return(FLERR_UNEXPECTED_BUSY);
  1115. #endif
  1116. // ***************************************************************
  1117. // * NOTE: строго говоря, можно было еще больше соптимизировать *
  1118. // * и записывать в свободный второй буфер во время записи пер- *
  1119. // * вого. Но это потребует переключения команд записи страниц *
  1120. // * ( __flash_hal__buffer1_program_wo_erase и *
  1121. // * __flash_hal__buffer1_program), а также команд записи *
  1122. // * в буфер __flash_hal__pagetobuffer1, на ходу, потребуется *
  1123. // * запоминать, какой буфер свободен. *
  1124. // * В целях упрощения решено так не делать. *
  1125. // ***************************************************************
  1126. pageBegin++;
  1127. address += BytesToWrite;
  1128. pBuffer += BytesToWrite;
  1129. size -= BytesToWrite;
  1130. BytesToWrite = __FLASH_DATAREMAININGINPAGE( address );
  1131. }
  1132. while( --PagesToWrite );
  1133. Return(FLERR_SUCCESS);
  1134. }
  1135. //----------
  1136. // flash_write_safe() - обеспечивает режим записи fwm_compatible
  1137. // # НЕ ПРОВЕРЯЕТ ПЕРЕДАННЫЕ ПАРАМЕТРЫ
  1138. // # Для быстрой работы требует включения режима AT45DB161E_BKGOPERATIONS
  1139. //
  1140. // # РЕЖИМ НЕ РЕАЛИЗОВАН
  1141. //
  1142. #warning Режим записи fwm_fastwrite не реализован
  1143. static flash_err_t flash_write_comp( flash_address_t address, __FLASH_BYTE * pBuffer, flash_address_t size )
  1144. {
  1145. // > Данные страницы прочитываются в буфер 1 чипа ( если запись страницы неполная )
  1146. // > Если возможно, производится стирание блока
  1147. // > Пока блок стирается, модифицируем данные в буфере 1
  1148. // > Постранично записываем данные в чип (если требуется, стриание+запись)
  1149. // ---------------------------------
  1150. // Вызываем алгоритм быстрой записи fwm_fastwrite
  1151. flash_err_t success = flash_write_fast( address, pBuffer, size );
  1152. // если были ошибки - сообщаем
  1153. if( FLASH_ERROR( success ) ) return(success);
  1154. // ---------------------------------
  1155. // Приступаем к верификации:
  1156. // > Поочередно загружаем в буфер 1 и буфер 2 страницы для сравнения
  1157. // > Пока один буфер производит сравнение, записываем данные во второй
  1158. // > При обнаружении расхождения генерируется ошибка
  1159. //
  1160. // ВОПРОС: а будет ли это быстрее, чем сравнивать на ходу?! А может просто прочитать массив на борт CPU и использовать memcmp() ?
  1161. //
  1162. // функторы действий
  1163. // void ( * buffer_write )(__FLASH_WORD,__FLASH_BYTE*,__FLASH_WORD) = __flash_hal__buffer1_write; // сначала выбираем буфер 1
  1164. // void ( * buffer_compare )(__FLASH_WORD) = __flash_hal__buffer1_compare; //
  1165. return(FLERR_SUCCESS);
  1166. }
  1167. // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
  1168. // flash_api_read - чтение данных по адресу
  1169. //
  1170. // * Функция проверяет правильность переданных параметров
  1171. // * Параметр @address задает линейный адрес внутри адресного пространства устройства.
  1172. // Адресное пространство с адреса 0 до AT45FLASH_MINIMUM_ADDRESS (не включительно) является
  1173. // зарезервированным. При попытке чтения из этого диапазона функция вернет ошибку.
  1174. // Параметр @pvBuffer должен указывать на буфер-приемник для прочитанных данных.
  1175. // Параметр @size должен указывать на размер буфер-приемника. Параметр показывает
  1176. // количество байт для чтения в буфер.
  1177. // # Если параметр @address указывает на адрес в диапазоне 0...AT45FLASH_MINIMUM_ADDRESS, функция вернет ошибку FLERR_INVALID_PARAMETER
  1178. // # Если параметр @pvBuffer равен NULL, функция вернет ошибку FLERR_INVALID_PARAMETER
  1179. // # Если параметр @size равен 0, функция вернет ошибку FLERR_INVALID_PARAMETER
  1180. static flash_err_t flash_api_read( flash_address_t address, __FLASH_BYTE * pBuffer, flash_address_t size )
  1181. {
  1182. // проверяем входные параметры
  1183. if( address < AT45FLASH_MINIMUM_ADDRESS ) return(FLERR_INVALID_PARAMETER);
  1184. if( !pBuffer || !size ) return(FLERR_INVALID_PARAMETER);
  1185. #ifndef AT45DB161E_EMU512
  1186. // проверяем диапазон чтения
  1187. if( address + size > __FULL_CHIP_SIZE ) return(FLERR_INVALID_PARAMETER);
  1188. #endif
  1189. // получаем начальную страницу
  1190. #ifdef AT45DB161E_EMU512
  1191. __FLASH_DWORD PagesToRead = __FLASH_PAGESINRANGE( address , size );
  1192. #endif
  1193. __FLASH_DWORD PageBegin = __FLASH_ADDRESS2PAGE( address );
  1194. __FLASH_DWORD PageOffset = __FLASH_ADDRESSOFFSETPAGE( address );
  1195. Enter();
  1196. // проверям готовность устройства
  1197. if( FLERR_TIMEOUT == flash_api_getready() ) Return(FLERR_TIMEOUT);
  1198. #ifndef AT45DB161E_EMU512
  1199. // работа без эмуляции страниц по 512 байт
  1200. AT45_LL_Routines.array_read( PageBegin, PageOffset, pBuffer, size );
  1201. Return(FLERR_SUCCESS);
  1202. #else
  1203. // эмуляция размера страниц 512 байт
  1204. // проверяем диапазон чтения
  1205. if( PagesToRead + PageBegin > __FULL_PAGES ) Return(FLERR_INVALID_PARAMETER);
  1206. // постраничное чтение
  1207. while( size && PagesToRead )
  1208. {
  1209. __FLASH_DWORD BytesToRead = __PAGE_SIZE_USER - __FLASH_ADDRESSOFFSETPAGE( address );
  1210. if( BytesToRead > size ) BytesToRead = size; // 22/09/15 - ErrorFix
  1211. AT45_LL_Routines.page_read( PageBegin, PageOffset, pBuffer, BytesToRead );
  1212. pBuffer += BytesToRead;
  1213. address += BytesToRead;
  1214. size -= BytesToRead;
  1215. PageBegin++;
  1216. PagesToRead--;
  1217. PageOffset = 0;
  1218. }
  1219. Return(FLERR_SUCCESS);
  1220. #endif
  1221. }
  1222. // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
  1223. // flash_api_sleepmode - переход в режим пониженного энергопотребления
  1224. // # переводит устройство в режим, когда все команды, кроме flash_api_wakeup игнорируются
  1225. static flash_err_t flash_api_sleepmode()
  1226. {
  1227. Enter();
  1228. AT45_LL_Routines.sleepmode();
  1229. Return(FLERR_SUCCESS);
  1230. }
  1231. // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
  1232. // flash_api_wakeup - выход из режима пониженного энергопотребления
  1233. // # выводит устройство из режима, когда все команды, кроме flash_api_wakeup игнорируются
  1234. static flash_err_t flash_api_wakeup()
  1235. {
  1236. Enter();
  1237. AT45_LL_Routines.wakeup();
  1238. if( AT45_LL_Routines.smart_waitms( AT45DBXXX_API_TIMEOUT ) )
  1239. {
  1240. Return(FLERR_SUCCESS);
  1241. }
  1242. Return(FLERR_TIMEOUT);
  1243. }
  1244. // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№