| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394 |
- // Файл с API функциями работы с FLASH-чипом AT45DB321D
- // v 1.6 от 16/04/19
- // Автор: Сычев А.
- #define AT45DB321D_API_C
- #define AT45DB321D_APILEVEL // использование интерфейса низкоуровневых функций
- #include "drivers\flash\lowlevel\AT45DB321D_GLOB.h"
- #include "drivers\flash\lowlevel\AT45DB321D_LL_func.h"
- #include "drivers\flash\api\AT45DB321D_API.h"
- #include "drivers\flash\common\AT45DBXXX_HAL.h"
- #include "drivers\flash\api\AT45DB321D_APIfunc.h"
- const flash_properties_t FlashProperties =
- {
- .minAddress = AT45FLASH_MINIMUM_ADDRESS,
- .maxAddress = AT45FLASH_MAXIMUM_ADDRESS,
- .maxSectors = AT45FLASH_SECTORS,
- .sectorSize = (AT45FLASH_PAGES_PER_SECTOR * AT45FLASH_PAGE_SIZE),
- };
- // Enter() и Return(.) - макросы блокировки ресурса в многозадачных ОС
- // При входе в критический участок кода - выполнение API функции - вызывается Enter(),
- // блокируя ресурс, при выходе - Leave() или Return(.) ( для выхода из функции )
- #define Enter() { __FLASH_LOCK(); }
- #define Leave() { __FLASH_UNLOCK(); }
- #define Return(code) { __FLASH_UNLOCK(); return (code); }
- //#define ret __FLASH_UNLOCK(); return
- // Done:
- // flash_initialize(...) // Высокоуровневая инициализация памяти (установка размера страницы, установка параметров защиты секторов...)
- // flash_erase(...) // стирание памяти (блоками, страницами или секторами)
- // flash_read(...) // чтение памяти по адресу
- // flash_protect(...) // защита секторов (модификация конфигурации защищаемых секторов)
- // flash_unprotect(...) // снятие защиты (модификация конфигурации защищаемых секторов)
- // flash_service(...) // получение информации о производителе, расширенной информации, размере памяти, размере страницы, количестве секторов, блоков, страниц и т.п.
- // flash_write(...) // запись памяти по адресу
- // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
- // flash_getready - проверка готовности устройства (со стандартным таймаутом)
- //
- // # Функция возвращает FLERR_SUCCESS, еслиу устройство готово, иначе FLERR_TIMEOUT
- static flash_err_t flash_getready()
- {
- Enter();
-
- if( __flash_smart_waitms( _TIME_FLASHAPI_TIMEOUT ) )
- {
- Return(FLERR_SUCCESS);
- }
- Return(FLERR_TIMEOUT);
- }
- static flash_err_t flash_getready_time( __FLASH_WORD timeout )
- {
- Enter();
- if( __flash_smart_waitms( timeout ) )
- {
- Return(FLERR_SUCCESS);
- }
- Return(FLERR_TIMEOUT);
- }
- // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
- // flash_initialize - инициализация драйвера и API работы с устройством
- //
- // # Функция возвращает FLERR_SUCCESS. Только в этом случае гарантируется нормальная работа.
- // # Функция возвращает ошибку инициализации при появлении сбоев или при непрохождении проверки (см файл конфигурации AT45DB321D_CONF.h)
- flash_err_t flash_initialize()
- {
- // производим нисзкоуровневую инициализацию: подаем питание и будим, проверяем наличие чипа, серию, производителя, размер...
- flash_err_t success = __flash_hal__initialize();
-
- if( FLASH_ERROR(success) )
- {
- // что-то пошло не так: ай печаль-печаль.
- return(success);
- }
-
- // отключаем защиту секторов при инициализации (общий бит защиты)
- success = flash_unprotect( 0 );
-
- if( FLASH_ERROR(success) )
- {
- // что-то пошло не так: ай печаль-печаль.
- return(success);
- }
-
- // считываем статус
- if( ! __flash_smart_waitms( _TIME_FLASHAPI_TIMEOUT ) )
- {
- // что-то пошло не так: ай печаль-печаль.
- return(success);
- }
- return(FLERR_SUCCESS);
- }
- // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
- // flash_finalize - безопасная де-инициализация драйвера
- // Функция завершает работу с флеш-памятью, отключаяя ее или переводя в режим гибернации
- // @bHibernate: булевый флаг, показывает, что нужно перевести флеш-память в режим гибернации,
- // если false - драйвер попытается отключить питание микросхемы, если разрешено управление питанием (AT45DB321D_POWER_MANAGEMENT)
- // если false и управление питанием запрещено, будет возвращена ошибка FLERR_INVALID_PARAMETER.
- // @bForce: насильное выполнение финализации в случае, если флеш-память занята незаконченной операцией.
- // если false и драйвер детектирует незаконченную операцию, будет возвращена ошибка FLERR_UNEXPECTED_BUSY.
- // Если выбран режим гибернации, после выдачи команды функция проверяет, уснула ли микросхема через чтение статуса.
- // Если в этом случае обнаруживается, что статус все еще считывается, генерируется ошибка FLERR_GENERIC_ERROR.
- // Данную проверку можно отключить опцией AT45DB321D_DONOTCHECK_HIBERNATE=1.
- // Внимание: проверка не реализуется если bHibernate=false.
- // # Функция возвращает FLERR_SUCCESS всегда, за исключением вышеописанных случаев.
- flash_err_t flash_finalize( bool bHibernate, bool bForce )
- {
- Enter();
-
- // подготовка к деинициализации
- flash_err_t status = __flash_hal__finalize_prepare();
- if( FLASH_ERROR(status) )
- {
- // ошибка, обнаружена проблема - устройство не готово
- // проверяем, разрешено ли принудительное завершение?
- if( bForce )
- {
- // разрешено, сначала производим сброс
- // доступно управление сигналом сброса?
- #if AT45DB321D_RESET_MANAGEMENT
- // да, производим сброс чипа
- __flash_hal__reset_pulse();
- #else
- // нет, а доступно управление питанием?
- #if AT45DB321D_POWER_MANAGEMENT
- // да, производим быстрый сброс чипа по питанию
- __flash_hal__power_pulse( 0, 0 );
- #else
- // нет, управление питанием тоже недоступно
- // возвращаем ошибку FLERR_INVALID_PARAMETER - невозможно выполнить принудительное отключение
- Return(FLERR_INVALID_PARAMETER);
- #endif
- #endif
- }
- else
- {
- // нет, принудительное завершение запрещено
- // возвращаем ошибку
- Return(status);
- }
- }
-
- // все нормально, продолжаем
- // выбран режим гибернации?
- if( bHibernate )
- {
- // отправляем микросхему поспать
- __flash_hal__sleepmode();
- #if AT45DB321D_DONOTCHECK_HIBERNATE == 0
- // проверяем, ответит ли микросхема?
- if( __flash_smart_waitms( _TIME_FLASHAPI_TIMEOUT ) )
- {
- // отвечает - бит готовности прочитался...
- // Может это просто подтянутый сигнал к +VCC?
- // попробуем по другому:
- if( FLASH_SUCCESS(__flash_hal__detect()) )
- {
- // ответила! значит точно не ложилась спать - ошибка
- Return(FLERR_GENERIC_ERROR);
- }
- }
- #endif
- }
- else
- {
- // доступно управление питанием?
- #if AT45DB321D_POWER_MANAGEMENT == 0
- // нет, недоступно, нечего делать, генерируем ошибку
- Return(FLERR_INVALID_PARAMETER);
- #else
- // Доступно, отключаем питание.
- __flash_hal__power_off();
- // не проверяем доступность, доверяем функции отключения питания
- #endif
- }
- Return(FLERR_SUCCESS);
- }
- // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
- // flash_service - функция получения общих сведений об флеш-памяти.
- // Полный список возможных запросов приведен ниже:
- // ЗАПРОС РАЗМЕР ТИП ТИП ИНФОРМАИИ
- // БУФЕРА ЗНАЧНИЯ
- // fsvc_getVendorId 2 __FLASH_WORD ID производителя
- // fsvc_getDeviceId 2 flash_deviceid_t ID устройства
- // fsvc_getExtInfo * __FLASH_BYTE[] расширенную информацию производителя
- // fsvc_getExtInfoLen 1 __FLASH_BYTE длинну расширенной информации производителя
- // fsvc_getCapacity 4 __FLASH_DWORD заявляемая по документации емкость устройства (MBit-s)
- // fsvc_getFullCapacity 4 __FLASH_DWORD полная емкость устройства (в байтах)
- // fsvc_getDataCapacity 4 __FLASH_DWORD доступная емкость устройства (в байтах)
- // fsvc_getProtect 1 __FLASH_BYTE информацию о защите секторов (общий бит защиты 0x00 или 0x01)
- // fsvc_getSectorsCount 2 __FLASH_WORD количество секторов
- // fsvc_getPagesCount 2 __FLASH_WORD количество страниц
- // fsvc_getBlocksCount 2 __FLASH_WORD количество блоков
- // fsvc_getPageSize 2 __FLASH_WORD размер страницы
- // fsvc_getReadyState 1 __FLASH_BYTE готовность устройства
- // fsvc_getMinAddress 4 __FLASH_DWORD минимально возможный линейный адрес
- // fsvc_getMaxAddress 4 __FLASH_DWORD максимально возможный линейный адрес
- //
- // * Параметр @si задает тип запроса (см. flash_service_info_t)
- // * Параметр @pdata должен указывать на заранее выделенный буфер памяти для сохранения
- // получаемых данных. Размер буфера зависит от типа запроса. Параметр не может быть NULL
- // * Параметр @pbufsize должен указывать на размер буфера, на который указывает pdata.
- // Параметр не может быть 0. Значение по указателю @pbufsize не может быть 0.
- // При успешном выполнении функции, по указателю @pbufsize будет записано фактическое количество
- // записанных в буфер данных.
- //
- // * Функция НЕ ОБНУЛЯЕТ память по указателю @pdata в случае, если передан слишком большой буфер.
- //
- // # Функция вернет ошибку FLERR_INVALID_PARAMETER при некорректном запросе @si
- // # Функция вернет ошибку FLERR_INVALID_PARAMETER если @pdata или @bufsize равны 0.
- // # Функция вернет ошибку FLERR_INVALID_BUFFER если размер буфера @size не достаточен для сохранения данных
- //
- // # Функция вернет FLERR_SUCCESS при отсутствии ошибок
- //
- flash_err_t flash_service( flash_service_info_t si, void * pdata, __FLASH_WORD * pbufsize )
- {
- if( !pdata || !pbufsize || !*pbufsize ) return(FLERR_INVALID_PARAMETER);
-
- Enter();
-
- switch( si )
- {
- case fsvc_getVendorId: // ID производителя
- case fsvc_getDeviceId: // ID устройства
- case fsvc_getCapacity: // заявляемая по документации емкость устройства (MBit-s)
- case fsvc_getDataCapacity: // доступная емкость устройства
- case fsvc_getFullCapacity: // полная емкость устройства
- {
- __FLASH_DWORD flashID = __flash_hal__manufactureridread( 0 );
-
- switch( si )
- {
- case fsvc_getVendorId: if( sizeof( __FLASH_WORD ) > *pbufsize )
- Return(FLERR_INVALID_BUFFER);
-
- *((__FLASH_WORD*)(pdata)) = ((__flash_rvid_t*) &flashID)->FullId;
- *pbufsize = sizeof(__FLASH_WORD);
-
- Return(FLERR_SUCCESS);
- //-------------------------
- case fsvc_getDeviceId: if( sizeof( __FLASH_WORD ) > *pbufsize )
- Return(FLERR_INVALID_BUFFER);
-
- *((flash_deviceid_t*)(pdata)) = ((__flash_rvid_t*) &flashID)->DevId;
- *pbufsize = sizeof(__FLASH_WORD);
-
- Return(FLERR_SUCCESS);
- //-------------------------
- case fsvc_getCapacity: if( sizeof( __FLASH_DWORD ) > *pbufsize )
- Return(FLERR_INVALID_BUFFER);
-
- *((__FLASH_DWORD*)(pdata)) = __FLASH_DENSITY2CAPACITY( ((flash_deviceid_t*)&((__flash_rvid_t*) &flashID)->DevId)->Density );
- *pbufsize = sizeof(__FLASH_DWORD);
-
- Return(FLERR_SUCCESS);
-
- //-------------------------
- case fsvc_getDataCapacity: if( sizeof( __FLASH_DWORD ) > *pbufsize )
- Return(FLERR_INVALID_BUFFER);
-
- *((__FLASH_DWORD*)(pdata)) = (AT45FLASH_MAXIMUM_ADDRESS - AT45FLASH_MINIMUM_ADDRESS);
- *pbufsize = sizeof(__FLASH_DWORD);
-
- Return(FLERR_SUCCESS);
-
- //-------------------------
- case fsvc_getFullCapacity: if( sizeof( __FLASH_DWORD ) > *pbufsize )
- Return(FLERR_INVALID_BUFFER);
-
- *((__FLASH_DWORD*)(pdata)) = (AT45FLASH_MAXIMUM_ADDRESS);
- *pbufsize = sizeof(__FLASH_DWORD);
-
- Return(FLERR_SUCCESS);
- }
- }
- break;
-
- case fsvc_getMinAddress:
- {
- if( sizeof( __FLASH_DWORD ) > *pbufsize )
- Return(FLERR_INVALID_BUFFER);
-
- *((__FLASH_DWORD*)(pdata)) = (AT45FLASH_MINIMUM_ADDRESS);
- *pbufsize = sizeof(__FLASH_DWORD);
-
- Return(FLERR_SUCCESS);
- }
- break;
-
- case fsvc_getMaxAddress:
- {
- if( sizeof( __FLASH_DWORD ) > *pbufsize )
- Return(FLERR_INVALID_BUFFER);
-
- *((__FLASH_DWORD*)(pdata)) = (AT45FLASH_MAXIMUM_ADDRESS);
- *pbufsize = sizeof(__FLASH_DWORD);
-
- Return(FLERR_SUCCESS);
- }
- break;
-
- //-------------------------
- case fsvc_getExtInfoLen: // длинну расширенной информации производителя
- case fsvc_getExtInfo: // расширенную информацию производителя
- {
- __flash_id_t mid;
- switch( si )
- {
- case fsvc_getExtInfoLen:
-
- if( sizeof( __FLASH_BYTE ) > *pbufsize )
- Return(FLERR_INVALID_BUFFER);
-
- mid.pExtBf = 0;
- mid.ExtLen = 0;
-
- // получение ДЛИННЫ расширенной информации
- __flash_hal__manufactureridread( &mid );
-
- *((__FLASH_BYTE*)(pdata)) = mid.ExtLen;
- *pbufsize = sizeof(__FLASH_BYTE);
-
- Return(FLERR_SUCCESS);
-
- case fsvc_getExtInfo:
-
- if( 1 * sizeof( __FLASH_BYTE ) > *pbufsize )
- Return(FLERR_INVALID_BUFFER);
-
- mid.pExtBf = pdata;
- mid.ExtLen = *pbufsize;
-
- // получение расширенной информации
- __flash_hal__manufactureridread( &mid );
-
- *pbufsize = mid.ExtLen;
-
- Return(FLERR_SUCCESS);
- }
- }
- Return(FLERR_INVALID_BUFFER);
-
- case fsvc_getReadyState: // готовность устройства
- {
- if( sizeof( __FLASH_BYTE ) <= *pbufsize )
- {
- *((__FLASH_BYTE*)(pdata)) = ( FLASH_SUCCESS( __flash_hal__getreadyfast() ) )? 0x01: 0x00;
-
- *pbufsize = sizeof(__FLASH_BYTE);
-
- Return(FLERR_SUCCESS);
- }
- }
- Return(FLERR_INVALID_BUFFER);
-
- case fsvc_getProtect: // информацию о защите секторов
- {
- if( sizeof( __FLASH_BYTE ) <= *pbufsize )
- {
- flash_err_t status = flash_getprotect(0);
-
- switch( status )
- {
- case FLERR_PROTECT_DISABLED:
-
- *pbufsize = sizeof(__FLASH_BYTE);
-
- *((__FLASH_BYTE*)(pdata)) = 0;
-
- Return(FLERR_SUCCESS);
-
- case FLERR_PROTECT_ENABLED:
-
- *pbufsize = sizeof(__FLASH_BYTE);
-
- *((__FLASH_BYTE*)(pdata)) = 1;
-
- Return(FLERR_SUCCESS);
- }
-
- Return(status); // Ошибка?
- }
- }
- Return(FLERR_INVALID_BUFFER);
-
- case fsvc_getPageSize: // размер страницы
- {
- if( sizeof( __FLASH_WORD ) >= *pbufsize )
- {
- *((__FLASH_WORD*)(pdata)) = AT45FLASH_PAGE_SIZE;
- *pbufsize = sizeof(__FLASH_WORD);
-
- Return(FLERR_SUCCESS);
- }
- }
- Return(FLERR_INVALID_BUFFER);
-
- case fsvc_getSectorsCount: // количество секторов
- {
- if( sizeof( __FLASH_WORD ) <= *pbufsize ) // 16.04.19 Bug Fixed: changed condition ">=" to "<="
- {
- *((__FLASH_WORD*)(pdata)) = AT45FLASH_SECTORS;
- *pbufsize = sizeof(__FLASH_WORD);
-
- Return(FLERR_SUCCESS);
- }
- }
- Return(FLERR_INVALID_BUFFER);
-
- case fsvc_getPagesCount: // количество страниц
- {
- if( sizeof( __FLASH_WORD ) >= *pbufsize )
- {
- *((__FLASH_WORD*)(pdata)) = AT45FLASH_PAGES;
- *pbufsize = sizeof(__FLASH_WORD);
-
- Return(FLERR_SUCCESS);
- }
- }
- Return(FLERR_INVALID_BUFFER);
-
- case fsvc_getBlocksCount: // количество блоков
- {
- if( sizeof( __FLASH_WORD ) >= *pbufsize )
- {
- *((__FLASH_WORD*)(pdata)) = AT45FLASH_BLOCKS;
- *pbufsize = sizeof(__FLASH_WORD);
-
- Return(FLERR_SUCCESS);
- }
- }
- Return(FLERR_INVALID_BUFFER);
- }
-
- Return(FLERR_INVALID_PARAMETER);
- }
- // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
- // flash_protect_ex - установить/снять защиту секторов
- // Поробности см. описание flash_protect() / flash_unprotect()
- //
- // @mode: flash_sector_unprotected - вызов из flash_unprotect()
- // @mode: flash_sector_protected - вызов из flash_protect()
- //
- flash_err_t flash_protect_ex( flash_api_protect_t * content, flash_api_protect_bits mode )
- {
- Enter();
-
- // проверяем устройство на занятость
- if( FLERR_TIMEOUT == flash_getready() ) Return(FLERR_TIMEOUT);
-
- // проверяем на NULL переданный параметр
- if( !content )
- {
- if( mode == flash_sector_unprotected )
- {
- // параметр NULL - значит СНИМАЕМ общий бит защиты
- __flash_hal__writeprotect_disable();
-
- // проверяем, сборсился ли бит защиты
- if( __flash_hal__getprotectstate() != FLERR_PROTECT_DISABLED )
- Return(FLERR_GENERIC_ERROR);
- }
- else
- {
- // параметр NULL - значит УСТАНАВЛИВАЕМ общий бит защиты
- __flash_hal__writeprotect_enable();
-
- // проверяем, установился ли бит защиты
- if( __flash_hal__getprotectstate() != FLERR_PROTECT_ENABLED )
- Return(FLERR_GENERIC_ERROR);
- }
- Return(FLERR_SUCCESS);
- }
- else
- {
- // режим модификации общего бита защиты
- switch( content->protection_modify )
- {
- case flash_sector_protect_nomodify:
-
- // не трогаем общий бит защиты
-
- break;
- case flash_sector_protect_modify:
-
- // flash_sector_protected
- if( content->protection_enabled )
- {
- // устанавливаем защиту
- __flash_hal__writeprotect_enable();
-
- if( __flash_hal__getprotectstate() != FLERR_PROTECT_ENABLED )
- Return(FLERR_GENERIC_ERROR);
- }
- // flash_sector_unprotected
- else
- {
- // снимаем защиту
- __flash_hal__writeprotect_disable();
-
- if( __flash_hal__getprotectstate() != FLERR_PROTECT_DISABLED )
- Return(FLERR_GENERIC_ERROR);
- }
-
- break;
-
- default:
- // неправильный параметр в поле protection_modify
- Return(FLERR_INVALID_PARAMETER);
- }
-
- // получаем указатель на буфер драйвера
- __flash_protectionregister_t * pReg = __flash_internal_getbuffer_protect();
- // зануляем память
- __FLASH_ZEROMEMORY( pReg, sizeof(__flash_protectionregister_t) );
- // считываем байты защиты
- __flash_hal__protectregister_read( pReg );
-
- //------------------------------------------------------
- // модифицируем значения регистра защиты
-
- // индивидуально для сектора 0a,0b
- if( content->sectors.s0 ) // flash_sector_protect_pick
- {
- // сектор выбран: устанавливаем или снимаем биты защиты
- if( mode == flash_sector_unprotected )
- {
- pReg->Sector0.prot_0a = __FLASH_PROTECTION_REG_S0_DISABLE;
- pReg->Sector0.prot_0b = __FLASH_PROTECTION_REG_S0_DISABLE;
- }
- else
- {
- pReg->Sector0.prot_0a = __FLASH_PROTECTION_REG_S0_ENABLE;
- pReg->Sector0.prot_0b = __FLASH_PROTECTION_REG_S0_ENABLE;
- }
- pReg->Sector0.reserved= 0;
- } else { /* не модифицировать статус защиты сектора */ }
-
- // модифицируем байты защиты
- for( int s = 1; s < __SECTORS_TYPICAL; ++s )
- {
- if( (content->sectors.bytes[ s/8 ]) & ( 1<<(s%8)) )
- {
- // сектор выбран: устанавливаем или снимаем биты защиты
- if( mode == flash_sector_unprotected )
- pReg->Sectors[ s ] = __FLASH_PROTECTION_REG_DISABLE;
- else
- pReg->Sectors[ s ] = __FLASH_PROTECTION_REG_ENABLE;
-
- } else { /* не модифицировать статус защиты сектора */ }
- }
-
- //------------------------------------------------------
- //
- // стираем регистр защиты
- __flash_hal__protectregister_erase();
-
- // проверяем готовность устройства
- #if AT45DB321D_BKGOPERATIONS
- if( FLERR_TIMEOUT == flash_getready_time( _TIME_PGERS_ms ) )
- #else
- if( FLERR_TIMEOUT == flash_getready() )
- #endif
- {
- // фатальная ошибка: регистр защиты стерт
- // устройство занято. продолжать не можем
- //
- // для восстановления регистра защиты необходимо
- // вызвать функцию flash_error_restore()
- //
- Return(FLERR_UNEXPECTED_BUSY);
- }
-
- // записываем регистр защиты
- __flash_hal__protectregister_write( pReg );
-
- //------------------------------------------------------
- //
- // проверяем готовность устройства
- #if AT45DB321D_BKGOPERATIONS
- if( FLERR_TIMEOUT == flash_getready_time( _TIME_PGPRG_ms ) )
- #else
- if( FLERR_TIMEOUT == flash_getready() )
- #endif
- {
- // Ошибка: запись длится дольше положенного времени
- Return(FLERR_TIMEOUT);
- }
-
- //------------------------------------------------------
-
- { // №№№№№№ ПРОВЕРКА №№№№№№
- // считываем байты защиты
- __flash_hal__protectregister_read( pReg );
- // индивидуально для сектора 0a,0b
- if( content->sectors.s0 ) // flash_sector_protect_pick
- {
- // сектор выбран: проверяем биты защиты
- if( mode == flash_sector_unprotected )
- {
- if( pReg->Sector0.prot_0a != __FLASH_PROTECTION_REG_S0_DISABLE ||
- pReg->Sector0.prot_0b != __FLASH_PROTECTION_REG_S0_DISABLE )
- {
- Return(FLERR_GENERIC_ERROR);
- }
- }
- else
- {
- if( pReg->Sector0.prot_0a != __FLASH_PROTECTION_REG_S0_ENABLE ||
- pReg->Sector0.prot_0b != __FLASH_PROTECTION_REG_S0_ENABLE )
- {
- Return(FLERR_GENERIC_ERROR);
- }
- }
- }
-
- // проверяем байты защиты
- for( int s = 1; s < __SECTORS_TYPICAL; ++s )
- {
- if( (content->sectors.bytes[ s/8 ]) & ( 1<<(s%8)) )
- {
- // сектор выбран: проверяем биты защиты
- if( mode == flash_sector_unprotected )
- {
- if( pReg->Sectors[ s ] != __FLASH_PROTECTION_REG_DISABLE )
- Return(FLERR_GENERIC_ERROR);
- }
- else
- {
- if( pReg->Sectors[ s ] != __FLASH_PROTECTION_REG_ENABLE )
- Return(FLERR_GENERIC_ERROR);
- }
- }
- }
- }
-
- //------------------------------------------------------
- // успех.
- Return(FLERR_SUCCESS);
- }
- }
- // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
- // flash_protect - установить защиту секторов
- //
- // Функция модифицирует флаги защиты сектров выбранных пользователем в состояние "защищен".
- // Установите соответствующие флаги в структуре @content в состояние "1" для защиты сектора.
- // Функция также может модифицировать общий флаг защиты выбранных секторов. Для этого установите
- // желаемое состояние защиты в поле protection_enabled ( 0 - не защищено, 1 - защищено ) и установите поле
- // protection_modify в состояние "flash_sector_protect_modify" для того, чтобы общий флаг защиты был
- // изменен.
- //
- // * Для того, чтобы модифицировать только флаги защиты секторов без изменения общего флага защиты,
- // установите поле protection_modify в состояние "flash_sector_protect_nomodify".
- //
- // * параметр @content может быть равен NULL
- //
- // * Для того, чтобы модифицировать только общий бит защиты
- // БЕЗ модификации частных флагов защиты сектров:
- // - Для УСТАНОВКИ общего бита защиты передайте NULL вместо параметра @content
- // - Для УСТАНОВКИ/СНЯТИЯ общего бита защиты установите ВСЕ поля частных флагов защиты
- // секторов (s0...s63) в состояние flash_sector_protect_nomodify, поле protection_modify
- // установите в "flash_sector_protect_modify", а поле protection_enabled в желаемое
- // состояние флага защиты: flash_sector_protected или flash_sector_unprotected
- //
- // # Функция вернет FLERR_SUCCESS, если в процессе операции не произошло ошибок.
- // # Функция вернет FLERR_INVALID_PARAMETER в случае, если обнаружит ошибку в переданном параметре
- // # Функция вернет FLERR_UNEXPECTED_BUSY в случае, если процесс выполнения был прерван из-за неожиданного отказа устройства
- // # Функция вернет FLERR_GENERIC_ERROR в случае, если общий бит защиты не был установлен из-за ошибки
- // # Функция вернет FLERR_GENERIC_ERROR в случае, если хотя бы один из выбранных битов защиты не был установлен/сброшен
- //
- flash_err_t flash_protect( flash_api_protect_t * content )
- {
- return( flash_protect_ex( content, flash_sector_protected ));
- }
- // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
- // flash_protect - снять защиту секторов. Функция аналогичная flash_protect(),
- // только имеет обратный эффект - снятие защиты с выбранных секторов.
- //
- // Функция модифицирует флаги защиты сектров выбранных пользователем в состояние "не защищен".
- // Установите соответствующие флаги в структуре @content в состояние "1" для снятия защиты сектора.
- // Функция также может модифицировать общий флаг защиты выбранных секторов. Для этого установите
- // желаемое состояние защиты в поле protection_enabled ( 0 - не защищено, 1 - защищено ) и установите поле
- // protection_modify в состояние "flash_sector_protect_modify" для того, чтобы общий флаг защиты был
- // изменен.
- //
- // * Для того, чтобы модифицировать только флаги защиты секторов без изменения общего флага защиты,
- // установите поле protection_modify в состояние "flash_sector_protect_nomodify".
- //
- // * параметр @content может быть равен NULL
- //
- // * Для того, чтобы модифицировать только общий бит защиты
- // БЕЗ модификации частных флагов защиты сектров:
- // - Для СНЯТИЯ общего бита защиты передайте NULL вместо параметра @content
- // - Для УСТАНОВКИ/СНЯТИЯ общего бита защиты установите ВСЕ поля частных флагов защиты
- // секторов (s0...s63) в состояние flash_sector_protect_nomodify, поле protection_modify
- // установите в "flash_sector_protect_modify", а поле protection_enabled в желаемое
- // состояние флага защиты: flash_sector_protected или flash_sector_unprotected
- //
- // # Функция вернет FLERR_SUCCESS, если в процессе операции не произошло ошибок.
- // # Функция вернет FLERR_INVALID_PARAMETER в случае, если обнаружит ошибку в переданном параметре
- // # Функция вернет FLERR_UNEXPECTED_BUSY в случае, если процесс выполнения был прерван из-за неожиданного отказа устройства
- // # Функция вернет FLERR_GENERIC_ERROR в случае, если общий бит защиты не был установлен из-за ошибки
- // # Функция вернет FLERR_GENERIC_ERROR в случае, если хотя бы один из выбранных битов защиты не был установлен/сброшен
- //
- flash_err_t flash_unprotect( flash_api_protect_t * content )
- {
- return( flash_protect_ex( content, flash_sector_unprotected ));
- }
- // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
- // flash_getprotect - получить информацию о защищенных секторах.
- // * Указатель @content может быть NULL.
- // # Возвращаемое значение - общий бит защиты protection_enabled.
- // Если защита установлена - будет возвращен код FLERR_PROTECT_ENABLED
- // Если защита снята - будет возвращен код FLERR_PROTECT_DISABLED
- // Если указатель @content не NULL, по адресу будет записана структура типа flash_api_getprotect_t,
- // содержащая информацию о защите сектора (один сектор на один бит), а поле protection_enabled
- // будет содержать общий бит защиты - flash_sector_protected (установлена) или flash_sector_unprotected (снята).
- flash_err_t flash_getprotect( flash_api_getprotect_t * content )
- {
- Enter();
-
- __flash_status_t status;
- // пользователь хочет получить детализацию по защите секторов
- if( content )
- {
- if( FLERR_TIMEOUT == flash_getready() ) Return(FLERR_TIMEOUT);
- // получаем указатель на буфер драйвера
- __flash_protectionregister_t * pReg = __flash_internal_getbuffer_protect();
- // зануляем память
- __FLASH_ZEROMEMORY( pReg, sizeof(__flash_protectionregister_t) );
- // считываем байты защиты
- __flash_hal__protectregister_read( pReg );
- if( pReg->Sector0.prot_0a == __FLASH_PROTECTION_REG_S0_ENABLE ||
- pReg->Sector0.prot_0b == __FLASH_PROTECTION_REG_S0_ENABLE )
- content->sectors.s0 = 1;
- else content->sectors.s0 = 0;
- for( int s = 1; s < __SECTORS_TYPICAL; ++s )
- {
- if( pReg->Sectors[ s ] == __FLASH_PROTECTION_REG_ENABLE )
- content->sectors.bytes[ s/8 ] |= ( 1<<(s%8) );
- else
- content->sectors.bytes[ s/8 ] &= ~( 1<<(s%8) );
- }
- }
- __flash_hal__statusread(&status);
- if( status.bProtect )
- {
- if( NULL != content ) // fixed: 22/05/19
- content->protection_enabled = flash_sector_protected;
- Return(FLERR_PROTECT_ENABLED);
- }
-
- if( NULL != content ) // fixed: 22/05/19
- content->protection_enabled = flash_sector_unprotected;
- Return(FLERR_PROTECT_DISABLED);
- }
- // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
- // flash_erase - мультирежимное стирание данных
- // * Параметр @mode задает режим стирания:
- // mode==fem_byaddress - начальное смещение задается адресом в параметре @start, длинна отрезка - @count в байтах
- // При этом минимальный стираемый диапазон - размер страницы.
- // Страница, которой принадлежит адрес @start стирается полностью
- // Страница, которой принадлежит адрес @start + @count также стирается полность
- // @start не может быть меньше AT45FLASH_MINIMUM_ADDRESS
- // mode==fem_bypage - начальное смещение задается номером страницы в параметре @start.
- // Количество стираемых страниц задается параметром @count
- // @start не может быть меньше AT45FLASH_PAGES_PER_SECTOR
- //
- // mode==fem_byblock - начальное смещение задается номером блока в параметре @start
- // Количество стираемых блоков задается параметром @count
- // @start не может быть меньше AT45FLASH_BLOCKS_PER_SECTOR
- //
- // mode==fem_bysector - начальное смещение задается номером сектора в параметре @start
- // Количество стираемых секторов задается параметром @count.
- // @start не может быть равен 0.
- //
- // Адресное пространство с 0 по AT45FLASH_MINIMUM_ADDRESS является зарезервированным. Попытка стирания элементов
- // в этом диапазоне приведет к ошибке.
- //
- // * Параметр @count не может быть 0.
- // Параметр @start не должен указывать на зарезервированную область.
- //
- // ! Функция НЕ проверяет защиту секторов !
- //
- // # Функция возвращает FLERR_SUCCESS если не произошло ошибок.
- // # Функция вернет FLERR_INVALID_PARAMETER если @start указывает на зарезервированную область.
- // # Функция вернет FLERR_INVALID_PARAMETER если диапазон стирания выходит за границу адресного пространства
- // # Функция вернет FLERR_INVALID_PARAMETER если @count равняется 0.
- // # Функция вернет FLERR_INVALID_PARAMETER если @mode имеет значение, отличное от перечисленных.
- // # Функция вернет FLERR_UNEXPECTED_BUSY если во время операции устройство перестало отвечать
- //
- flash_err_t flash_erase( flash_erase_mode_t mode, __FLASH_DWORD start, __FLASH_DWORD count )
- {
- if( !count || !start ) return(FLERR_INVALID_PARAMETER);
-
- Enter();
-
- switch( mode )
- {
- case fem_byaddress: // стирание по адресу
-
- if( start < AT45FLASH_MINIMUM_ADDRESS ) Return(FLERR_INVALID_PARAMETER);
- if( start + count > AT45FLASH_MAXIMUM_ADDRESS ) Return(FLERR_INVALID_PARAMETER);
-
- case fem_bypage: // стирание по страницам
- {
- __FLASH_DWORD PagesToErase=0;
- __FLASH_DWORD PageBegin =0;
-
- if( mode == fem_byaddress )
- {
- // стирание по адресу
- PagesToErase = __FLASH_PAGESINRANGE( start , count );
- PageBegin = __FLASH_ADDRESS2PAGE( start );
- }
- else
- {
- // стирание по страницам
- if( start < AT45FLASH_PAGES_PER_SECTOR ) Return(FLERR_INVALID_PARAMETER);
- if( start + count > __FULL_PAGES ) Return(FLERR_INVALID_PARAMETER);
-
- PagesToErase = count;
- PageBegin = start;
- }
-
- while( PagesToErase )
- {
- // проверяем, нельзя ли использовать блочное стирание?
- if( __FLASH_PAGE_ARRAGED_BY_BLOCK ( PageBegin ) && // проверяем выравниваение
- ( PagesToErase >= AT45FLASH_PAGES_PER_BLOCK ) ) // проверяем количество страниц
- {
- // можно!
-
- // стираем блок - это быстрее
- __flash_hal__block_erase( __FLASH_PAGE2BLOCK( PageBegin ) );
-
- #if AT45DB321D_BKGOPERATIONS
- if( FLERR_TIMEOUT == flash_getready_time( _TIME_BKERS_ms ) )
- #else
- if( FLERR_TIMEOUT == flash_getready() )
- #endif
- {
- // фатальная ошибка: устройство занято дольше обычного
- Return(FLERR_UNEXPECTED_BUSY);
- }
-
- PageBegin += __PAGES_PER_BLOCK;
- PagesToErase -= __PAGES_PER_BLOCK;
- }
- else
- {
- // нельзя
- __flash_hal__page_erase( PageBegin );
-
- #if AT45DB321D_BKGOPERATIONS
- if( FLERR_TIMEOUT == flash_getready_time( _TIME_PGERS_ms ) )
- #else
- if( FLERR_TIMEOUT == flash_getready() )
- #endif
- {
- // фатальная ошибка: устройство занято дольше обычного
- Return(FLERR_UNEXPECTED_BUSY);
- }
-
- PageBegin ++;
- PagesToErase --;
- }
- }
- }
- break;
-
- case fem_byblock: // стирание по блокам
- {
- if( start < AT45FLASH_PAGES_PER_SECTOR ) Return(FLERR_INVALID_PARAMETER);
- if( start + count > __BLOCKS ) Return(FLERR_INVALID_PARAMETER);
-
- while( count )
- {
- __flash_hal__block_erase( start );
-
- #if AT45DB321D_BKGOPERATIONS
- if( FLERR_TIMEOUT == flash_getready_time( _TIME_BKERS_ms ) )
- #else
- if( FLERR_TIMEOUT == flash_getready() )
- #endif
- {
- // фатальная ошибка: устройство занято дольше обычного
- Return(FLERR_UNEXPECTED_BUSY);
- }
-
- start ++;
- count --;
- }
- }
- break;
-
- case fem_bysector: // стирание по секторам
- {
- if( start == 0 ) Return(FLERR_INVALID_PARAMETER); // сектор 0 - зарезервирован
- if( start + count > __SECTORS ) Return(FLERR_INVALID_PARAMETER);
-
- while( count )
- {
- __flash_hal__sector_erase( start );
-
- #if AT45DB321D_BKGOPERATIONS
- if( FLERR_TIMEOUT == flash_getready_time( _TIME_SCERS_ms ) )
- #else
- if( FLERR_TIMEOUT == flash_getready() )
- #endif
- {
- // фатальная ошибка: устройство занято дольше обычного
- Return(FLERR_UNEXPECTED_BUSY);
- }
-
- start ++;
- count --;
- }
- }
- break;
-
- default: Return(FLERR_INVALID_PARAMETER);
- }
-
- // успех.
- Return(FLERR_SUCCESS);
- }
- // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
- // flash_write - мультирежимная запись данных по адресу
- //
- // * Параметр @address указывает линейный адрес в адресном пространстве чипа.
- // Область 0 - AT45FLASH_MINIMUM_ADDRESS является зарезервированной, все попытки записи в эту область вызовут ошибку.
- // * Параметр @pBuffer - должен указывать на буфер-источник данных для записи. Не может быть NULL.
- // * Параметр @size - должен указывать на размер данных на запись. Не может быть равен 0.
- // * Параметр @mode - задает режим записи. Доступны следующий режимы:
- // - fwm_safewrite - режим безопасной записи. Медленный режим, когда запись/стирание происходит
- // постранично с верификацией. В случае ошибки верификации запись прекращается,
- // остальная (незаписанная) часть данных не переписывается/не стрирается,
- // При этом функция возвращает ошибку FLERR_VERIFY_ERROR
- //
- // - fwm_fastwrite - режим быстрой записи. Стирание происходит по блокам (8 станиц, см. заголовочный файл)
- // Запись постраничная. Верификация данных не проводится.
- //
- // - fwm_compatible режим ускоренной записи. НЕ РЕАЛИЗОВАН. ИСПОЛЬЗУЕТСЯ fwm_fastwrite.
- // Нечто среднее между режимамаи безопасной и быстрой записи.
- // Стирание происходит по блокам, запись по страницам. По завершении записи/стирания
- // всего объема данных происходит верификация. При обнаружении ошибки возвращается код FLERR_VERIFY_ERROR.
- //
- //
- // # Функция возвращает FLERR_SUCCESS, если не произшло никаких ошибок.
- // # Функция возвращает FLERR_UNEXPECTED_BUSY, если во время записи произошел отказ устройства.
- // # Функция возвращает FLERR_VERIFY_ERROR, если обнаружена ошибка верификации данных.
- // # Функция возвращает FLERR_INVALID_PARAMETER, если указан неверный параметр:
- // - @address указывает на зарезервированную область, либо область записи выходит за границу адресного пространства;
- // - @pBuffer или @size равны 0;
- // - @mode имеет значение, отличное от перечисленных
- //
- // # Для быстрой работы требует включения режима AT45DB321D_BKGOPERATIONS
- // Функция использует три различные монорежимные функции записи:
- static flash_err_t flash_write_fast( flash_address_t address, __FLASH_BYTE * pBuffer, flash_address_t size );
- static flash_err_t flash_write_safe( flash_address_t address, __FLASH_BYTE * pBuffer, flash_address_t size );
- static flash_err_t flash_write_comp( flash_address_t address, __FLASH_BYTE * pBuffer, flash_address_t size );
-
- flash_err_t flash_write( flash_address_t address, __FLASH_BYTE * pBuffer, flash_address_t size, flash_write_mode_t mode )
- {
- if( address < AT45FLASH_MINIMUM_ADDRESS ) return(FLERR_INVALID_PARAMETER);
- if( !size || !pBuffer ) return(FLERR_INVALID_PARAMETER);
- if( address + size > AT45FLASH_MAXIMUM_ADDRESS ) return(FLERR_INVALID_PARAMETER);
-
- switch( mode )
- {
- case fwm_safewrite: //режим безопасной записи.
- // > Данные страницы прочитываются в буфер 1 чипа ( если запись страницы неполная )
- // > Данные страницы прочитываются в буфер 2 чипа ( если запись страницы неполная )
- // > Производится модификация данных в буфере 1 (запись в буфер со смещением)
- // > Используется команда стирание+запись страницы (буфер 1)
- // > Производится модификация данных в буфере 2 (пока идет запись)
- // > Производится сравнение записанной страницы с буфером 2
- // > Если данные совпадают - запись без ошибок
- /* ______________________
- / \
- | Slow Moderate Fast |
- | \ | / |
- | \ |
- | \ |
- | \ |
- | __\____ |
- \_____________________/
-
- */
- return(flash_write_safe( address, pBuffer, size ));
-
- case fwm_compatible: //режим ускоренной записи
- // > Данные блока считываются во временный буфер контроллера
- // > Производится стирание блока
- // > Пока блок стирается, модифицируем данные в буфере
- // > Постранично записываем данные в чип
- // > Поочередно загружаем в буфер 1 и буфер 2 страницы для сравнения
- // > Пока один буфер производит сравнение, записываем данные во второй
- // > При обнаружении расхождения генерируется ошибка
- /* ______________________
- / \
- | Slow Moderate Fast |
- | \ | / |
- | | |
- | | |
- | | |
- | ___|___ |
- \_____________________/
-
- */
- return(flash_write_comp( address, pBuffer, size ));
-
-
- case fwm_fastwrite: //режим быстрой записи.
- // > Данные страницы прочитываются в буфер 1 чипа ( если запись страницы неполная )
- // > Если возможно, производится стирание блока
- // > Пока блок стирается, модифицируем данные в буфере 1
- // > Постранично записываем данные в чип (если требуется, стриание+запись)
- // > Готово.
- /* ______________________
- / \
- | Slow Moderate Fast |
- | \ | / |
- | / |
- | / |
- | / |
- | _____/_ [!] |
- \_____________________/
-
- */
- return(flash_write_fast( address, pBuffer, size ));
-
- default:;
- }
-
- return(FLERR_INVALID_PARAMETER);
- }
- //----------
- // flash_write_safe() - обеспечивает режим записи fwm_safewrite
- // # НЕ ПРОВЕРЯЕТ ПЕРЕДАННЫЕ ПАРАМЕТРЫ
- // # Для быстрой работы требует включения режима AT45DB321D_BKGOPERATIONS
- static flash_err_t flash_write_safe( flash_address_t address, __FLASH_BYTE * pBuffer, flash_address_t size )
- {
- // > Данные страницы прочитываются в буфер 1 чипа ( если запись страницы неполная )
- // > Данные страницы прочитываются в буфер 2 чипа ( если запись страницы неполная )
- // > Производится модификация данных в буфере 1 (запись в буфер со смещением)
- // > Используется команда стирание+запись страницы (буфер 1)
- // > Производится модификация данных в буфере 2 (пока идет запись)
- // > Производится сравнение записанной страницы с буфером 2
- // > Если данные совпадают - запись без ошибок
-
- __FLASH_DWORD pageBegin = __FLASH_ADDRESS2PAGE( address ); // вычисляем номер первой страницы
- __FLASH_DWORD PagesToWrite = __FLASH_PAGESINRANGE( address, size ); // вычисляем количество затрагиваемых страниц
- __FLASH_DWORD BytesToWrite = __FLASH_DATAREMAININGINPAGE( address ); // вычисляем для первой страницы
-
- Enter();
-
- do
- {
- //---------------------
- // ПЕРВАЯ и ПОСЛЕДНЯЯ страницы могут записываться частично: требуется предварительное чтение
- if( __FLASH_ADDRESSOFFSETPAGE( address ) || PagesToWrite<=1 )
- {
- // Данные страницы прочитываются в буфер 1 чипа
- __flash_hal__pagetobuffer1( pageBegin );
- #if AT45DB321D_BKGOPERATIONS
- __FLASH_WAITus( _TIME_BLDCM_us );
- #endif
- if( FLASH_ERROR( __flash_hal__getreadyfast() ) ) Return(FLERR_UNEXPECTED_BUSY);
-
- // Данные страницы прочитываются в буфер 2 чипа
- __flash_hal__pagetobuffer2( pageBegin );
- #if AT45DB321D_BKGOPERATIONS
- __FLASH_WAITus( _TIME_BLDCM_us );
- #endif
- if( FLASH_ERROR( __flash_hal__getreadyfast() ) ) Return(FLERR_UNEXPECTED_BUSY);
- }
- //---------------------
- if( size < BytesToWrite ) BytesToWrite = size;
- //---------------------
- // Производится модификация данных в буфере 1 (запись в буфер со смещением)
- __flash_hal__buffer1_write( __FLASH_ADDRESSOFFSETPAGE( address ), // смещение в буфере
- pBuffer, // данные
- BytesToWrite ); // количество данных на запись
- //---------------------
- // идет запись: СТИРАНИЕ + ПРОГРАММИРОВАНИЕ
- __flash_hal__buffer1_program( pageBegin );
-
- #if AT45DB321D_BKGOPERATIONS == 0
- if( FLASH_ERROR( __flash_hal__getreadyfast() ) ) Return(FLERR_UNEXPECTED_BUSY);
- #endif
- //---------------------
- // Производится модификация данных в буфере 2 (запись в буфер со смещением)
- __flash_hal__buffer2_write( __FLASH_ADDRESSOFFSETPAGE( address ), // смещение в буфере
- pBuffer, // данные
- BytesToWrite ); // количество данных на запись
- //---------------------
- // дожидаемся завершения записи
- #if AT45DB321D_BKGOPERATIONS
- if( FLASH_ERROR( flash_getready_time( _TIME_PGEPR_ms ) ) ) Return(FLERR_UNEXPECTED_BUSY);
- #endif
- //---------------------
- // Производится сравнение записанной страницы с буфером 2
- __flash_hal__buffer1_compare( pageBegin );
-
- #if AT45DB321D_BKGOPERATIONS
- __FLASH_WAITus( _TIME_BLDCM_us );
- #endif
- //---------------------
- // Если данные совпадают - запись без ошибок
- if( FLASH_ERROR( __flash_hal__getcompareresult() ) ) Return(FLERR_VERIFY_ERROR);
- //---------------------
- pageBegin++;
- address += BytesToWrite;
- pBuffer += BytesToWrite;
- size -= BytesToWrite;
- BytesToWrite = __FLASH_DATAREMAININGINPAGE( address );
- }
- while( --PagesToWrite );
-
- Return(FLERR_SUCCESS);
- }
- //----------
- // flash_write_safe() - обеспечивает режим записи fwm_fastwrite
- // # НЕ ПРОВЕРЯЕТ ПЕРЕДАННЫЕ ПАРАМЕТРЫ
- // # Для быстрой работы требует включения режима AT45DB321D_BKGOPERATIONS
- static flash_err_t flash_write_fast( flash_address_t address, __FLASH_BYTE * pBuffer, flash_address_t size )
- {
- // > Данные страницы прочитываются в буфер 1 чипа ( если запись страницы неполная )
- // > Если возможно, производится стирание блока
- // > Пока блок стирается, модифицируем данные в буфере 1
- // > Постранично записываем данные в чип (если требуется, стриание+запись)
- // > Готово.
- __FLASH_DWORD pageBegin = __FLASH_ADDRESS2PAGE( address ); // вычисляем номер первой страницы
- __FLASH_DWORD PagesToWrite = __FLASH_PAGESINRANGE( address, size ); // вычисляем количество затрагиваемых страниц
- __FLASH_DWORD BytesToWrite = __FLASH_DATAREMAININGINPAGE( address ); // вычисляем для первой страницы
- __FLASH_DWORD PagesErased = 0; // количество заранее стретых страниц (блочное стирание)
-
- Enter();
-
- do
- {
- //---------------------
- // ПЕРВАЯ и ПОСЛЕДНЯЯ страницы могут записываться частично: требуется предварительное чтение
- if( __FLASH_ADDRESSOFFSETPAGE( address ) || PagesToWrite<=1 )
- {
- // Данные страницы прочитываются в буфер 1 чипа
- __flash_hal__pagetobuffer1( pageBegin );
- #if AT45DB321D_BKGOPERATIONS
- __FLASH_WAITus( _TIME_BLDCM_us );
- #endif
- if( FLASH_ERROR( __flash_hal__getreadyfast() ) ) Return(FLERR_UNEXPECTED_BUSY);
- }
- //---------------------
- if( size < BytesToWrite ) BytesToWrite = size;
- //---------------------
-
- // Производится стирание блока
- if( __FLASH_PAGE_ARRAGED_BY_BLOCK( pageBegin ) && PagesToWrite >= AT45FLASH_PAGES_PER_BLOCK )
- {
- __flash_hal__block_erase( __FLASH_PAGE2BLOCK( pageBegin ) );
-
- PagesErased = AT45FLASH_PAGES_PER_BLOCK; // запоминаем, что много-много страниц стерто
- }
- //---------------------
- // Производится модификация данных в буфере 1 (запись в буфер со смещением)
- __flash_hal__buffer1_write( __FLASH_ADDRESSOFFSETPAGE( address ), // смещение в буфере
- pBuffer, // данные
- BytesToWrite ); // количество данных на запись
-
-
- #if AT45DB321D_BKGOPERATIONS
- //---------------------
- // дожидаемся окончания стирания блока
- if( AT45FLASH_PAGES_PER_BLOCK == PagesErased ) // Только если только что стерли.
- if( FLASH_ERROR( flash_getready_time( _TIME_BKERS_ms ) ) ) Return(FLERR_UNEXPECTED_BUSY);
- #endif
- //---------------------
- // если стерто много страниц (блочное стирание )
- if( PagesErased )
- // идет запись: ПРОГРАММИРОВАНИЕ БЕЗ СТИРАНИЯ
- {
- __flash_hal__buffer1_program_wo_erase( pageBegin );
-
- PagesErased--;
- }
- else
- // идет запись: СТИРАНИЕ + ПРОГРАММИРОВАНИЕ
- __flash_hal__buffer1_program( pageBegin );
-
- #if AT45DB321D_BKGOPERATIONS == 0
- if( FLASH_ERROR( __flash_hal__getreadyfast() ) ) Return(FLERR_UNEXPECTED_BUSY);
- #endif
-
- //---------------------
- // дожидаемся завершения записи
- #if AT45DB321D_BKGOPERATIONS
- if( FLASH_ERROR( flash_getready_time( _TIME_PGEPR_ms ) ) ) Return(FLERR_UNEXPECTED_BUSY);
- #endif
-
- // ***************************************************************
- // * NOTE: строго говоря, можно было еще больше соптимизировать *
- // * и записывать в свободный второй буфер во время записи пер- *
- // * вого. Но это потребует переключения команд записи страниц *
- // * ( __flash_hal__buffer1_program_wo_erase и *
- // * __flash_hal__buffer1_program), а также команд записи *
- // * в буфер __flash_hal__pagetobuffer1, на ходу, потребуется *
- // * запоминать, какой буфер свободен. *
- // * В целях упрощения решено так не делать. *
- // ***************************************************************
-
- pageBegin++;
-
- address += BytesToWrite;
- pBuffer += BytesToWrite;
- size -= BytesToWrite;
- BytesToWrite = __FLASH_DATAREMAININGINPAGE( address );
- }
- while( --PagesToWrite );
-
- Return(FLERR_SUCCESS);
- }
- //----------
- // flash_write_safe() - обеспечивает режим записи fwm_compatible
- // # НЕ ПРОВЕРЯЕТ ПЕРЕДАННЫЕ ПАРАМЕТРЫ
- // # Для быстрой работы требует включения режима AT45DB321D_BKGOPERATIONS
- //
- // # РЕЖИМ НЕ РЕАЛИЗОВАН
- //
- #warning Режим записи fwm_fastwrite не реализован
- static flash_err_t flash_write_comp( flash_address_t address, __FLASH_BYTE * pBuffer, flash_address_t size )
- {
- // > Данные страницы прочитываются в буфер 1 чипа ( если запись страницы неполная )
- // > Если возможно, производится стирание блока
- // > Пока блок стирается, модифицируем данные в буфере 1
- // > Постранично записываем данные в чип (если требуется, стриание+запись)
- // ---------------------------------
- // Вызываем алгоритм быстрой записи fwm_fastwrite
- flash_err_t success = flash_write_fast( address, pBuffer, size );
- // если были ошибки - сообщаем
- if( FLASH_ERROR( success ) ) return(success);
- // ---------------------------------
- // Приступаем к верификации:
- // > Поочередно загружаем в буфер 1 и буфер 2 страницы для сравнения
- // > Пока один буфер производит сравнение, записываем данные во второй
- // > При обнаружении расхождения генерируется ошибка
- //
- // ВОПРОС: а будет ли это быстрее, чем сравнивать на ходу?! А может просто прочитать массив на борт CPU и использовать memcmp() ?
- //
- // функторы действий
- // void ( * buffer_write )(__FLASH_WORD,__FLASH_BYTE*,__FLASH_WORD) = __flash_hal__buffer1_write; // сначала выбираем буфер 1
- // void ( * buffer_compare )(__FLASH_WORD) = __flash_hal__buffer1_compare; //
- return(FLERR_SUCCESS);
- }
- // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
- // flash_read - чтение данных по адресу
- //
- // * Функция проверяет правильность переданных параметров
- // * Параметр @address задает линейный адрес внутри адресного пространства устройства.
- // Адресное пространство с адреса 0 до AT45FLASH_MINIMUM_ADDRESS (не включительно) является
- // зарезервированным. При попытке чтения из этого диапазона функция вернет ошибку.
- // Параметр @pvBuffer должен указывать на буфер-приемник для прочитанных данных.
- // Параметр @size должен указывать на размер буфер-приемника. Параметр показывает
- // количество байт для чтения в буфер.
-
- // # Если параметр @address указывает на адрес в диапазоне 0...AT45FLASH_MINIMUM_ADDRESS, функция вернет ошибку FLERR_INVALID_PARAMETER
- // # Если параметр @pvBuffer равен NULL, функция вернет ошибку FLERR_INVALID_PARAMETER
- // # Если параметр @size равен 0, функция вернет ошибку FLERR_INVALID_PARAMETER
-
- flash_err_t flash_read( flash_address_t address, __FLASH_BYTE * pBuffer, flash_address_t size )
- {
- // проверяем входные параметры
- if( address < AT45FLASH_MINIMUM_ADDRESS ) return(FLERR_INVALID_PARAMETER);
- if( !pBuffer || !size ) return(FLERR_INVALID_PARAMETER);
-
- #ifndef AT45DB321D_EMU512
- // проверяем диапазон чтения
- if( address + size > __FULL_CHIP_SIZE ) return(FLERR_INVALID_PARAMETER);
- #endif
-
- // получаем начальную страницу
- #ifdef AT45DB321D_EMU512
- __FLASH_DWORD PagesToRead = __FLASH_PAGESINRANGE( address , size );
- #endif
- __FLASH_DWORD PageBegin = __FLASH_ADDRESS2PAGE( address );
- __FLASH_DWORD PageOffset = __FLASH_ADDRESSOFFSETPAGE( address );
-
- Enter();
-
- // проверям готовность устройства
- if( FLERR_TIMEOUT == flash_getready() ) Return(FLERR_TIMEOUT);
-
- #ifndef AT45DB321D_EMU512
- // работа без эмуляции страниц по 512 байт
- __flash_hal__array_read( PageBegin, PageOffset, pBuffer, size );
-
- Return(FLERR_SUCCESS);
- #else
- // эмуляция размера страниц 512 байт
-
- // проверяем диапазон чтения
- if( PagesToRead + PageBegin > __FULL_PAGES ) Return(FLERR_INVALID_PARAMETER);
-
- // постраничное чтение
- while( size && PagesToRead )
- {
- __FLASH_DWORD BytesToRead = __PAGE_SIZE_USER - __FLASH_ADDRESSOFFSETPAGE( address );
-
- if( BytesToRead > size ) BytesToRead = size; // 22/09/15 - ErrorFix
-
- __flash_hal__page_read( PageBegin, PageOffset, pBuffer, BytesToRead );
-
- pBuffer += BytesToRead;
-
- address += BytesToRead;
-
- size -= BytesToRead;
-
- PageBegin++;
-
- PagesToRead--;
-
- PageOffset = 0;
- }
-
- Return(FLERR_SUCCESS);
- #endif
- }
- // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
- // flash_sleepmode - переход в режим пониженного энергопотребления
- // # переводит устройство в режим, когда все команды, кроме flash_wakeup игнорируются
- flash_err_t flash_sleepmode()
- {
- Enter();
- __flash_hal__sleepmode();
- Return(FLERR_SUCCESS);
- }
- // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
- // flash_wakeup - выход из режима пониженного энергопотребления
- // # выводит устройство из режима, когда все команды, кроме flash_wakeup игнорируются
- flash_err_t flash_wakeup()
- {
- Enter();
- __flash_hal__wakeup();
- if( __flash_smart_waitms( _TIME_FLASHAPI_TIMEOUT ) )
- {
- Return(FLERR_SUCCESS);
- }
- Return(FLERR_TIMEOUT);
- }
- // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
|