Инструменты пользователя

Инструменты сайта


prog:example_v6:otp_test_ve8

Различия

Здесь показаны различия между двумя версиями данной страницы.

Ссылка на это сравнение

Предыдущая версия справа и слева Предыдущая версия
Следующая версия
Предыдущая версия
prog:example_v6:otp_test_ve8 [2019/10/10 17:15]
vasco [Алгоритм программирования]
prog:example_v6:otp_test_ve8 [2019/10/15 13:55] (текущий)
vasco [Запуск проекта - Прошивка]
Строка 4: Строка 4:
 Красивые картинки про память и многое полезное можно найти в данной статье - [[https://​semiengineering.com/​the-benefits-of-antifuse-otp/​|The Benefits Of Antifuse OTP]]. Красивые картинки про память и многое полезное можно найти в данной статье - [[https://​semiengineering.com/​the-benefits-of-antifuse-otp/​|The Benefits Of Antifuse OTP]].
  
-В обоих случаях изначально биты имеют значения 0, а прожигаются только те биты, которые должны стать "​1"​. Согласно приведенной статье,​ прожит бита памяти Fuse можно сделать только один раз. Если после единичного прожига бит не стал читаться как "​1",​ то память бракуется. В отличие от Fuse, бит памяти типа AntiFuse можно прожигать несколько ​раз, в статье про порядка 18 раз. При прожиге происходит пробой подзатворного диэлектрика,​ если пробой будет небольшой то его можно "​прожигать"​ повторно,​ чтобы образовался надежный контакт. Если контакт оставить плохой,​ то память не сможет работать на заявленных скоростях.+В обоих случаях изначально биты имеют значения 0, а прожигаются только те биты, которые должны стать "​1"​. Согласно приведенной статье,​ прожиг бита памяти Fuse можно сделать только один раз. Если после единичного прожига бит не стал читаться как "​1",​ то память бракуется. В отличие от Fuse, бит памяти типа AntiFuse можно прожигать несколько раз. При прожиге происходит пробой подзатворного диэлектрика,​ если пробой будет небольшой то его можно и нужно "​прожигать"​ повторно,​ чтобы образовался надежный контакт. Если контакт оставить плохой,​ то память не сможет работать на заявленных скоростях.
  
-=====Программирование,​ допрограммирование,​ верификаци===== +=====Программирование,​ допрограммирование,​ верификация===== 
-Все вышесказанное объясняет алгоритм программирования памяти ОТР в микроконтроллере 1986ВЕ8Т. Согласно спецификации,​ сначала необходимо провести первичный прожиг бит равных "​1"​ - **"​фаза программирования"​**. После этого запускается **"​фаза допрограммирования"​**,​ когда считываются текущие значения в ячейках и если где-то "​1"​ не прописалась,​ то запускается процедура программирования для данного бита. После окончания допрограммирования необходимо проверить,​ на сколько качественно прожглись каналы в подзатворном диэлектрике. Для этого запускается этап **"​верификации"​**,​ который на максимально заявленной для памяти частоте сверяет значения ячеек памяти. Если каналы будут слабые,​ то при высокой скорости обращения будут возникать сбои, память будет читаться с ошибками,​ т.е. не будет совпадать со значениями которые в нее были записаны. Описанная сейчас процедура составляет один **цикл программирования** памяти. Гарантированный компанией "​Миландр"​ коэффициент программируемости составляет 0,7. Т.е. потенциально больше 30% операций записи может закончится неудачей. Но это гарантируемый коэффициент,​ на самом деле процент гораздо выше.+Все вышесказанное объясняет алгоритм программирования памяти ОТР в микроконтроллере 1986ВЕ8Т. Согласно спецификации,​ сначала необходимо провести первичный прожиг бит равных "​1"​ - **"​фаза программирования"​**. После этого запускается **"​фаза допрограммирования"​**,​ когда считываются текущие значения в ячейках и если где-то "​1"​ не прописалась,​ то запускается процедура программирования для данного бита. После окончания допрограммирования необходимо проверить,​ на сколько качественно прожглись каналы в подзатворном диэлектрике. Для этого запускается этап **"​верификации"​**,​ который на максимально заявленной для памяти частоте сверяет значения ячеек памяти. Если каналы будут слабые,​ то при высокой скорости обращения будут возникать сбои, память будет читаться с ошибками,​ т.е. не будет совпадать со значениями которые в нее были записаны. Описанная сейчас процедура составляет один **цикл программирования** памяти. Гарантированный компанией "​Миландр"​ коэффициент программируемости составляет 0,7. Т.е. при программировании 100 микросхем успешно пропишутся из них только 70, а 30 микросхем запрограммировать не удастся, будут ошибки. Но это гарантируемый коэффициент,​ на самом деле процент гораздо выше. Каждый производитель оставляет себе некоторый запас.
  
 В случае,​ если в первом цикле программирования верификация выявила наличие ошибок,​ то есть возможность запустить **повторный цикл**. Но во вторичном цикле необходимо исключить операцию программирования. Это связано с тем, что вторичный прожиг уже пробитого бита не желателен. Поэтому второй цикл программирования должен состоять только из этапов **допрограммирования** и **верификации**. Производитель не рекомендует использовать более двух циклов программирования,​ предлагая в случае неудачи второго цикла браковать микроконтроллер. В случае,​ если в первом цикле программирования верификация выявила наличие ошибок,​ то есть возможность запустить **повторный цикл**. Но во вторичном цикле необходимо исключить операцию программирования. Это связано с тем, что вторичный прожиг уже пробитого бита не желателен. Поэтому второй цикл программирования должен состоять только из этапов **допрограммирования** и **верификации**. Производитель не рекомендует использовать более двух циклов программирования,​ предлагая в случае неудачи второго цикла браковать микроконтроллер.
Строка 26: Строка 26:
 По схеме видно, что различия крайне незначительны и можно реализовать оба этапа одной функцией. При этом, //"​Различие 2"// решается передачей в функцию количества повторов программирования бита, 1 цикл для программирования и 40 для допрограммирования. Остается //"​различие 1"// с присутствием чтения текущего значения при допрограммировании. Но будет ли хуже, если программирование тоже будет читать текущее значение ячейки и писать только если есть незаписанные 1-цы? По схеме видно, что различия крайне незначительны и можно реализовать оба этапа одной функцией. При этом, //"​Различие 2"// решается передачей в функцию количества повторов программирования бита, 1 цикл для программирования и 40 для допрограммирования. Остается //"​различие 1"// с присутствием чтения текущего значения при допрограммировании. Но будет ли хуже, если программирование тоже будет читать текущее значение ячейки и писать только если есть незаписанные 1-цы?
  
-Изначально предполагается что чип чист и вся память 0-вая, поэтому нет чтения в программировании. В допрограммировании же важно исключить вторичный прожиг уже пробитого бита, поэтому чтение необходимо. ​Поэтому, лишнее чтение ничем этапу программирования не навредит. Репликами чтение 0-ей выставлено максимально легким,​ т.е. нет шансов что "​0"​ друг прочтется "​1"​-ей и на этапе чтения ​будет пропущено программирование какого-либо бита из-за того что было предварительное чтение. Кроме этого, если по ошибке произойдет запуск программирования для уже записанной памяти,​ то это исключит повторную запись уже пробитого бита.+Изначально предполагается что чип чист и вся память 0-вая, поэтому нет чтения в программировании. В допрограммировании же важно исключить вторичный прожиг уже пробитого бита, поэтому чтение необходимо. ​Судя по всему, лишнее чтение ничем этапу программирования не навредит. Репликами чтение 0-ей выставлено максимально легким,​ т.е. нет шансов что "​0"​ друг прочтется "​1"​-ей и будет пропущено программирование какого-либо бита из-за того что добавилось предварительное чтение. Кроме этого, если по ошибке произойдет запуск программирования для уже записанной памяти,​ то это исключит повторную запись уже пробитого бита.
  
 В целом я не вижу никакого резона делать две отдельные функции для этапов программирования и допрограммирования. Достаточно реализовать их в одной функции,​ на вход задав лишь количество допустимых повторов. В библиотеке Pack_V6 это сделано так: В целом я не вижу никакого резона делать две отдельные функции для этапов программирования и допрограммирования. Достаточно реализовать их в одной функции,​ на вход задав лишь количество допустимых повторов. В библиотеке Pack_V6 это сделано так:
Строка 44: Строка 44:
 </​code>​ </​code>​
  
-Листинг самой функции я приводить не буду, исходники доступны на GitHub.+Листинг самой функции я приводить не буду, исходники доступны на GitHub, драйвер MDR_OTP - [[https://​github.com/​StartMilandr/​MDR_Pack_v6/​blob/​master/​PACK_Gen/​Files/​SPL/​Drivers/​MDR_OTP_VE8x.h|MDR_OTP_VE8x.h]] и [[https://​github.com/​StartMilandr/​MDR_Pack_v6/​blob/​master/​PACK_Gen/​Files/​SPL/​Drivers/​MDR_OTP_VE8x.c|MDR_OTP_VE8x.c]] . 
 + 
 +С помощью драйвера MDR_OTP запись памяти выглядит так, отрывок из проекта описанного ниже: 
 +<​code>​ 
 +void OPT_WriteTestData(void) 
 +
 +  MDR_OTP_Enable(); ​                           // - Выключение доступа к контроллеру OTP, KEY 
 +  MDR_OTP_ProgBegin_ByClockCPU_Hz(freqCPU_Hz);​ // - Расчет задержек,​ выставление минимального DUcc, 
 +                                               // ​  ​задержка HV_PE, выставление реплик в TUNING 
 +  MDR_OTP_ProgWord(OTP_TEST_PROG_ADDR,​ OTP_TEST_PROG_DATA); ​  // Программирование слова 
 +  ... 
 +  ...   
 +  ... 
 + 
 +  MDR_OTP_ProgEnd(); ​                          // - реплики и DUcc в состояние по умолчанию 
 +  MDR_OTP_Disable(); ​                          // - выключение доступа к контроллеру OTP, KEY 
 +
 +</​code>​ 
 + 
 +Внешнее напряжение программирования 7,2 В должно быть задано до исполнения данного кода! Повышенное напряжение необходимо чтобы пробить диэлектрик,​ для этих же целей в функции MDR_OTP_ProgBegin() понижается питание самой микросхемы через подстройку внутренних LDO. После модификации LDO выдерживается необходимая задержка между подачей питания HV и входом в режим программирования - бит PE. 
 +=====Пример OTP_Test_VE8===== 
 +Данный пример был реализован чтобы проверить работоспособность драйвера MDR_OTP. В примере используются все три кнопки на отладочной плате:​ 
 +  * Key1 - Записать слово OTP_TEST_PROG_DATA в память по адресу OTP_TEST_PROG_ADDR 
 +  * Key2 - Считать слово из адреса OTP_TEST_PROG_ADDR и сравнить со значением OTP_TEST_PROG_DATA  
 +  * Key3 - Запустить/​остановить вывод задержек на светодиод LED3. 
 + 
 + ​Для индикации используется два светодиода:​ 
 +  * LED1 (Cyclic) - мигает с произвольным периодом показывая что МК работает. 
 +  * LED2 (OK) - загорается по Key2, если слово в памяти совпало с ожидаемыми данными. 
 +  * LED3 (Fault)- загорается по Key2, если чтение слова из памяти НЕ совпало с ожидаемыми данными. 
 + 
 +====Тестовые адрес и данные==== 
 +Слова в проекте пишутся начиная с конца памяти ОТР, чтобы оставить начальные адреса для рабочей программы. Пишется всего одно слово, на нем проверяется как отрабатывает запись и чтение. Для записи следующего слова необходимо исправить в коде значение OTP_TEST_TEST_IND,​ потому что он задает адрес:​ 
 + 
 +<​code>​ 
 +//  Увеличивать после каждой записи - сдвиг на чистую память с конца ОТР. 
 +//  Минимальное значение = 1 
 +#define OTP_TEST_TEST_IND ​         5 
 + 
 +#define OTP_TEST_ADDR_END ​         0x01020000 
 +#define OTP_TEST_PROG_ADDR ​        ​(OTP_TEST_ADDR_END - (OTP_TEST_TEST_IND * 4)) 
 +</​code>​ 
 + 
 +В тесте был опробован прожиг от трех источников тактирования,​ данные записываемые при каждом прожиге тоже менялись:​ 
 + 
 +<​code>​ 
 +//  Значения записываемые/​записанные в память в порядке OTP_TEST_TEST_IND 
 +//  1: OTP_TEST_TEST_IND = 1 от HSE0_PLL_Max 
 +//  #define OTP_TEST_PROG_DATA ​        ​0x13768421 
 +//  2: OTP_TEST_TEST_IND = 2 от HSE0_PLL_Max 
 +//  #define OTP_TEST_PROG_DATA ​        ​0x87245687 ​   
 +//  3: OTP_TEST_TEST_IND = 3 от HSI_Trim (задержки точные) 
 +//  #define OTP_TEST_PROG_DATA ​        ​0xABCDEFED 
 +//  4: OTP_TEST_TEST_IND = 4 от HSI без Trim (задержки не точные) 
 +//  #define OTP_TEST_PROG_DATA ​        ​0x12345678 
 +//  5: OTP_TEST_TEST_IND = 5 от HSE1 Gen 25MHz 
 +    #define OTP_TEST_PROG_DATA ​        ​0x9ABCDEF 
 +</​code>​ 
 + 
 +  * При тактировании HSE0_PLL_Max ядро тактируется от резонатора HSE0 10МГц на плате, с последующим умножением в PLL для получения максимально допустимой частоты тактирования от PLL  в 40МГц (см. Errata 0051 - большой джиттер PLL).  
 +  * При тактировании от HSI ядро работало на штатном неточном внутреннем генераторе HSI, прошивка проводилась при подстроенном значении HSI и том, какое возникает при штатном значении Trim. //(Trim - это значение подстройки частоты HSI, значение по умолчанию 32, диапазон значений от 0 до 63.)//  
 +  * Последним вариантом проверялась прошивка от внешнего генератора на 25 МГц, который заводился на HSE1. 
 + 
 +В сущности не важно, на какой частоте происходит прошивка,​ все варианты отработали с первого раза - с первого нажатия на кнопку Key1. **Важно правильно выдержать необходимые задержки в циклах программирования!** Рекомендуемая частота прошивки ~24МГц необходима лишь для проведения этапа верификации. Ведь читать память необходимо на ее максимальной рабочей частоте. В данном примере это возможно только в варианте тактирования от внешнего генератора. 
 + 
 +====Реализация задержек==== 
 +Необходимые задержки указаны в спецификации на стр. 215, таблица 36: 
 + 
 +^  Название ​ ^  Имя ​  ​^ ​ Мин значение ​ ^  Кол. тактов ​ ^^^^ 
 +^  :::  ^ :::  ^  мкс ​ ^  8 МГц ​ ^  25 МГц ^  40 МГц ^   64 МГц ​ ^ 
 +^ Режим записи - бит PE  ^^^^^^^ 
 +| Предустановка HV перед PE  | t_HV_PE |  10000 |  80000 |  250000 |  400000 |  640000 | 
 +| Предустановка PE перед DATA  | t_PE_D |  300 |  2400 |  7500 |  12000 |  19200 | 
 +| Предустановка ADR перед DATA  | t_A_D |  300 |  2400 |  7500 |  12000 |  19200 | 
 +| Удержание ADR после DATA  | t_D_A |  5 |  40 |  125  |  200 |  320 | 
 +| Время программирования ​ | t_Prog |  3000 |  24000 |  75000 |  120000 |  192000 | 
 +| Задержка между битами ​ | t_LD |  5 |  40 |  125 |  200 |  320 | 
 +| Удержание PE после DATA  | t_D_PE |  0 |  0 |  0 |  0 |  0 | 
 +^ Режим чтения - бит SE  ^^^^^^^ 
 +| Предустановка ADR перед SE  | t_A_SE |  0.005 |  0,04 |  0,125 |  0,2 |  0,32 | 
 +| Удержание ADR после SE  | t_SE_A |  0 |  0 |  0 |  0 |  0 | 
 +| Длительность HSE  | t_SE |  0.01 | 0,08 |  0,25 |  0,4 |  0,64 | 
 + 
 +По таблице видно, что для всех допустимых частот ядра достаточно лишь четырех задержек - на 10мс, 3мс, 300мкс и 5мкс. Остальные задержки составляют меньше чем один такт ядра, поэтому заботиться об их выдержке нет необходимости.  
 + 
 +Задержка 5мкс между записью нескольких бит подряд не пригодилась. Дело в том, что на блок схемах в спецификации описан режим программирования,​ в котором каждый бит записывается и тут же читается 5 раз, чтобы убедиться что он прошит. Если бит не прошит,​ то он снова прожигается,​ вплоть до 30 раз. На диаграмме же сигналов представлен режим, в котором биты записываются подряд,​ и затем видимо целиком происходит чтение. Или не происходит,​ потому что подобный режим нигде не описан,​ но реализован у Vasili с форума в его программе прошивки OTP по UART - [[http://​forum.milandr.ru/​viewtopic.php?​p=16804#​p16804|PRG_OTP_UART]]. 
 + 
 +Драйвер MDR_OTP был реализован согласно блок схем из спецификации и примера полученного от тех-поддержки. Диаграмма задержек при записи одного бита получается такая:​ 
 + 
 +{{mk8:​otp_bit_delays.png}} 
 + 
 +На диаграмме есть не упоминающиеся в спецификации задержки,​ это: 
 +  * t_Acc - время чтения памяти,​ которое по спецификации составляет 40нс. Обработка данной задержки в ПО не нужна. Потому что в коде после выставления SE идет инициализация цикла на 5 чтений памяти,​ что займет гораздо больше циклов,​ чем требуется на данную задержку. 
 +  * t_PE_SE - время между выходом из режима программирования PE и входом в режим чтения SE. В образцах кода от техподдержки и у Vasili эта задержка совпадает с задержкой t_A_D. Чтобы не получить не рабочий код, решено было оставить эту задержку такой же.  
 + 
 +Для расчета задержек в функцию MDR_OTP_ProgBegin_ByClockCPU_Hz() передается текущая частота процессора,​ которая определяется функцией MDR_CPU_GetFreqHz(). Важно лишь в MDR_ConfigVE8.h прописать правильные частоты для подключенных внешних HSE0 и HSE1.  
 + 
 +В качестве альтернативы,​ расчет задержек можно сделать отдельной функцией MDR_OTP_GetProgDelays() и получить из нее структуру с задержками,​ которая затем подается на вход MDR_OTP_ProgBegin(). Все тоже самое делает инлайн функция MDR_OTP_ProgBegin_ByClockCPU_Hz(),​ чтобы не писать это отдельно. 
 + 
 +<​code>​ 
 +  #define MDR_OTP_DELAY_US_HV_PE ​  ​10000 
 +  #define MDR_OTP_DELAY_US_A_D ​      300 
 +  #define MDR_OTP_DELAY_US_PROG ​    ​3000 
 + 
 +  typedef struct { 
 +    uint32_t delay_HV_PE;​ 
 +    uint32_t delay_A_D;​ 
 +    uint32_t delay_Prog;​ 
 +  } MDR_OTP_ProgDelays;​ 
 +   
 +  //  Вычисление задержек 
 +  MDR_OTP_ProgDelays ​  ​MDR_OTP_GetProgDelays(uint32_t freqCPU_Hz); ​  
 +   
 +  //  Инициализация программирования - снижение DUcc, выставление Tuning 
 +  void MDR_OTP_ProgBegin(const MDR_OTP_ProgDelays *progDelays);​ 
 + 
 +  //  Все описанное вместе 
 +  __STATIC_INLINE void MDR_OTP_ProgBegin_ByClockCPU_Hz(uint32_t freqCPU_Hz)  
 +  {  
 +    MDR_OTP_ProgDelays delays = MDR_OTP_GetProgDelays(freqCPU_Hz);​ 
 +    MDR_OTP_ProgBegin(&​delays);​  
 +  } 
 +</​code>​ 
 + 
 +Задержки рассчитываются под функцию MDR_Delay(),​ реализация который была описана ранее в данной статье - [[https://​startmilandr.ru/​doku.php/​prog:​pack_v6:​delayasm|"​Функция задержки и особенности её реализации в ассемблере"​]]. 
 + 
 +Значения в таблице определяют минимальные величины задержек,​ следовательно их важно не сделать короче. Самая важная задержка - это время программирования. Она единственная для которой определено максимальное значение. Это необходимо для того, чтобы ограничить время воздействия на ячейку повышенного напряжения. Иначе вероятно может случиться деградация структур в топологии,​ тогда могут пострадают и соседние ячейки. Другие же задержки лишь означают,​ что следующий по диаграмме сигнал необходимо выставить не раньше чем к этому будет готов контроллер памяти. 
 + 
 +Для того чтобы проверить,​ как отрабатываются задержки данной функцией в проекте используется кнопка KEY3. При нажатии на данную кнопку,​ на светодиоде LED3 начинают переключатся уровни напряжений с заданными задержками. Вот, например,​ какие возникают задержки при тактировании от HSI со значением Trim по умолчанию:​ 
 + 
 +{{mk8:​otp_delays_hsi.png}} 
 + 
 +Как видно, данные задержки превышают минимальные значения,​ т.е. по существу являются допустимыми. Время программирования t_Prog по спецификации составляет от 3 до 7мс. Что тоже не нарушается при таких задержках. Поэтому при одном из запусков проекта прошивались ячейки при тактировании от HSI без подстройки. Для полного соответствия проводилась прошивка и с подстроенным HSI, задержки тут имеют более точные значения:​ 
 + 
 +{{mk8:​otp_delays_hsi_trim.png}} 
 + 
 +После вторичного нажатия на кнопку KEY3 режим вывода задержек отключается. 
 +====Запуск проекта - предварительные проверки==== 
 +Для запуска проекта к демо-плате необходимо подключить источник питания на 7,2В, это середина из разрешенного диапазона 7,0-7,4В. В нашем случае это был источник,​ непосредственная подача питания от котором осуществляется по нажатию кнопки. Согласно порядку подачи напряжений,​ сначала необходимо запитать плату от рабочего источника,​ а уже затем, когда дело дойдет до прошивки памяти подать на плату напряжение программирования. Порядок снятия напряжений обратный,​ сначала необходимо отключить источник на 7,2В, потом выключить плату. 
 + 
 +Для подачи напряжения программирования на плате есть специальный разъем:​ 
 + 
 +{{mk8:​otp_write_board_min.jpg}} 
 + 
 +Прежде чем подать на плату повышенное напряжение,​ можно убедиться что функция MDR_OTP_ProgBegin_ByClockCPU_Hz() действительно понижает напряжение **DUcc**. Для этого необходимо закомментировать функцию программирования,​ а после MDR_OTP_ProgBegin_ByClockCPU_Hz() поставить breakpoint. Проект запускается из под ОЗУ, поэтому запустившись с отладчиком доходим до установленного breakpoint и проверяем тестером что на выводах DUcc напряжение понизилось. После выполнения MDR_OTP_ProgEnd() напряжение должно вернуться в исходный уровень. 
 + 
 +<​code>​ 
 +void OPT_WriteTestData(void) 
 +
 +  MDR_OTP_Enable(); ​  
 +  MDR_OTP_ProgBegin_ByClockCPU_Hz(freqCPU_Hz);​  
 +//  MDR_OTP_ProgWord(OTP_TEST_PROG_ADDR,​ OTP_TEST_PROG_DATA);​ - отключаем программирование 
 +  MDR_OTP_ProgEnd(); ​ // Breakpoint сюда, чтобы увидеть снижение DUcc 
 +  MDR_OTP_Disable();​  
 +
 +</​code>​ 
 + 
 +**Обязательно следует проверить,​ что задержки формируются правильно для используемого источника тактирования!** 
 + 
 +На картинке на плату заведено тактирование от внешнего источника на 25МГц, частота подключена к выводу HSE1. Эта частота использовалась для одного из запусков проекта. Чтобы задержки считались правильно,​ в файле MDR_ConfigVE8.h была указана частота,​ которая подключена снаружи для HSE1. Если внешняя частота будет выбрана другая,​ обязательно необходимо поменять значение в MDR_ConfigVE8.h. 
 + 
 +<​code>​ 
 +//​================ ​ Параметры источников частоты ================ 
 +//  External Generators 
 +... 
 +#define HSE1_FREQ_HZ ​     25000000UL 
 +#define HSE1_OTP_DELAY ​   MDR_OTP_Delay_le_20MHz84 
 +</​code>​ 
 + 
 +Чтобы измерить задержки,​ запускаем проект под отладчиком,​ при этом начнет мигать LED1 (VD7). Нажимаем Key3 и видим что начинает тускло гореть светодиод LED3 (VD9). Измеряем сигнал на выводе + данного светодиода,​ должны получится картинки,​ как те что были представлены в предыдущем разделе. Измеряем задержки аналогично. Если задержки неправильные,​ ищем в чем проблема - переходить к прошивке с неправильными задержками нельзя. 
 + 
 +Параметр HSE1_OTP_DELAY - задержку доступа к OTP оставляем минимальной,​ чтобы верификация приходила с максимальной скоростью доступа к памяти. 
 + 
 +====Запуск проекта - Прошивка==== 
 +Для прошивки ячейки памяти в проекте предлагается такой алгоритм действий:​ 
 +  - Включаем плату. 
 +  - Входим в режим отладки,​ запускаем по F5. Начинает мигать LED1 (VD7) показывая что код main исполняется. 
 +  - Нажимаем KEY2 (Read), при этом должен загореться светодиод LED3 (VD9) Error. Потому что ячейка памяти еще не прописана и содержит пустое значение 0х00000000. 
 +  - Теперь включаем подачу напряжения программирования - 7,2В. 
 +  - Нажимаем KEY1 (Write), загораются все три светодиода. Меньше чем через секунду светодиоды погаснут - программирование закончилось. 
 +  - Нажимаем KEY2 чтобы убедиться,​ что значение прописалось. Если значение правильное то загорится LED2 (OK), если данные не совпали - LED3 (Error).  
 +  - Если данные не совпали,​ горит LED3, то повторяем запись - нажимаем KEY1. Так-же можно посмотреть отладчиком ​ на сколько отличаются данные,​ какие биты не прописались. 
 +  - Отключаем источник 7,2В. 
 +  - Отключаем питание платы. Выжидаем некоторое время, чтобы МК полностью сбросился. 
 +  - Включаем снова плату и нажимаем KEY2 - убеждаемся что память содержит значение в нее записанное - должен гореть LED2 (OK). 
 + 
 +При запусках проекта мы не столкнулись с ошибками при записи,​ память прописывалась с первого раза, на какой бы частоте мы ее не прописывали. Но в данном проекте нет как такового этапа верификации. Память здесь читается через регистровый доступ чтобы не было выхода в HardFault из-за ошибок ЕСС, при этом она фактически читается не при 25МГц и не через необходимые шины. Поэтому в данном примере качество "​прожига"​ оценить нельзя. 
 + 
 +Для прошивки следующего слова необходимо увеличить OTP_TEST_TEST_IND и можно поменять слово данных для разнообразия.  
 + 
 +Не стоит пытаться дописать новые биты "​1"​ в эту же ячейку памяти,​ потому что для нового значения слова изменится и ЕСС, для которого скорее всего потребуется изменить уже прописанный "​0"​ на "​1",​ что невозможно. Но с другой стороны,​ если дописываемый бит будет всего один, то это даст сбой по единичной ошибке ЕСС, которая будет аппаратно парирована в случае чтения данного слова по шине. Это можно использовать для проверки того, как отрабатывает контроллер ошибок **FT_CNTRL**,​ как генерируются события ошибки,​ прерывания и прочее. 
 + 
 +=====Выводы===== 
 +Запуск проекта показал,​ что функции работы с OTP 1986ВЕ8Т драйвера MDR_OTP отрабатывают правильно. Следующим шагом будет написать на основе их FLM и прошить какой-нибудь проект,​ тоже куда-нибудь в конец памяти. 
 + 
 +Ссылка на проект - [[https://​github.com/​StartMilandr/​MDR_Pack_v6/​tree/​master/​PACK_Gen/​Files/​Examples/​All_Boards/​OTP/​OTP_Test_VE8|GitHub]]
prog/example_v6/otp_test_ve8.1570713330.txt.gz · Последние изменения: 2019/10/10 17:15 — vasco