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.
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.
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.