В предыдущей статье был добавлен в командную строку файл прошивки памяти RAM, в класс Dumps.cs были добавлены модули записи в RAM и копирования в RAM память STM8. В этой статье добавляем модули записи в EEPROM память.
В адресном пространстве STM8S103F3 ячейки EEPROM памяти расположены в адресах $4000...$427F (640 байт). Память EEPROM разделена на 10 блоков(block) по 16 слов(word) или 64 байта, в каждом слове 4 байта. Начальные адреса блоков, выровненны по маске $xx00 $xx40 $xx80 $xxC0. Начальные адреса слов, выровненны по маске $xxx0 $xxx4 $xxx8 $xxC. Байты имеют произвольный доступ в пределах адресного пространства. Адреса блоков :
$4000...$403F, $4040...$407F, $4080...$40BF, $40C0...$40FF, $4100...$413F, $4140...$417F, $4180...$41BF, $41C0...$41FF, $4200...$423F, $4240...$427F.
В отличие от записи в RAM запись в EEPROM требует :
- разблокирования EEPROM памяти после каждого сброса STM8 последовательной записью значений $AE и $56 в регистр FLASH_DUKR ($5064). С этого момента доступна побайтовая запись ячеек памяти EEPROM. При некорректной записи в регистр FLASH_DUKR потребуется повторная перезагрузка STM8;
- выбора режима Standard block programming (запись блока со стиранием) $01/$FE, Fast block programming (запись блока без стиранием) $10/$EF, Block erase (стирание блока) $20/$DF, Word programming $40/$BF последовательной записью в регистры FLASH_CR2 ($505B) и FLASH_NCR2 ($505C). При некорректной записи в регистры FLASH_CR2 ($505B) и FLASH_NCR2 ($505C) будет выполняться только побайтовая(медленная) запись;
- на время записи/стирания EEPROM памяти останавливается выполнение программы;
- программа записи/стирания EEPROM памяти (кроме побайтовой записи) желательно должна исполняться из RAM памяти;
- при побайтовой записи в EEPROM требуется только предварительное разблокирование последовательной записью значений $AE и $56 в регистр FLASH_DUKR ($5064), далее обычные команды записи в ячейки памяти (напр LD).
Standard block programming. В этом режиме происходит запись блока с автоматическим стиранием (требуется в два раза больше времени на запись). Алгоритм записи:
1 - разблокировать запись/стирание EEPROM последовательным копированием значений $AE и $56 в регистр FLASH_DUKR ($5064), если это еще не сделано;
2 - выбрать режим Standard block programming последовательным копированием значений $01 и $FE в регистры FLASH_CR2 ($505B) и FLASH_NCR2 ($505C) соответственно;
3 - наполнить блок с начального адреса, выровненного по маске $xx00 $xx40 $xx80 $xxC0 требуемым содержимым командами записи в ячейки памяти (напр LD, MOV и пр.);
4 - при копировании в блок всех 64 байтов автоматически начинается запись блока, на время записи останавливается выполнение команд;
5 - после записи блока режим Standard block programming отключается;
6 - при необходимоти записи следующего блока перейти к п.2;
7 - при копирования более 64 байт лишние байты будут записываться в побайтовом (медленном) режиме ;
8 - после окончания записи автоматически начнется выполнение команд.
; unlock EEPROM memory (writing the correct MASS keys) mov FLASH_DUKR, #$AE ; Write $AE then $56 in FLASH_DUKR($5064) mov FLASH_DUKR, #$56 mov FLASH_CR2, #$01 ; Write $01 then $FE in FLASH_CR2($505B) and FLASH_NCR2($505C) mov FLASH_NCR2, #$FE ldw X, #$8800 ; src table in FLASH ldw Y, #$4240 ; dst table in EEPROM mov $0000, #64 ; counter in RAM Write_block_cycle: ld A, (X) ld (Y), A ; после выполнения этой команды при последней итерации начинается запись блока dec $0000 ; после окончания записи блока начинает выполняться эта команда jrne Write_block_cycle
Fast block programming. В этом режиме происходит запись блока с предварительно стертым содержимым (требуется меньше времени на запись). Алгоритм записи:
1 - разблокировать запись/стирание EEPROM памяти данных последовательным копированием значений $AE и $56 в регистр FLASH_DUKR ($5064), если это еще не сделано;
2 - выбрать режим Fast block programming последовательным копированием значений $10 и $EF в регистры FLASH_CR2 ($505B) и FLASH_NCR2 ($505C) соответственно;
3 - наполнить блок с начального адреса, выровненного по маске $xx00 $xx40 $xx80 $xxC0 требуемым содержимым командами записи в ячейки памяти (напр LD, MOV и пр.);
4 - при копировании в блок всех 64 байтов автоматически начинается запись блока, на время записи останавливается выполнение команд;
5 - после записи блока режим Fast block programming отключается;
6 - при необходимоти записи следующего блока перейти к п.2;
7 - при копирования более 64 байт лишние байты будут записываться в побайтовом (медленном) режиме ;
8 - после окончания записи автоматически начнется выполнение команд.
Block erase. В этом режиме происходит стирание содержимого блока. Алгоритм стирания:
1 - разблокировать запись/стирание EEPROM памяти данных последовательным копированием значений $AE и $56 в регистр FLASH_DUKR ($5064), если это еще не сделано;
2 - выбрать режим Block erase последовательным копированием значений $20 и $DF в регистры FLASH_CR2 ($505B) и FLASH_NCR2 ($505C) соответственно;
3 - скопировть значение $00 в четыре последовательные ячейки памяти внутри блока с начальным адресом выровненым по маске $xxx0 $xxx4 $xxx8 $xxxC командами записи в ячейки памяти (напр LD, MOV и пр.);
4 - автоматически начнется стирание блока, на время стирания останавливается выполнение команд;
5 - после стирания блока режим Block erase отключается;
6 - при необходимоти стереть следующий блок перейти к п.2;
7 - после окончания стирания блока автоматически начнется выполнение команд.
Word programming. В этом режиме происходит запись слова. Стирание происходит записью нулевых значений. Алгоритм записи:
1 - разблокировать запись/стирание EEPROM памяти данных последовательным копированием значений $AE и $56 в регистр FLASH_DUKR ($5064), если это еще не сделано;
2 - выбрать режим Word programming последовательным копированием значений $40 и $BF в регистры FLASH_CR2 ($505B) и FLASH_NCR2 ($505C) соответственно;
3 - заполнить содержимым четыре последовательные ячейки памяти с начальным адресом выровненным по маске $xxx0 $xxx4 $xxx8 $xxxC;
4 - при копировании всех 4 байтов автоматически начинается запись слова, на время записи останавливается выполнение команд;
5 - после записи блока режим Word programming отключается;
7 - при копирования более 4 байт лишние байты будут записываться в побайтовом (медленном) режиме ;
8 - после окончания записи автоматически начнется выполнение команд.
mov FLASH_DUKR, #$AE mov FLASH_DUKR, #$56 mov FLASH_CR2, #$40 mov FLASH_NCR2, #$BF ; следующая запись произойдет с начальным адресом $4100 mov $4100, #$11 ; запись произойдет по адресу $4100 mov $4101, #$11 ; запись произойдет по адресу $4101 mov $4102, #$11 ; запись произойдет по адресу $4102 mov $4103, #$11 ; запись произойдет по адресу $4103 mov FLASH_DUKR, #$40 mov FLASH_DUKR, #$BF ; следующая запись произойдет с начальным адресом $4240 вместо ожидаемого $423F ld A, #$33 ld $423F, A ; запись произойдет по адресу $4240 ld $4240, A ; запись произойдет по адресу $4241 ld $4241, A ; запись произойдет по адресу $4242 ld $4242, A ; запись произойдет по адресу $4243 ; следующая запись произойдет с начальным адресом $4124 вместо ожидаемого $4121 mov FLASH_DUKR, #$40 mov FLASH_DUKR, #$BF ldw X, #$8200 ldw Y, #$4121 mov $0000, #4 Write_word_cycle: ld A, (X) ld (Y), A dec $0000 jrne Write_word_cycle
Byte programming. В этом режиме происходит побайтовая запись в ячейки EEPROM. Для STM8S103F3 на время записи также останавливается выполнеие команд. Алгоритм записи:
1 - разблокировать запись/стирание EEPROM последовательным копированием значений $AE и $56 в регистр FLASH_DUKR ($5064), если это еще не сделано;
2 - скопировать байт(байты) в ячейку(ячейки) EEPROM командами записи в ячейки памяти (напр LD, MOV и пр.);
3 - на время записи каждого байта останавливается выполнение команд.
; unlock EEPROM memory (writing the correct MASS keys) mov FLASH_DUKR, #$AE ; Write $AE then $56 in FLASH_DUKR($5064) mov FLASH_DUKR, #$56 ; If wrong keys have been entered, another key programming sequence can be issued without resetting the device. mov $427F, #$14
Классы [Dumps], [FileOpenMemorySorting], [IntelHEXfile], [MotorolaS19file].
Файл STM8uLoader.cs :
// STM8uLoader.cs using System; using System.IO; using System.IO.Ports; using System.Threading; using System.Collections.Generic; public class STM8uLoader { public static void Main(string[] arg) { if (arg.Length == 0) {Console.WriteLine("Отсутствуют аргументы командной строки"); Console.ReadKey(); return;} else fileName = arg[0]; Console.WriteLine("Обнаружены {0} аргумент(ов) командной строки", arg.Length); foreach(string strArg in arg){ Console.WriteLine(strArg); }//foreach FileOpenMemorySorting fileSorted = new FileOpenMemorySorting(fileName); Console.Write("Из файла"); foreach( KeyValuePairkvp in fileSorted.GetRAMaddressLineSorted() ){ Console.Write("\n${0:X4} ", kvp.Key); for(int i = 0; i < kvp.Value.Length; i++) Console.Write("${0:X2} ", kvp.Value[i]); }// foreach Console.WriteLine("\n"); //Dumps myDumps = new Dumps(); Dumps.COM_port_Open(); readThread = new Thread(Dumps.Read); readThread.IsBackground = true; // не позволит остаться потоку в памяти после закрытия программы ? try { readThread.Start(); // запускаем поток чтения COM порта } catch (Exception ex) {Console.WriteLine("readThread.Start(). Exception" + ex.Message); } Dumps.Load_First_Dump(Dumps.Read_128000v14); blckAdr = 0x0100; blckSize = 178; Console.WriteLine("Из памяти до записи"); Dumps.Dump_To_Console(Dumps.Read_128000(blckAdr, blckSize)); //Dumps.Load_Dump(Dumps.Write_RAM_128000v14); Console.WriteLine("пишем в память"); Dumps.Write_RAM_128000(fileSorted.GetRAMaddressLineSorted()); //Dumps.Load_Dump(Dumps.Read_128000v14); blckAdr = 0x0100; blckSize = 178; Console.WriteLine("Из памяти после записи"); Dumps.Dump_To_Console(Dumps.Read_128000(blckAdr, blckSize)); blckAdr = 0x4100; blckSize = 512; Console.WriteLine("Из EEPROM до записи"); Dumps.Dump_To_Console(Dumps.Read_128000(blckAdr, blckSize)); addressBytesBlock.Clear(); blckAdr = 0x4100; for(int i = 0; blckAdr < 0x4280; i = i + 64){ for(int j = 0; j < 64; j++){ blck64Bytes[j] = (byte)0x00; } addressBytesBlock.Add(blckAdr, blck64Bytes); blckAdr = blckAdr + 64; } Dumps.WriteBlock_EEPROM_128000(addressBytesBlock); blckAdr = 0x4100; blckSize = 512; Console.WriteLine("Из EEPROM после записи"); Dumps.Dump_To_Console(Dumps.Read_128000(blckAdr, blckSize)); addressBytesBlock.Clear(); blckAdr = 0x4100; for(; blckAdr < 0x4280;){ for(int j = 0; j < 4; j++){ wrd4Bytes[j] = (byte)0x11; } addressBytesBlock.Add(blckAdr, wrd4Bytes); blckAdr = blckAdr + 19; } Dumps.WriteWord_EEPROM_128000(addressBytesBlock); blckAdr = 0x4100; blckSize = 512; Console.WriteLine("Из EEPROM после записи"); Dumps.Dump_To_Console(Dumps.Read_128000(blckAdr, blckSize)); readThread.Join(); // останавливаем поток чтения COM порта Dumps.COM_port_Close(); Console.ReadKey(); return; } // Main(); public static Thread readThread; public static string stringMemoryMap = ""; public static byte rx_byte = 0x00; public static byte[] btBytes = new byte[1]; public static byte[] wrd4Bytes = new byte[4]; public static byte[] blck64Bytes = new byte[64]; public static byte[] blck192Bytes = new byte[192]; public static SortedDictionary addressBytesBlock = new SortedDictionary (); public static int blckAdr; public static int blckSize; public static bool unready = true; public static string fileName; public static byte[] txBytes = {0, 0}; }// class STM8uLoader // STM8uLoader.cs
Запускаем BAT файл [run.bat], нажимаем кнопку сброса на плате STM8.
В следующей статье добавим в класс Dumps.cs модули записи во FLASH память программ.
Исходники:[boot_PC.zip] , [WriteByte_EEPROM_128000v14.asm] , [WriteWord_EEPROM_128000v14.asm] , [WriteBlock_EEPROM_128000v14.asm] .