NFLic

STM8uLoader

Класс Dumps. Модули записи в память FLASH (Статья 10)

В предыдущей статье в класс Dumps.cs были добавлены модули записи в EEPROM память данных микоконтроллера STM8S103F3. В этой статье добавляем модули записи во FLASH память программ.

В адресном пространстве STM8S103F3 ячейки FLASH памяти программ расположена в адресах $8000...$9FFF. Память FLASH разделена на 128 блоков(block) по 16 слов(word) или 64 байта, в каждом слове 4 байта. Начальные адреса блоков, выровненны по маске $xx00 $xx40 $xx80 $xxC0. Начальные адреса слов, выровненны по маске $xxx0 $xxx4 $xxx8 $xxC. Байты имеют произвольный доступ в пределах адресного пространства. Адреса блоков :

 

  $8000...$803F, $8040...$807F, $8080...$80BF, $80C0...$80FF, 
  $8100...$813F, $8140...$817F, $8180...$81BF, $81C0...$81FF,
  $8200...$823F, $8240...$827F, $8280...$82BF, $82C0...$82FF, 
  $8300...$833F, $8340...$837F, $8380...$83BF, $83C0...$83FF,
  $8400...$843F, $8440...$847F, $8480...$84BF, $84C0...$84FF, 
  $8500...$853F, $8540...$857F, $8580...$85BF, $85C0...$85FF,
  $8600...$863F, $8640...$867F, $8680...$86BF, $86C0...$86FF, 
  $8700...$873F, $8740...$877F, $8780...$87BF, $87C0...$87FF,
  $8800...$883F, $8840...$887F, $8880...$88BF, $88C0...$88FF, 
  $8900...$893F, $8940...$897F, $8980...$89BF, $89C0...$89FF,
  $8A00...$8A3F, $8A40...$8A7F, $8A80...$8ABF, $8AC0...$8AFF, 
  $8B00...$8B3F, $8B40...$8B7F, $8B80...$8BBF, $8BC0...$8BFF,
  $8C00...$8C3F, $8C40...$8C7F, $8C80...$8CBF, $8CC0...$8CFF, 
  $8D00...$8D3F, $8D40...$8D7F, $8D80...$8DBF, $8DC0...$8DFF,
  $8E00...$8E3F, $8E40...$8E7F, $8E80...$8EBF, $8EC0...$8EFF, 
  $8F00...$8F3F, $8F40...$8F7F, $8F80...$8FBF, $8FC0...$8FFF,
  $9000...$903F, $9040...$907F, $9080...$90BF, $90C0...$90FF, 
  $9100...$913F, $9140...$917F, $9180...$91BF, $91C0...$91FF,
  $9200...$923F, $9240...$927F, $9280...$92BF, $92C0...$92FF, 
  $9300...$933F, $9340...$937F, $9380...$93BF, $93C0...$93FF,
  $9400...$943F, $9440...$947F, $9480...$94BF, $94C0...$94FF, 
  $9500...$953F, $9540...$957F, $9580...$95BF, $95C0...$95FF,
  $9600...$963F, $9640...$967F, $9680...$96BF, $96C0...$96FF, 
  $9700...$973F, $9740...$977F, $9780...$97BF, $97C0...$97FF,
  $9800...$983F, $9840...$987F, $9880...$98BF, $98C0...$98FF, 
  $9900...$993F, $9940...$997F, $9980...$99BF, $99C0...$99FF,
  $9A00...$9A3F, $9A40...$9A7F, $9A80...$9ABF, $9AC0...$9AFF, 
  $9B00...$9B3F, $9B40...$9B7F, $9B80...$9BBF, $9BC0...$9BFF,
  $9C00...$9C3F, $9C40...$9C7F, $9C80...$9CBF, $9CC0...$9CFF, 
  $9D00...$9D3F, $9D40...$9D7F, $9D80...$9DBF, $9DC0...$9DFF,
  $9E00...$9E3F, $9E40...$9E7F, $9E80...$9EBF, $9EC0...$9EFF, 
  $9F00...$9F3F, $9F40...$9F7F, $9F80...$9FBF, $9FC0...$9FFF.

 

В отличие от записи в RAM запись в FLASH требует :

- разблокирования FLASH памяти после каждого сброса устройства последовательной записью значений $56 и $AE в регистр FLASH_PUKR ($5062). С этого момента доступна побайтовая запись ячеек памяти FLASH. При некорректной записи в регистр FLASH_PUKR потребуется перезагрузка устройства;

- выбора режима (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) будет выполняться только побайтовая(медленная) запись;

- на время записи/стирания FLASH памяти останавливается выполнение программы;

- программа записи/стирания FLASH памяти (кроме побайтовой записи) желательно должна исполняться из RAM памяти;

- при побайтовой записи в FLASH требуется только предварительное разблокирование последовательной записью значений $56 и $AE в регистр FLASH_PUKR ($5062), далее обычные команды записи в ячейки памяти (напр LD).

 

Запись в ячейки памяти FLASH с адресами $8000...$8003, $9FF0...$9FFD повредит код начального копировщика boot_FLASH. Необходимо предусмотреть соответствующие блокировки в хост-программе компьютера и, возможно, в соответствующих модулях/дампах.

 

Standard block programming. В этом режиме происходит запись блока с автоматическим стиранием (требуется в два раза больше времени на запись). Алгоритм записи:

1 - разблокировть запись/стирание FLASH памяти программ последовательным копированием значений $56 и $AE в регистр FLASH_PUKR ($5062)), если это еще не сделано;

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 FLASH memory  (writing the correct MASS keys)
         mov      FLASH_PUKR, #$56      ; Write $56 then $AE in FLASH_PUKR($5062)
         mov      FLASH_PUKR, #$AE
         mov      FLASH_CR2,  #$01      ; Write $01 then $FE in FLASH_CR2($505B) and FLASH_NCR2($505C)   
         mov      FLASH_NCR2, #$FE      
         ldw     X, #$4240              ; src table in EEPROM
         ldw     Y, #$9300              ; dst table in FLASH
         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 - разблокировать запись/стирание FLASH памяти программ последовательным копированием значений $56 и $AE в регистр FLASH_PUKR ($5062), если это еще не сделано;

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 - разблокировать запись/стирание FLASH памяти программ последовательным копированием значений $56 и $AE в регистр FLASH_PUKR ($5062), если это еще не сделано;

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 - разблокировать запись/стирание FLASH памяти программ последовательным копированием значений $56 и $AE в регистр FLASH_PUKR ($5062), если это еще не сделано;

2 - выбрать режим Word programming последовательным копированием значений $40 и $BF в регистры FLASH_CR2 ($505B) и FLASH_NCR2 ($505C) соответственно;

3 - заполнить содержимым четыре последовательные ячейки памяти с начальным адресом выровненным по маске $xxx0 $xxx4 $xxx8 $xxxC;

4 - при копировании всех 4 байтов автоматически начинается запись слова, на время записи останавливается выполнение команд;

5 - после записи блока режим Word programming отключается;

7 - при копирования более 4 байт лишние байты будут записываться в побайтовом (медленном) режиме ;

8 - после окончания записи автоматически начнется выполнение следующих команд.

 

    ; unlock FLASH memory  (writing the correct MASS keys)
         mov     FLASH_PUKR, #$56      ; Write $56 then $AE in FLASH_PUKR($5062)
         mov     FLASH_PUKR, #$AE
         mov     FLASH_CR2,  #$40
         mov     FLASH_NCR2, #$BF
    ; следующая запись произойдет с начальным адресом $9C00
         mov     $9C00, #$11      ; запись произойдет по адресу $9C00
         mov     $9C01, #$11      ; запись произойдет по адресу $9C01
         mov     $9C02, #$11      ; запись произойдет по адресу $9C02
         mov     $9C03, #$11      ; запись произойдет по адресу $9C03

         mov     FLASH_PUKR, #$40
         mov     FLASH_PUKR, #$BF
    ; следующая запись произойдет с начальным адресом $8780 вместо ожидаемого $877F
         ld      A, #$33          
         ld      $877F, A         ; запись произойдет по адресу $8780
         ld      $8780, A         ; запись произойдет по адресу $8781
         ld      $8781, A         ; запись произойдет по адресу $8782
         ld      $8782, A         ; запись произойдет по адресу $8783
    ; следующая запись произойдет с начальным адресом $9234 вместо ожидаемого $9231
         mov     FLASH_PUKR, #$40
         mov     FLASH_PUKR, #$BF
         ldw     X, #$4100
         ldw     Y, #$9231
         mov     $0000, #4
    write_word_cycle:
         ld      A, (X)
         ld      (Y), A		 
         dec     $0000
         jrne    write_word_cycle

 

Byte programming. В этом режиме происходит побайтовая запись в ячейки FLASH. Для STM8S103F3 на время записи также останавливается выполнеие команд. Алгоритм записи:

1 - разблокировать запись/стирание FLASH последовательным копированием значений $56 и $AE в регистр FLASH_PUKR ($5062), если это еще не сделано;

2 - скопировать байт(байты) в ячейку(ячейки) EEPROM командами записи в ячейки памяти (напр LD, MOV и пр.);

3 - на время записи каждого байта останавливается выполнение команд.

    ; unlock FLASH memory  (writing the correct MASS keys)
         mov      FLASH_PUKR, #$56      ; Write $56 then $AE in FLASH_PUKR($5062)
         mov      FLASH_PUKR, #$AE 
         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 STM8S103F3 uLoader
{
	
	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("Из файла RAM память");
			foreach( KeyValuePair kvp 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");
		Console.Write("Из файла EEPROM память");
			foreach( KeyValuePair kvp in fileSorted.GetEEPROMaddressLineSorted() ){
				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");
		Console.Write("Из файла FLASH память");
			foreach( KeyValuePair kvp in fileSorted.GetFLASHaddressLineSorted() ){
				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 = 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)0x01;
			}
			addressBytesBlock.Add(blckAdr, blck64Bytes);
			blckAdr = blckAdr + 64;
		}
		Dumps.WriteBlock_EEPROM_128000(addressBytesBlock);

		addressBytesBlock.Clear();
		blckAdr = 0x4100;
		for(; blckAdr < 0x4280;){
			for(int j = 0; j < 4; j++){
				wrd4Bytes[j] = (byte)0x06;
			}
			addressBytesBlock.Add(blckAdr, wrd4Bytes);
			blckAdr = blckAdr + 19;
		}
		Dumps.WriteWord_EEPROM_128000(addressBytesBlock);

		addressBytesBlock.Clear();
		blckAdr = 0x4100;
		for(; blckAdr < 0x4280;){
			btBytes[0] = (byte)0x09;
			addressBytesBlock.Add(blckAdr, btBytes);
			blckAdr = blckAdr + 17;
		}
		Dumps.WriteByte_EEPROM_128000(addressBytesBlock);
		
		blckAdr = 0x4100;	blckSize = 512;
		Console.WriteLine("Из EEPROM после записи");
		Dumps.Dump_To_Console(Dumps.Read_128000(blckAdr, blckSize));

		
		
		blckAdr = 0x9100;	blckSize = 512;
		Console.WriteLine("Из FLASH до записи");
		Dumps.Dump_To_Console(Dumps.Read_128000(blckAdr, blckSize));

		addressBytesBlock.Clear();
		blckAdr = 0x9100;
		for(int i = 0; blckAdr < 0x9280; i = i + 64){
			for(int j = 0; j < 64; j++){
				blck64Bytes[j] = (byte)0x01;
			}
			addressBytesBlock.Add(blckAdr, blck64Bytes);
			blckAdr = blckAdr + 64;
		}
		Dumps.WriteBlock_FLASH_128000(addressBytesBlock);

		addressBytesBlock.Clear();
		blckAdr = 0x9100;
		for(; blckAdr < 0x9280;){
			for(int j = 0; j < 4; j++){
				wrd4Bytes[j] = (byte)0x06;
			}
			addressBytesBlock.Add(blckAdr, wrd4Bytes);
			blckAdr = blckAdr + 19;
		}
		Dumps.WriteWord_FLASH_128000(addressBytesBlock);

		addressBytesBlock.Clear();
		blckAdr = 0x9100;
		for(; blckAdr < 0x9280;){
			btBytes[0] = (byte)0x09;
			addressBytesBlock.Add(blckAdr, btBytes);
			blckAdr = blckAdr + 17;
		}
		Dumps.WriteByte_FLASH_128000(addressBytesBlock);
		
		blckAdr = 0x9100;	blckSize = 512;
		Console.WriteLine("Из FLASH после записи");
		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.

 

 

 

 

В следующей статье попытаемся разработать метод сортировки содержимого по блокам / словам / байтам.

 

Исходники:[boot_PC.zip] , [WriteByte_FLASH_128000v14.asm] , [WriteWord_FLASH_128000v14.asm] , [WriteBlock_FLASH_128000v14.asm] .

 

[Класс Dumps. Модули записи в память EEPROM (Статья 9)] [Оглавление.] [Методы сортировки содержимого по блокам / словам / байтам (Статья 11)]