IAP Demo - erasing / writing flash memory etc.

Download pre-release library modules and new examples to use with Astrobe for Cortex-M3. Forum members can also upload their own source code examples.

IAP Demo - erasing / writing flash memory etc.

Postby cfbsoftware » Wed Jun 06, 2012 1:16 pm

Main Module - IAPDemo.mod:
Code: Select all
MODULE IAPDemo;
(* ========================================================================= 
   Example Cortex-M3 Oberon Program 
 
   Description:
     Uses the LPC1000 on-chip IAP functions to perform the following:
     
     1. Display the part identification number
     2. Display the boot code version number
     3. Display the unique device serial number
     4. Display the last sector details
     5. Fill the last sector with 0AAH
     6. Blank check the last sector
     7. Prepare the last sector
     8. Erase the last sector
     9. Blank check the last sector again
    10. Compare a range of identical bytes
    11. Compare a range of dissimilar bytes
 
   Astrobe for Cortex-M3 Version:
      v4.2 or later
   
  Target:
     All supported LPC13xx / LPC17xx systems
     
   References:
     The chapter titled: LPC13xx Flash memory programming firmware
       NXP UM10375 LPC1311/13/42/43 User manual

     The chapter titled: LPC17xx Flash memory interface and programming
       NXP UM10360 LPC17xx User manual
       
     Oberon for Cortex-M3 Microcontrollers: Library Modules > IAP
   
   (c) 2010-2012 CFB Software   
   http://www.astrobe.com 
 
 ========================================================================= *)

IMPORT Device, IAP, Out, Main, MAU, MCU, SYSTEM;


PROCEDURE OutLabel(label: ARRAY OF CHAR);
(* Pad the label with trailing blanks and a colon *)
VAR
  str: ARRAY 16 OF CHAR;
  i: INTEGER;
BEGIN
  str := "             : ";
  FOR i := 0 TO LEN(label) - 1 DO
    str[i] := label[i]
  END;
  Out.String(str)
END OutLabel;


PROCEDURE ShowPartID;
VAR
  id: INTEGER;
BEGIN
  IAP.ReadPartID(id);
  OutLabel("Device Id"); Out.Hex(id, 9); Out.Ln;
  OutLabel("Device Name");
  Out.String("LPC"); Out.Int(Device.name, 0);
  Out.Ln()
END ShowPartID;
 

PROCEDURE OutVersionNumber(version: INTEGER);
VAR
  major, minor: INTEGER;
BEGIN
   major := version MOD 010000H DIV 100H;
  minor := version MOD 100H;
  Out.Int(major, 0);
  Out.Char(".");
  IF minor < 10 THEN Out.Char("0") END;
  Out.Int(minor, 0)
END OutVersionNumber;


PROCEDURE ShowBootVersion;
VAR
  version: INTEGER;
BEGIN
  IAP.ReadBootVersion(version);
  OutLabel("Version Code"); Out.Hex(version, 9); Out.Ln;
  OutLabel("Version No"); OutVersionNumber(version); Out.Ln
END ShowBootVersion;


PROCEDURE ShowUniqueID;
VAR
  id: IAP.UniqueID;
  i: INTEGER;
BEGIN
  IAP.ReadUniqueID(id);
  OutLabel("UniqueID");
  FOR i := 0 TO LEN(id) - 1 DO
    Out.Hex(id[i], 9);
    Out.Char(" ")
  END;
  Out.Ln
END ShowUniqueID;


PROCEDURE ShowLastSector();
VAR
  lastSector, size, addr: INTEGER;
BEGIN
  lastSector := Device.sectorCount;
  addr := Device.SectorStartAddr(lastSector);
  size := Device.SectorSize(lastSector);
  OutLabel("Last sector");
  Out.String("No = "); Out.Int(lastSector, 0);
  Out.String(", Address = "); Out.Hex(addr, 0);
  Out.String(", Size = "); Out.Int(size, 0);
  Out.Ln()
END ShowLastSector;


PROCEDURE ShowStatus(msg: ARRAY OF CHAR; status: INTEGER);
BEGIN
  OutLabel(msg);
  IF status = 0 THEN
    Out.String("OK")
  ELSE
    Out.String("Error code ");
    Out.Int(status, 0)
  END;
  Out.Ln
END ShowStatus;


PROCEDURE CheckBlankLastSector();
VAR
  offset, contents, status, lastSector: INTEGER;
BEGIN
  lastSector := Device.sectorCount;
  status := IAP.BlankCheckSectors(lastSector, lastSector, offset, contents);
  ShowStatus("CheckBlank", status);
  IF status = IAP.SectorNotBlank THEN
    OutLabel("Results");
    Out.String("Offset = "); Out.Hex(offset, 10);
    Out.String(", Contents = "); Out.Hex(contents, 10);
    Out.Ln
  END;
END CheckBlankLastSector;


PROCEDURE CompareBytes(addr1, addr2, nBytes: INTEGER);
VAR
  offset, status: INTEGER;
BEGIN
  status := IAP.CompareBytes(addr1, addr2, nBytes, offset);
  ShowStatus("Compare", status);
  IF status = IAP.CompareError THEN
    OutLabel("Results");
    Out.String("Offset = "); Out.Hex(offset, 10); Out.Ln
  END
END CompareBytes;


PROCEDURE EraseLastSector();
VAR
  lastSector: INTEGER;
BEGIN
  lastSector := Device.sectorCount;
  ShowStatus("Prepare", IAP.PrepareSectors(lastSector, lastSector));
  ShowStatus("Erase", IAP.EraseSectors(lastSector, lastSector, MCU.CCLK))
END EraseLastSector;

PROCEDURE MaxBlockSize(): INTEGER;
(* IAP.WriteFlash requires blocks to be written to be one of four sizes *)
(* Choose the largest that can be used as a dynamic local array         *)
VAR
  i: INTEGER;
  sizes: ARRAY 5 OF INTEGER;
BEGIN
  sizes[0] := 4096;
  sizes[1] := 1024;
  sizes[2] := 512;
  sizes[3] := 256;
  sizes[4] := 0;
  i := 0;
  WHILE (i <= 3) & (sizes[i] > MAU.MemAvailable()) DO
    INC(i)
  END;
  RETURN sizes[i]
END MaxBlockSize; 


PROCEDURE FillLastSector(value: CHAR);
(* Fill the last sector of flash RAM with value *)
VAR
  i, srcAddr, destAddr, lastSector, nBlocks, nBytes, blockSize: INTEGER;
  block: ARRAY OF CHAR;
BEGIN
  blockSize := MaxBlockSize();
  NEW(block, blockSize);
  lastSector := Device.sectorCount;
  nBytes := Device.SectorSize(lastSector);
  destAddr := Device.SectorStartAddr(lastSector);
  FOR i := 0 TO blockSize - 1 DO
    block[i] := value
  END;
  srcAddr := SYSTEM.ADR(block);
  nBlocks := nBytes DIV blockSize;
  OutLabel("WriteFlash");
  Out.String("srcAddr = "); Out.Hex(srcAddr, 0);
  Out.String(", destAddr = "); Out.Hex(destAddr, 10);
  Out.Ln();
  OutLabel("");
  Out.String("blockSize = "); Out.Int(blockSize, 0);
  Out.String(", nBlocks = "); Out.Int(nBlocks, 0);
  Out.Ln();
  FOR i := 0 TO nBlocks - 1 DO
    ShowStatus("Prepare", IAP.PrepareSectors(lastSector, lastSector));
    ShowStatus("WriteFlash", IAP.WriteFlash(srcAddr, destAddr, blockSize, MCU.CCLK));
    destAddr := destAddr + blockSize
  END
END FillLastSector;


BEGIN
  ShowPartID();
  ShowBootVersion();
  ShowUniqueID();
  ShowLastSector();
  FillLastSector(0AAX);
  CheckBlankLastSector();
  EraseLastSector();
  CheckBlankLastSector();
  CompareBytes(01000H, 01000H, 256);
  CompareBytes(01000H, 02000H, 256)
END IAPDemo.

Device.def
Code: Select all
DEFINITION MODULE Device;

IMPORT IAP;

VAR
  (* Number of sectors of flash memory *)
  sectorCount*,
  (* MCU Target name e.g. 1343, 1755 etc. identified
     by using IAP to read the PartID
  *)
  name*: INTEGER;

PROCEDURE* SectorStartAddr*(sectorNo: INTEGER): INTEGER;
(* Sectors 0..15 are 4KB, Sectors 16..29 are 32KB *)

PROCEDURE* SectorSize*(sectorNo: INTEGER): INTEGER;
(* Sectors 0..15 are 4KB, Sectors 16..29 are 32KB *)
   
END Device.

Device.mod:
Code: Select all
MODULE Device;
(* ========================================================================= 
   Astrobe for Cortex-M3 Library Functions for device-specific features 
 
   Target:
     All supported LPC13xx / LPC17xx systems
     
   (c) 2012 CFB Software   
   http://www.astrobe.com 
 
 ========================================================================= *)

IMPORT IAP;

VAR
  id: INTEGER;
  sectorCount*, name*: INTEGER;

PROCEDURE* Init(id: INTEGER; VAR name, sectorCount: INTEGER);
BEGIN
  IF id = 02C40102BH THEN
    name := 1313; 
    sectorCount := 7
  ELSIF id = 03D00002BH THEN
    name := 1343; 
    sectorCount := 7
  ELSIF id = 025001118H THEN
    name := 1751; 
    sectorCount := 7
  ELSIF id = 025001121H THEN
    name := 1752; 
    sectorCount := 15
  ELSIF id = 025011722H THEN
    name := 1754; 
    sectorCount := 17
  ELSIF id = 025011723H THEN
    name := 1756; 
    sectorCount := 21
  ELSIF id = 025013F37H THEN
    name := 1758; 
    sectorCount := 29
  ELSIF id = 025113737H THEN
    name := 1759; 
    sectorCount := 29
  ELSIF id = 026012033H THEN
    name := 1763; 
    sectorCount := 21
  ELSIF id = 026011922H THEN
    name := 1764; 
    sectorCount := 17
  ELSIF id = 026013733H THEN
    name := 1765; 
    sectorCount := 21
  ELSIF id = 026013F33H THEN
    name := 1766; 
    sectorCount := 21
  ELSIF id = 026012837H THEN
    name := 1767; 
    sectorCount := 29
  ELSIF id = 026013F37H THEN
    name := 1768; 
    sectorCount := 29
  ELSIF id = 026113F37H THEN
    name := 1769; 
    sectorCount := 29
  END
END Init;


PROCEDURE* SectorStartAddr*(sectorNo: INTEGER): INTEGER;
(* Sectors 0..15 are 4KB, Sectors 16..29 are 32KB *)
VAR
  addr: INTEGER;
BEGIN
  ASSERT(sectorNo >= 0, 20);
  ASSERT(sectorNo <= sectorCount, 21);
  IF sectorNo < 16 THEN
    addr := 00001000H * sectorNo
  ELSE
    addr := 00010000H + ((sectorNo - 16) * 08000H)
  END;
  RETURN addr
END SectorStartAddr;


PROCEDURE* SectorSize*(sectorNo: INTEGER): INTEGER;
(* Sectors 0..15 are 4KB, Sectors 16..29 are 32KB *)
VAR
  nBytes: INTEGER;
BEGIN
  ASSERT(sectorNo >= 0, 20);
  ASSERT(sectorNo <= sectorCount, 21);
  IF sectorNo < 16 THEN
    nBytes := 4 * 1024
  ELSE
    nBytes := 32 * 1024
  END; 
  RETURN nBytes
END SectorSize;
   
   
BEGIN
  IAP.ReadPartID(id);
  Init(id, name, sectorCount)
END Device.

Typical Output (run on a Coridium SuperPRO development board):
IAPDemo.png
You do not have the required permissions to view the files attached to this post.
cfbsoftware
Site Admin
 
Posts: 302
Joined: Fri Dec 31, 2010 12:30 pm

Return to Cortex-M3