| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738 |
- // Файл с основными определениями для W25Q16JV.
- // v 1.0 от 08/10/20
- // Автор: Сычев А.
- // используйте следующие макросы перед подключением этого заголовочного файла
- // W25Q16JV_APILEVEL - для доступа к структурам и типам низокуровневых функций
- // W25Q16JV_LOWLEVEL - для доступа ко всем низкоуровневым определениям
- //
- // например: # файл c API для работы с флешкой использует
- // только интерфейсы, ему достаточно только W25Q16JV_APILEVEL
- // # файл, который реализует низкоуровневые команды требует W25Q16JV_LOWLEVEL
- // # пользовательский файл высокоуровневой программы вообще не требует этих макросов
- #ifndef W25Q16JV_H
- #define W25Q16JV_H
- // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
- // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№ ВВЕДЕНИЕ №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
- // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
- // ВНИМАНИЕ! Здесь и далее вводится замена "Сектор" => "Блок" и наоборот, т.к. данный драйвер основан
- // драйвере для чипа AT45, где под сектором понимается самый большой кусок данных, под блоком - кусок
- // по меньше, и под страницей - самый меньший. В W25Q под блоком наоборт - самый большой, а под сектором
- // самый малый, а страниц нет вообще. Для унификации для W25Q вводим замену понятия Блок - в даташите
- // блок это самый большой кусок, а в драйвере - будет самый малый. В даташите - сектор - самый малый
- // в данном драйвере - самый большой.
- // Такая замена необходима для сохранения внутренней структуры драйвера, функций и макросов.
- // W25Q16JV - чип энергонезависимой памяти емкостью 16 мегабит.
- // Чип W25Q16JV состоит из 32 секторов, 2 особенных и 30 обычных. Каждый сектор делится на 16 блоков
- // размером 4KB. Особенность 2 секторов заключается в том, как работает блочная защита от записи.
- // Особенные сектора расположены: один в начале памяти, один в конце.
- // Чип обладает 2 программными способами защиты от записи: индивидуальная защита секторов и групповая.
- // Индивидуальная защита позволяет заблокировать независимо каждый из 30 обычных секторов и независимо
- // каждый блок из 2 особенных секторов. В итоге есть возможность защитить 62 элемента: 30 по секторам
- // (все 16 блоков каждого из 30 секторов) и 32 по блокам (16+16 из 2 секторов). Групповая защита
- // строится на регистре защиты, где выбирается определенная часть защищаемого пространства от начала
- // памяти или от конца памяти. По умолчанию выбрана групповая схема защиты.
- //
- // Защита от записи:
- // -переходит в состояние сбороса если питание снижено до предела
- // -разрешает запись только после прошествии защитного итервала после выхода их сброса (либо при подаче питания)
- // -программная защита от записи активируется после каждой операции записи/стирания
- // -имеется HW и SW защита регистра статуса
- // -возможность индивидуальной защиты блока
- // -возможность защиты по защелке: защита снимается только после Power-up (пробуждения)
- // -возможность одноразового программирования: OTP
- //
- // Производитель обращает внимание на особенность, связанную с защитой от записи при формировании
- // сигнала выбора (CS): управляющий контроллер должен отслеживать уровень питания чипа с тем,
- // чтобы выставлять CS только когда уровень питания находится в допустимой зоне после старта,
- // а также перед выключнием, чтобы исключить выбор устройства вблизи границы напряжения питания.
- //
- // Чип позволяет использовать дополнительные линии передачи данных совместно с DO,
- // а именно Dual-Output и Quad-Output, для чего использутся отдельные команды.
- // Данная библиотека НЕ ПОДДЕРЖИВАЕТ данные режимы.
- /* <CONFIG> */
- #include <stdint.h>
- #include <stddef.h>
- #include "drivers\flash\w25q\config\W25Q16JV_CONF.h"
- #include "drivers\flash\base\bitbuffer.h"
- #ifndef W25QXXX_API_TIMEOUT
- #define W25QXXX_API_TIMEOUT _TIME_FLASHAPI_TIMEOUT
- #endif
- /* </CONFIG> */
- // Библиотека позволяет исключить циклы ожидания после
- // длительных команд, переложив ожидание ПОСЛЕ команды
- // в ожидание ПЕРЕД командой - активное ожидание освобождения
- // устройства через сканирования флага BUSY в статусном регистре.
- // Библиотека в любом случае использует чтение флага перед
- // каждой низкоуровневой командой, но делает это обычно 1 раз,
- // возвращая ошибку после неудачи. Используйте макрос W25QXXX_BKGOPERATIONS=1,
- // для того, чтобы использовать постоянное сканирование флага
- // перед командой вместо ожидания в конце команды. Используя данный режим,
- // будьте внимательны при сохранении данных перед выключением питания.
- // Библиотека позволяет использовать "умные" задержки после длительных
- // операций. Это означает, что ожидание после команды представляет собой
- // периодическое сканирование флага BUSY. Заданная в спецификации задержка
- // разбивается на квантованные промежутки времени, через которые происходит
- // опрос занятости устройства. Так предположительно длительная задержка
- // может быть сокращена при досрочном освобождении устройства. По умолчанию
- // режим "умных" задержек включен. Для выключения объявите макрос W25Q16JV_DONTUSESMARTDELAY=1
- // Режим "умных" задержек используется для обеспечения МИЛЛИСЕКУНДНЫХ задержек более W25QXXX_SMART_WAIT_THRESHOLD миллисекунд
- #define __FLASH_PAGE_WRITECYCLES 100000 // main datasheet
- #define __FLASH_STATUSREGISTER_WRITECYCLES 100000 // AN0000016 August 7, 2019 Revision 2.0
- /* <CONFIG> */
- //#define W25Q16JV_DONTUSESMARTDELAY 0 // отключение "умной" задержки
- //#define W25QXXX_BKGOPERATIONS 0 // отключение задержек операций | ВНИМАНИЕ! Только для ОПЫТНЫХ пользователей (-: !!!
- /* </CONFIG> */
- //--------------------------------------------------------------
- // Иерархия распределения блоков и секторов
- // Номера секторов - отнисительно блока секторов
- //--------------------------------------------------------------
- // W25Q16JV
- // _________
- // |
- // |-[-] Сектор 0 / Специальный сектор, содержит 16 блоков 4КБ
- // | | _____
- // | |___ Блок 0 }-----------------------------------------------+ [ 0] | |
- // | |___ Блок 1 }-----------------------------------------------+ [ 1] | |
- // | . | | I |
- // | . . | N |
- // | . | | D |
- // | |___ Блок 15 }-----------------------------------------------+ [15] | I |
- // | | | V |
- // | | | I |
- // |-[-] Сектор 1 / Обычный Сектор, содержит 16 блоков 4КБ }------+ [16] | D |
- // | | | | U |
- // | |___ Блок 0 | | A |
- // | |___ Блок 1 | | L |
- // | . . | |
- // | . . | S |
- // | . . | E |
- // | |___ Блок 15 | | C |
- // | | | T |
- // | | | O |
- // |-[-] Сектор 2 / Обычный Сектор, содержит 16 блоков 4КБ }------+ [17] | R |
- // | | | | / |
- // | |___ Блок 0 | | B |
- // | |___ Блок 1 | | L |
- // | . . | O |
- // | . . | C |
- // | . . | K |
- // | |___ Блок 15 | | |
- // . . | P |
- // . . | R |
- // . . | O |
- // |-[-] Сектор 30 / Обычный Сектор, содержит 16 блоков 4КБ }------+ [58] | T |
- // | | | | E |
- // | |___ Блок 0 | | C |
- // | |___ Блок 1 | | T |
- // | . . | I |
- // | . . | O |
- // | . . | N |
- // | |___ Блок 15 | | |
- // | | | R |
- // | | | E |
- // |-[-] Сектор 31 / Специальный Сектор, содержит 16 блоков 4КБ | | G |
- // | | | | I |
- // | |___ Блок 0 }-----------------------------------------------+ [59] | S |
- // | |___ Блок 1 }-----------------------------------------------+ [60] | T |
- // | . . | E |
- // | . . | R |
- // | . . | |
- // | |___ Блок 15 }-----------------------------------------------+ [61] |___|
- //
- //----------------------------------------------------------------------------------------------------------
- // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
- // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№ Внутренние определения №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
- // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
- // ##__##__##__##__##__##__##__##__##__##__##__##__##__##__##__##
- // ## ##
- // ## Распределение памяти ##
- // ## ##
- // ##__##__##__##__##__##__##__##__##__##__##__##__##__##__##__##
- // размер страницы
- #define __FULL_PAGE_SIZE 4096
- #define __PROG_PAGE_SIZE 256 // размер страницы при программировании
- // страницы (=сектора) стандартные - каждая страница имеет 4096 байт данных
- #define __PAGE_SIZE __FULL_PAGE_SIZE // размер страницы: для API
- #define __PAGE_SIZE_USER __PAGE_SIZE // размер страницы: для пользователя
- // размер блока
- #define __PAGES_PER_BLOCK 1
- #define __BLOCK_SIZE ( __PAGES_PER_BLOCK * __PAGE_SIZE )
- #define __BLOCK_SIZE_USER ( __PAGES_PER_BLOCK * __PAGE_SIZE_USER )
- // Количество секторов, блоков
- #define __SECTORS_TYPICAL 30 // количество обычных секторов
- #define __SECTORS_SPECIAL 2 // количество особенных секторов
- #define __SECTORS_FULL (__SECTORS_TYPICAL + __SECTORS_SPECIAL) // полное количество секторов
- #define __SECTORS __SECTORS_FULL
- #define __BLOCKS 512 // полное количество блоков
- #define __BLOCKS_PER_SECTOR 16 // количество блоков в секторе
- #define __FULL_PAGES (__BLOCKS * __PAGES_PER_BLOCK)
- #define __PAGES_PER_SECTOR (__BLOCKS_PER_SECTOR * __PAGES_PER_BLOCK )
- #define __PROT_SECTOR_FLAGS (__SECTORS_TYPICAL + (__SECTORS_SPECIAL) * (__BLOCKS_PER_SECTOR) )
- #define __PROT_SECTOR_TO_ADDRESS(n) W25Q16JV_prot_sector_to_address(n)
- #define __SECTOR_TO_PROTSECTOR(n,m) W25Q16JV_sector_to_protsector(n,&m)
- // размеры секторов
- #define __SECTOR_STD_SIZE 0x10000 // 64K
- #define __SECTOR0_SIZE __SECTOR_STD_SIZE
- #define __SECTOR1_SIZE __SECTOR_STD_SIZE
- #define __SECTOR2_SIZE __SECTOR_STD_SIZE
- #define __SECTOR3_SIZE __SECTOR_STD_SIZE
- #define __SECTOR4_SIZE __SECTOR_STD_SIZE
- #define __SECTOR5_SIZE __SECTOR_STD_SIZE
- #define __SECTOR6_SIZE __SECTOR_STD_SIZE
- #define __SECTOR7_SIZE __SECTOR_STD_SIZE
- #define __SECTOR8_SIZE __SECTOR_STD_SIZE
- #define __SECTOR9_SIZE __SECTOR_STD_SIZE
- #define __SECTOR10_SIZE __SECTOR_STD_SIZE
- #define __SECTOR11_SIZE __SECTOR_STD_SIZE
- #define __SECTOR12_SIZE __SECTOR_STD_SIZE
- #define __SECTOR13_SIZE __SECTOR_STD_SIZE
- #define __SECTOR14_SIZE __SECTOR_STD_SIZE
- #define __SECTOR15_SIZE __SECTOR_STD_SIZE
- #define __SECTOR16_SIZE __SECTOR_STD_SIZE
- #define __SECTOR17_SIZE __SECTOR_STD_SIZE
- #define __SECTOR18_SIZE __SECTOR_STD_SIZE
- #define __SECTOR19_SIZE __SECTOR_STD_SIZE
- #define __SECTOR20_SIZE __SECTOR_STD_SIZE
- #define __SECTOR21_SIZE __SECTOR_STD_SIZE
- #define __SECTOR22_SIZE __SECTOR_STD_SIZE
- #define __SECTOR23_SIZE __SECTOR_STD_SIZE
- #define __SECTOR24_SIZE __SECTOR_STD_SIZE
- #define __SECTOR25_SIZE __SECTOR_STD_SIZE
- #define __SECTOR26_SIZE __SECTOR_STD_SIZE
- #define __SECTOR27_SIZE __SECTOR_STD_SIZE
- #define __SECTOR28_SIZE __SECTOR_STD_SIZE
- #define __SECTOR29_SIZE __SECTOR_STD_SIZE
- #define __SECTOR30_SIZE __SECTOR_STD_SIZE
- #define __SECTOR31_SIZE __SECTOR_STD_SIZE
- #define __FULL_CHIP_SIZE (__BLOCKS * __PAGES_PER_BLOCK * __FULL_PAGE_SIZE)
- #define __FULL_DATA_SIZE (__FULL_CHIP_SIZE)
- // переводит НОМЕР защищаемого сектора в адрес
- // Защищаемый сектор - не всегда сектор 64КБ, для 0 и 31 секторов 64К из них
- // выводятся биты защиты для каждого блока 4К
- //
- // используется для команд индивидуальной защиты секторов/блоков
- static inline size_t W25Q16JV_prot_sector_to_address(size_t protsector)
- {
- size_t w24Address = 0;
- if( protsector > 0 && protsector < __PROT_SECTOR_FLAGS )
- {
- // проверка на первый специальный сектор, состоящий из __BLOCKS_PER_SECTOR
- // каждый блок такого сектора представлен отдельным битом защиты
- // Это сектор 0
- if( protsector < __BLOCKS_PER_SECTOR )
- {
- // адрес наращивается для каждого блока 4К в секторе 64К
- w24Address = (protsector * __BLOCK_SIZE);
- }
- else
- // Это обычные сектора 1..30, каждый сектора представлен одним битом защиты, без разбиения на блоки
- if( protsector >= __BLOCKS_PER_SECTOR && protsector < __BLOCKS_PER_SECTOR + __SECTORS_TYPICAL )
- {
- w24Address = (__SECTOR0_SIZE) + (protsector - __BLOCKS_PER_SECTOR) * (__SECTOR_STD_SIZE);
- }
- // Это опять особенный, последний, сектор, разделенный на защищаемые блоки
- else
- {
- w24Address = (protsector - __BLOCKS_PER_SECTOR - __SECTORS_TYPICAL) * (__BLOCK_SIZE) + (__SECTOR_STD_SIZE)*(__SECTORS - 1);
- }
- }
- return w24Address;
- }
- // вычисляет начальный номер protection-sector-block для сектора 64КБ
- // используется для команд индивидуальной защиты секторов/блоков
- static inline size_t W25Q16JV_sector_to_protsector(size_t nSector, size_t * pCount )
- {
- size_t nStartProtSector = 0;
-
- if( nSector == 0 )
- {
- nStartProtSector = 0;
- *pCount = __BLOCKS_PER_SECTOR; // количество protsectors в секторе 64КБ = 16 для особенного сектора
- }
- else if( nSector == __SECTORS - 1 )
- {
- nStartProtSector = __BLOCKS_PER_SECTOR + __SECTORS_TYPICAL;
- *pCount = __BLOCKS_PER_SECTOR; // количество protsectors в секторе 64КБ = 16 для особенного сектора
- }
- else
- {
- nStartProtSector = __BLOCKS_PER_SECTOR + nSector - 1;
- *pCount = 1; // количество protsectors в секторе 64КБ = 1 для обычного сектора
- }
- return nStartProtSector; // начальный номер protsector-а для сектора 64КБ
- }
- #include "drivers\flash\base\flash_api_types.h"
- #ifdef W25Q16JV_LOWLEVEL
- //---------------------------------------------------------------
- // Чип имеет 2 встроенных SRAM буфера по 528 байт для проведения
- // операций чтения/записи и сравнения. Чип позволяет читать
- // данные последовательно, страницу за страницей (послед. чтение).
- // Также возможна запись содержимого буфера в память со стиранием,
- // при этом стирание происходит автоматически.
- //---------------------------------------------------------------
- // ##__##__##__##__##__##__##__##__##__##__##__##__##__##__##__##
- // ## ##
- // ## команды обмена ##
- // ## ##
- // ##__##__##__##__##__##__##__##__##__##__##__##__##__##__##__##
- // чтение
- #define _RCMD_ARRYREAD 0x03 // последовательное чтение
- #define _LCMD_ARRYREAD 0x03 // последовательное чтение (до 50MHz)
- #define _HCMD_ARRYREAD 0x0B // последовательное чтение (до 133MHz)
- // запись
- #define _WCMD_PGWRIT 0x02 // Запись страницы
- // Стирание: Чип позволяет стирать память по-странично, и по-блочно
- #define _ECMD_PAGERASE 0x20 // Стирание страницы
- #define _ECMD_BLKERASE32 0x52 // Стирание 8 страниц
- // по-секторно
- #define _ECMD_SCTERASE 0xD8 // Стирание сектора
- // или целиком (последовательность 4 команд-байт)
- #define _ECMD_CHPERASE 0xC7 // Стрирание чипа
- // энергосберегающий режим, сброс
- #define _ACMD_EPWRDOWN 0xB9 // переход в спящий режим
- #define _ACMD_LPWRDOWN 0xAB // выход их спящего режима
- #define _ACMD_ENARESET 0x66 // разрешение сброса чипа
- #define _ACMD_DORESET 0x99 // команда сброса чипа (Требуется предварительная 0x66)
- // команды чтения/записи "статусных" регистров
- #define _ACMD_STATREAD_1 0x05 // чтение статусного регистра 1
- #define _ACMD_STATREAD_2 0x35 // чтение статусного регистра 2
- #define _ACMD_STATREAD_3 0x15 // чтение статусного регистра 3
- #define _ACMD_STATWRIT_1 0x01 // запись статусного регистра 1
- #define _ACMD_STATWRIT_2 0x31 // запись статусного регистра 2
- #define _ACMD_STATWRIT_3 0x11 // запись статусного регистра 3
- // команды идентификации
- #define _ACMD_MFIDREAD 0x9F // чтение информации о производителе и ID микросхемы
- #define _ACMD_SFDPREAD 0x5A // чтение регистра Serial Flash Discoverable Parameter (Информация о производителе и устройстве)
- #define _ACMD_UIDRREAD 0x4B // чтение регистра Unique ID
- // команды защиты
- #define _SCMD_WRENABLE 0x06 // разрешение записи
- #define _SCMD_WRDISABLE 0x04 // разрешение записи
- #define _SCMD_WRENVOL 0x50 // разрешение записи (только для статусных регистров, без сохранения)
- #define _SCMD_SECRGERS 0x44 // стирание регистра защиты
- #define _SCMD_SECRGWRT 0x42 // запись регистра защиты
- #define _SCMD_SECRGRD 0x48 // чтение регистра защиты
- #define _SCMD_GLBLLK 0x7E // глобальная блокировка блоков
- #define _SCMD_GLBLUNLK 0x98 // глобальная разблокировка блоков
- #define _SCMD_BLKLKRD 0x3D // чтение регистра индивидуальной блокировки сектора/блока
- #define _SCMD_BLKLOCK 0x36 // индивидуальная блокировка сектора/блока
- #define _SCMD_BLKULOCK 0x39 // индивидуальная разблокировка сектора/блока
- #define _SCMD_ERPGSUSP 0x75 // заморозить процесс стирания/записи
- #define _SCMD_ERPGRESM 0x7A // разморозить процесс стирания/записи
- #endif
- #if defined(W25Q16JV_APILEVEL) || defined(W25Q16JV_LOWLEVEL)
- // ##__##__##__##__##__##__##__##__##__##__##__##__##__##__##__##
- // ## ##
- // ## максимальные времена ##
- // ## ##
- // ##__##__##__##__##__##__##__##__##__##__##__##__##__##__##__##
- //
- // из колонки MAX таблицы временных характеристик чипа
- #define _TIME_CSSET_us 1 // время на установление CS в 1
- #define _TIME_CSCLR_us 1 // время на установление CS в 0
- #define _TIME_CSHLD_us 1 // минимальное время CS в неактивном состоянии м/у командами
- #define _TIME_EDPDM_us 3 // вход в спящий режим
- #define _TIME_RDPDM_us 4 // выход из спящего режима
- #define _TIME_RSTRC_us 30 // время восстановления после сброса
- #define _TIME_RSTWD_us 10 // время удержания сигнала сброса
- #define _TIME_STRUP_us 20 // время готовности после подачи питания (но чип все еще не готов записывать данные)
- #define _TIME_PGPRG_ms 3 // программирование страницы
- #define _TIME_STPRG_ms 15 // программирование статусного регистра
- #define _TIME_START_ms 7 // ожидание запуска чипа до полной готовности
- #define _TIME_COOLDOWN_ms 20 // ожидание "остывания" чипа после выключения питания
- #define _TIME_PGERS_ms 400 // стирание страницы (=блока 4KB)
- #define _TIME_BKERS_ms 400 // стирание блока (=страницы 4KB)
- #define _TIME_SCERS_ms 2000 // стирание сектора (64KB)
- #define _TIME_FLASHAPI_TIMEOUT 10 // стандартный таймаут ожидания API-функций
- #endif
- #if defined(W25Q16JV_LOWLEVEL) || defined(W25Q16JV_APILEVEL)
- // ##__##__##__##__##__##__##__##__##__##__##__##__##__##__##__##
- // ## ##
- // ## ДРУГИЕ ОПРЕДЕЛЕНИЯ ##
- // ## ##
- // ##__##__##__##__##__##__##__##__##__##__##__##__##__##__##__##
- /* <CONFIG> */
- #include "drivers\flash\w25q\config\W25Q16JV_CONF.h"
- /* </CONFIG> */
- // чтение идентификатора
- #define __FLASH_WINBOND_ID 0xEF // индентификатор фирмы WINBOND в поле Manufacturer ID
- #define __FLASH_INVALID_ID 0xFF // неверно прочитанный идентификатор Manufacturer ID
- #define __FLASH_DENSITY_16MB 0x15 // идентификатор объема накопителя 16МБит
- #define __FLASH_MEMORYID_Q 0x40 // идентификатор типа чипа W25Q16JV-IQ/JQ
- #define __FLASH_MEMORYID_M 0x70 // идентификатор типа чипа W25Q16JV-IM*/JM*
- #endif
- #if defined(W25Q16JV_APILEVEL) || defined(W25Q16JV_LOWLEVEL)
- // регистр защиты - байты защиты
- #define __FLASH_PROTECTION_REG_ENABLE 0xFF // байт регистра защиты - сектор защищен
- #define __FLASH_PROTECTION_REG_DISABLE 0x00 // байт регистра защиты - сектор НЕ защищен
- #endif
- #ifdef W25Q16JV_LOWLEVEL
- // оперативная память
- #define __FLASH_LL_COMMAND_MAXSIZE 8 // максимальное количество байт, выделяемое для буфера команд
- // максимальное количество байт, выделяемое для буфера команд + буфера страницы
- #define __FLASH_LL_SVCMEM_SIZE ( __FLASH_LL_COMMAND_MAXSIZE + __SECTORS_FULL ) // alloc_place содержит protectbuffer[] байт
- #endif
- #if defined(W25Q16JV_APILEVEL) || defined(W25Q16JV_LOWLEVEL)
- // регистр безопасности
- #define __FLASH_USER_SECURITY_BYTES 256 // количество байт, доступных для программирования в регистре безопасности
- #endif
- // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
- // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№ структуры и типы №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
- // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
- //
- #if defined(W25Q16JV_LOWLEVEL) || defined(W25Q16JV_APILEVEL)
- //-------------------------------------------
- #pragma pack( push, 1 )
- // РЕГИСТРЫ СТАТУСА
- union __flash_status_register_st_1 { // [W25Q OK]
- struct
- {
- __FLASH_BYTE bBusy : 1; // BUSY бит занятости BUSY: занят(1)/свободен(0), WIP (Write In Progress)
- __FLASH_BYTE bWrEnLatch: 1; // WEL индикатор возможности записи после Write Enable Instruction: (1) разрешена / (0) запрещена
- __FLASH_BYTE cBlkProt : 3; // BP индикаторы и установки групповой защиты блоков
- __FLASH_BYTE bTopBot : 1; // TB бит переключения групповой защиты с начала (bTopBot=0) или конца (bTopBot=1) памяти
- __FLASH_BYTE bSectBlk : 1; // SEC бит переключения групповой защиты на блоки 4КБ (bSectBlk=1) или 64КБ секторы (bSectBlk=0) [sic!]
- __FLASH_BYTE bStatProt : 1; // SRP бит аппаратной защиты статусного регистра: (1) - запись возможна если аппаратный сигнал ~WP=0 (asserted), (0) - без защиты
- };
- __FLASH_BYTE status;
- };
- union __flash_status_register_st_2 { // [W25Q OK]
- struct
- {
- __FLASH_BYTE bStatLock : 1; // SRL блокировка стаусного регистра: (1) - заблокировать до следующего цикла подачи питания, (0) - нет блокировки
- __FLASH_BYTE bQuadEn : 1; // разрешение режима Quad SPI (обмен по 4 линиям IO). (1) - разрешен, (0) - запрещен
- __FLASH_BYTE bRes1 : 1; // зарезервировано, RO, =0
- __FLASH_BYTE bLockSec1 : 1; // LB1 бит защиты Security Register 1: блокировка записи SR1, OTP, не снимается!
- __FLASH_BYTE bLockSec2 : 1; // LB2 бит защиты Security Register 2: блокировка записи SR2, OTP, не снимается!
- __FLASH_BYTE bLockSec3 : 1; // LB3 бит защиты Security Register 3: блокировка записи SR3, OTP, не снимается!
- __FLASH_BYTE bCmpProt : 1; // CMP бит комплиментарности групповой защиты: позволяет проинвертировать признаки групповой защиты блоков, CMP=0 - нет инверсии
- __FLASH_BYTE bSuspended: 1; // SYS индикатор Suspend State, SYS=1 если одна из команд записи/стирания находится на паузе
- };
- __FLASH_BYTE status;
- };
- union __flash_status_register_st_3 { // [W25Q OK]
- struct
- {
- __FLASH_BYTE cRes_0 : 2; // зарезервировано, RO, =0
- __FLASH_BYTE bWPSel : 1; // WPS выбор схемы защиты от записи, WPS=0 групповая защита {CMP, SEC, TB, BP[2:0]}, WPS=1 индивидуальная защита секторов/блоков
- __FLASH_BYTE cRes_1 : 2; // зарезервировано, RO, =0
- __FLASH_BYTE cDrvStr : 2; // DRV настройка тока выходного драйвера: 00 = 100%, 11 = 25% (по умолчанию)
- __FLASH_BYTE bRes : 1; // зарезервировано, RO, =0
- };
- __FLASH_BYTE status;
- };
- #define __FLASH_WPS_GROUP_PROTECT 0 // bWPSel=0, групповая защита секторов
- #define __FLASH_WPS_INDIVIDUAL_PROTECT 1 // bWPSel=1, индивидуальная защита секторов
- #define __FLASH_DRS_DEFAULT 3 // cDrvStr=11, Driver Strength = 25%
- #define __FLASH_SRP_WP_ENABLE 1 // bStatProt=1, разрешение аппаратного ~WP
- #define __FLASH_SRP_WP_DISABLE 0 // bStatProt=0, запрещение аппаратного ~WP
- #if W25QXXX_HW_WR_PROTECT
- #define __FLASH_SRP_WP_DEFAULT __FLASH_SRP_WP_ENABLE
- #else
- #define __FLASH_SRP_WP_DEFAULT __FLASH_SRP_WP_DISABLE
- #endif
- #define __FLASH_SRL_LOCKED 1 // bStatLock=1, запись в статусные регистры запрещена по следующего цикла включения питания
- #define __FLASH_SRL_UNLOCKED 0 // bStatLock=0, запись в статусные регистры разрешена
- #define __FLASH_QUAD_ENABLED 1 // bQuadEn=1, разрешен режим Quad SPI
- #define __FLASH_QUAD_DISABLED 0 // bQuadEn=0, запрещен режим Quad SPI
- #define __FLASH_SYS_ENABLED 1 // bSuspended=1, задействован режим suspend
- #define __FLASH_BP_RESET 0 // cBlkProt=0, все индикаторы групповой защиты сброшены
- #define __FLASH_BP_SET 7 // cBlkProt=7, все индикаторы групповой защиты установлены
- #define __FLASH_CMP_ENABLE 1 // bCmpProt=1, режим комплиментарной защиты включен
- #define __FLASH_CMP_DISABLE 0 // bCmpProt=0, режим комплиментарной защиты выключен
- #pragma pack( pop )
- typedef union __flash_status_register_st_1 __flash_status1_t;
- typedef union __flash_status_register_st_2 __flash_status2_t;
- typedef union __flash_status_register_st_3 __flash_status3_t;
- //-------------------------------------------
- #pragma pack( push, 1 )
- // ИНДЕТИФИКАТОР ПРОИЗВОДИТЕЛЯ
- struct __flash_deviceid_st // [W25Q OK]
- {
- __FLASH_BYTE Family; // семейство памяти, в зависимости от модели
- __FLASH_BYTE Density : 6; // вместимость чипа, для линейки W25Q: значение [10h ... 20h]
- __FLASH_BYTE Reserved: 2; //
- };
- typedef struct __flash_deviceid_st flash_deviceid_t;
- struct __flash_manufacturerid_st // [W25Q OK]
- {
- union {
- struct {
- __FLASH_BYTE LowId; // стандартный байт ID (не расширенный)
- __FLASH_BYTE Reserved; // зарезервировано, всегда 0.
- // Поле использовалось под расширенный байт ID, Continuation Code, JEDEC JEP-106,
- // но семейство W25Q не поддерживает подобный формат.
- };
- __FLASH_WORD FullId; // полный ID
- };
- __FLASH_WORD DevId; // код устройства [flash_deviceid_t]
- // W25Q не поддерживает расширение поля ID в соответствии с JEDEC JEP-106,
- // однако поддерживает другой стандарт Serial Flash Discoverable Parameter Structure (JESD216D.01)
- // Поля ExtLen и pExtBf будут использованы для выдачи информации о чипе в этом формате
- __FLASH_BYTE ExtLen; // длинна расширенной информации
- __FLASH_BYTE * pExtBf; // указатель на буфер приемник расширенной информации
- };
- struct __flash_manufacturerid_ex_st // [W25Q OK]
- {
- union {
- struct {
- __FLASH_BYTE LowId; // стандартный байт ID (не расширенный)
- __FLASH_BYTE Reserved; // зарезервировано, всегда 0.
- // Поле использовалось под расширенный байт ID, Continuation Code, JEDEC JEP-106,
- // но семейство W25Q не поддерживает подобный формат.
- };
- __FLASH_WORD FullId; // полный ID
- };
- flash_deviceid_t DevId; // код устройства
- // W25Q не поддерживает расширение поля ID в соответствии с JEDEC JEP-106,
- // однако поддерживает другой стандарт Serial Flash Discoverable Parameter Structure (JESD216D.01)
- // Поля ExtLen и pExtBf будут использованы для выдачи информации о чипе в этом формате
- __FLASH_BYTE ExtLen; // длинна расширенной информации
- __FLASH_BYTE * pExtBf; // указатель на буфер приемник расширенной информации
- };
- struct __flash_manufacturerid_returnvalue_st // [W25Q OK]
- {
- union {
- struct {
- __FLASH_BYTE LowId; // стандартный байт ID (не расширенный)
- __FLASH_BYTE HighId; // зарезервировано, всегда 0.
- };
- __FLASH_WORD FullId; // полный ID
- };
- flash_deviceid_t DevId; // код устройства
- };
- typedef struct __flash_manufacturerid_returnvalue_st __flash_rvid_t;
- typedef struct __flash_manufacturerid_st __flash_id_t;
- typedef struct __flash_manufacturerid_ex_st __flash_exid_t;
- #pragma pack( pop )
-
- #pragma pack( push, 1 )
- // РЕГИСТРЫ ЗАЩИТЫ/БЛОКИРОВКИ СЕКТОРОВ/БЛОКОВ
- struct __flash_protect_register_st // [W25Q OK]
- {
- // байты защиты секторов 0-62 (__FLASH_PROTECTION_REG_ENABLE / __FLASH_PROTECTION_REG_DISABLE )
- __FLASH_BYTE bSectors[ BITBUFFER_SIZE(__PROT_SECTOR_FLAGS) ];
- };
- typedef struct __flash_protect_register_st __flash_protectionregister_t;
- struct __flash_protect_sector_register_st // [W25Q OK]
- {
- // байты защиты секторов 0-31 (__FLASH_PROTECTION_REG_ENABLE / __FLASH_PROTECTION_REG_DISABLE )
- // Группировка по секторам 64К !
- __FLASH_BYTE bSectors[ BITBUFFER_SIZE(__SECTORS) ];
- };
- typedef struct __flash_protect_sector_register_st __flash_sectorprotectionregister_t;
- #pragma pack( pop )
- #define FLASH_PROTECTION_REGISTER_CHECK(bSectors,n) BITBUFFER_CHECK(bSectors,n)
- #define FLASH_PROTECTION_REGISTER_SET( bSectors,n) BITBUFFER_SET( bSectors,n)
- #define FLASH_PROTECTION_REGISTER_CLEAR(bSectors,n) BITBUFFER_CLEAR(bSectors,n)
- //-------------------------------------------
- // РЕГИСТРЫ БЕЗОПАСНОСТИ ПОЛЬЗОВАТЕЛЯ
- #pragma pack( push, 1 )
- struct __flash_security_register_st // [W25Q OK]
- {
- __FLASH_BYTE content[ __FLASH_USER_SECURITY_BYTES ]; // доступные для однократного программирования байты в регистре безопасности
- };
- typedef struct __flash_security_register_st __flash_securityregister_t;
- #pragma pack( pop )
- //-------------------------------------------
- // РЕГИСТРЫ ИДЕНТИФИКАТОРОВ
- #pragma pack( push, 1 )
- struct __flash_uniqueid_register_st // [W25Q OK]
- {
- __FLASH_BYTE uid[8]; // 8-байтовый уникальный идентификатор в пределах модели
- };
- typedef struct __flash_uniqueid_register_st __flash_uniqueidregister_t;
- #pragma pack( pop )
- //-------------------------------------------
- // ВНУТРЕННИЕ СЛУЖЕБНЫЕ СТРУКТУРЫ И ТИПЫ
- typedef const __FLASH_BYTE (*__flash_pageprogramptr_t)[ __PROG_PAGE_SIZE ];
- typedef enum
- {
- fibufSectorFlags, // буфер флагов защиты секторов 64К
- fibufSectorFlags_2, // буфер флагов защиты секторов 64К (еще один буфер)
- fibufProtSectorFlags, // буфер флагов защиты секторов/блоков (protSector)
- fibufPageIO, // буфер ввода/вывода страницы
- }
- __flash_internal_buffer_type_t;
- // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
- // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№ преобразования адресов №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
- // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
- //
- #if defined(W25Q16JV_LOWLEVEL) || defined(W25Q16JV_APILEVEL)
- #define __FLASH_ADDRESS2SECTOR(addr) ((addr)/__SECTOR_STD_SIZE) // __FLASH_ADDRESS2SECTOR - преобразует адрес в номер сектора с учетом используемого размера страницы
- #define __FLASH_ADDRESS2PAGE(addr) ((addr)/__PAGE_SIZE_USER) // __FLASH_ADDRESS2PAGE - преобразует адрес в номер страницы с учетом используемого размера страницы
- #define __FLASH_PAGE2ADDRESS(page) ((page)*__PAGE_SIZE_USER) // __FLASH_PAGE2ADDRESS - преобразует номер страницы в адрес с учетом используемого размера страницы
- #define __FLASH_PAGE2BLOCK(page) ((page)/__PAGES_PER_BLOCK) // __FLASH_PAGE2BLOCK - преобразует номер страницы в номер блока
- #define __FLASH_PAGE2SECTOR(page) ((page)/__PAGES_PER_SECTOR) // __FLASH_PAGE2SECTOR - преобразует номер страницы в номер сектора
- #define __FLASH_ADDRESSOFFSETPAGE(addr) ((addr)%__PAGE_SIZE_USER) // __FLASH_ADDRESSOFFSETPAGE - получает смещение адреса относительно начала страницы
- // __FLASH_DATAREMAININGINPAGE - вычисляет, какое количество байт осталось до конца страницы
- #define __FLASH_DATAREMAININGINPAGE(addr) ( __PAGE_SIZE_USER - __FLASH_ADDRESSOFFSETPAGE( address ) )
- // В линейке чипов Winbind серии W25Q существуют чипы емкостью от 1МБит до 512МБит
- // Код емкости: 10h - 512KBit, 11h - 1Mbit, 12h - 2Mbit, ..., 19h - 256MBit, и 20h - 512MBit
- // Чип емкостью 512МБит выбивается из общего правила, т.к. имеет код не 1Ah, а 20h.
- // __W25Q_density
- // Возвращает емкость в Мегабитах
- static inline int __W25Q_density(int density)
- {
- if( 0x11 <= density && density <= 0x19 )
- return (1 << ((density & 0xF) - 1));
- switch( density )
- {
- case 0x10: return 0; // 512KBit
- case 0x20: return 512; // 512MBit
- }
- return 0; // undefined
- }
- #define __FLASH_DENSITY2CAPACITY(density) __W25Q_density(density)
- // __FLASH_PAGESINRANGE - вычисляет, какое количество страниц находится на промежутке длинной size начиная с адреса address
- #define __FLASH_PAGESINRANGE(address,size) \
- ((address+size)/__PAGE_SIZE_USER - \
- (address)/__PAGE_SIZE_USER + \
- (((address+size)%__PAGE_SIZE_USER)?1:0)) //
- // __FLASH_PAGE_ARRAGED_BY_BLOCK - проверяет, выровнена ли страница на размер блока
- #define __FLASH_PAGE_ARRAGED_BY_BLOCK(pg) (!( pg % W25QFLASH_PAGES_PER_BLOCK ))
- // __FLASH_PAGE_ARRAGED_BY_SECTOR - проверяет, выровнена ли страница на размер сектора
- #define __FLASH_PAGE_ARRAGED_BY_SECTOR(pg) (!( pg % W25QFLASH_PAGES_PER_SECTOR ))
- #endif
- // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
- // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№ экпортируемые макросы №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
- // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
- //
- // для экспорта функций используйте заголовочный файл "W25Q16JV_LL_func.h"
- #define W25QFLASH_WINBOND_ID __FLASH_WINBOND_ID // Winbond' Manufacturer ID
- #define W25QFLASH_DENSITY_16MB __FLASH_DENSITY_16MB // Winbond' Density for 16Mbit
- #define W25QFLASH_FAMILYDATAFLASHQ __FLASH_MEMORYID_Q // Winbond' Family code
- #define W25QFLASH_FAMILYDATAFLASHM __FLASH_MEMORYID_M // Winbond' Family code
- #define W25QFLASH_CHIP_SIZE __FULL_CHIP_SIZE // полный объем чипа
- #define W25QFLASH_DATA_SIZE __FULL_DATA_SIZE // полный объем данных (с учетом или без учета сервисных байтов)
- #define W25QFLASH_SECTORS __SECTORS // количество секторов
- #define W25QFLASH_PAGE_SIZE __PAGE_SIZE_USER // размер страницы (зависит от использования сервисных секторов)
- #define W25QFLASH_BLOCKS __BLOCKS // количество блоков
- #define W25QFLASH_BLOCK_SIZE __BLOCK_SIZE_USER // размер блока (зависит от использования сервисных секторов)
- #define W25QFLASH_PAGES __FULL_PAGES // количество страниц
- #define W25QFLASH_BLOCKS_PER_SECTOR __BLOCKS_PER_SECTOR // количество блоков в секторе
- #define W25QFLASH_PAGES_PER_SECTOR __PAGES_PER_SECTOR // количество страниц в стандартном секторе
- #define W25QFLASH_PAGES_PER_BLOCK __PAGES_PER_BLOCK
- //-------------------------------------------
- // размеры секторов
- #define W25QFLASH_SECTOR0_SIZE __SECTOR0_SIZE
- #define W25QFLASH_SECTOR1_SIZE __SECTOR1_SIZE
- #define W25QFLASH_SECTOR2_SIZE __SECTOR2_SIZE
- #define W25QFLASH_SECTOR3_SIZE __SECTOR3_SIZE
- #define W25QFLASH_SECTOR4_SIZE __SECTOR4_SIZE
- #define W25QFLASH_SECTOR5_SIZE __SECTOR5_SIZE
- #define W25QFLASH_SECTOR6_SIZE __SECTOR6_SIZE
- #define W25QFLASH_SECTOR7_SIZE __SECTOR7_SIZE
- #define W25QFLASH_SECTOR8_SIZE __SECTOR8_SIZE
- #define W25QFLASH_SECTOR9_SIZE __SECTOR9_SIZE
- #define W25QFLASH_SECTOR10_SIZE __SECTOR10_SIZE
- #define W25QFLASH_SECTOR11_SIZE __SECTOR11_SIZE
- #define W25QFLASH_SECTOR12_SIZE __SECTOR12_SIZE
- #define W25QFLASH_SECTOR13_SIZE __SECTOR13_SIZE
- #define W25QFLASH_SECTOR14_SIZE __SECTOR14_SIZE
- #define W25QFLASH_SECTOR15_SIZE __SECTOR15_SIZE
- #define W25QFLASH_SECTOR16_SIZE __SECTOR16_SIZE
- #define W25QFLASH_SECTOR17_SIZE __SECTOR17_SIZE
- #define W25QFLASH_SECTOR18_SIZE __SECTOR18_SIZE
- #define W25QFLASH_SECTOR19_SIZE __SECTOR19_SIZE
- #define W25QFLASH_SECTOR20_SIZE __SECTOR20_SIZE
- #define W25QFLASH_SECTOR21_SIZE __SECTOR21_SIZE
- #define W25QFLASH_SECTOR22_SIZE __SECTOR22_SIZE
- #define W25QFLASH_SECTOR23_SIZE __SECTOR23_SIZE
- #define W25QFLASH_SECTOR24_SIZE __SECTOR24_SIZE
- #define W25QFLASH_SECTOR25_SIZE __SECTOR25_SIZE
- #define W25QFLASH_SECTOR26_SIZE __SECTOR26_SIZE
- #define W25QFLASH_SECTOR27_SIZE __SECTOR27_SIZE
- #define W25QFLASH_SECTOR28_SIZE __SECTOR28_SIZE
- #define W25QFLASH_SECTOR29_SIZE __SECTOR29_SIZE
- #define W25QFLASH_SECTOR30_SIZE __SECTOR30_SIZE
- #define W25QFLASH_SECTOR31_SIZE __SECTOR31_SIZE
- // количество циклов перезаписи регистра статуса
- #define W25QFLASH_STATREG_WRITECOUNT __FLASH_STATUSREGISTER_WRITECYCLES
- // количество циклов перезаписи страницы 4К
- #define W25QFLASH_PAGE_WRITECOUNT __FLASH_PAGE_WRITECYCLES
- // зарезервированная область в начале адресного пространства
- #define W25QFLASH_MINIMUM_ADDRESS (0x20000) // указано 128K для совместимости с AT45, но если не требуется => указать 0
- // максимально возможный адрес
- #define W25QFLASH_MAXIMUM_ADDRESS (W25QFLASH_PAGES * __PAGE_SIZE_USER )
- //-------------------------------------------
- #endif
- #endif
|