; --------------------------------------------------------------------------------
; @Title: Flash declaration for NXP LPC54xxx Cortex-M4 internal flash
; @Description:
;   Reprogam internal Flash of NXP LPC54xxx.
;   Script arguments:
;     DO lpc54xx [PREPAREONLY] [CPU=<cpu>] [DUALPORT=<0|1>]
;       PREPAREONLY    only declares flash but does not execute flash programming
;       CPU=<cpu>      selects CPU derivative <cpu>
;       DUALPORT=<0|1> use dual port memory access, default 1
;   Example:
;   DO ~~/demo/arm/flash/lpc54xx CPU=LPC54102J512UK49-M4 PREPAREONLY
;   Note : Flash programming must be done from a Cortex-M4
;
;   List of LPC40xx derivatives and their configuration:
;   CPU-Type          Flash   RamSize    ROM   SRAM0 address
;                      [kB]    [kB]      [kB]
; --------------------------------------------------------------------------------
;   LPC5410x-series:                             0x02000000
;     LPC54101J256       256      64       64
;     LPC54102J256       256      64       64
;     LPC54101J512       512      64       64
;     LPC54102J512       512      64       64
;   LPC5411x-series:                             0x20000000
;     LPC54113J256       256     192       32
;     LPC54114J256       256     192       32
;     LPC54113J128       128      96       32
;     LPC54113J256       256     192       32
;     LPC54114J256       256     192       32
;   LPC546xx-series:                             0x20000000
;     LPC54628J512       512     200       32
;     LPC54618J512       512     200       32
;     LPC54616J256       256     136       32
;     LPC54616J512       512     200       32
;     LPC54608J512       512     200       32
;     LPC54607J256       256     136       32
;     LPC54607J512       512     200       32
;     LPC54606J256       256     136       32
;     LPC54606J512       512     200       32
;     LPC54605J256       512     200       32
;     LPC54605J512       256     136       32
;
;   Memories:
;                              LPC5410      LPC5411      LPC546x
;   Flash at                 0x00000000   0x00000000   0x00000000
;   up to 64 kB SRAM0 at     0x02000000   0x20000000   0x20000000
;   up to 32 kB SRAM1 at     0x02010000   0x20010000
;   up to  8 kB SRAM2 at     0x03400000   0x20020000
;   Boot and Driver ROM at   0x03000000   0x03000000   0x03000000
;   APB0 peripherals         0x40000000   0x03000000   0x03000000
;     Flash Controller       0x40024000   0x40034000
;     Watchdog               0x40038000   0x4000C000
;   APB1 peripherals         0x40080000   0x40020000   0x40020000
;   APB2 peripherals                                   0x40040000
;   AHB peripherals                       0x40080000   0x40080000
;
;   Flash characteristics:
;     Page size     256 Byte
;     Sector size    32 KB
;
;   Code Read Protection (CRP):
;    CRP is invoked by programming a specific pattern in flash location
;    0x000002FC.
;
;   Name     Pattern      Description
; --------------------------------------------------------------------------------
;   CRP1     0x12345678    Access to chip via the JTAG pins is disabled. This mode
;                          allows partial flash update using the following ISP
;                          commands and restrictions:
;                          Write to RAM command can not access RAM below
;                          0x02000300.
;                          Read Memory command: disabled.
;                          Copy RAM to Flash command: cannot write to Sector 0.
;                          Erase sector(s) command: can erase any individual
;                          sector except sector 0 only, or can erase all sectors
;                          at once.
;                          Compare command: disabled
;                          This mode is useful when CRP is required and flash
;                          field updates are needed but all sectors can not be
;                          erased. The compare command is disabled, so in the
;                          case of partial flash updates the secondary loader
;                          should implement a checksum mechanism to verify the
;                          integrity of the flash.
;   CRP2     0x87654321    Access to chip via the SWD pins is disabled.
;                         The following ISP commands are disabled:
;                            Read Memory
;                            Write to RAM
;                            Go
;                            Copy RAM to flash
;                            Compare
;                         When CRP2 is enabled the ISP erase command only allows
;                         erasure of all user sectors.
;   CRP3     0x43218765   This is similar to CRP2, but ISP entry by pulling
;                         P2[10] LOW is disabled if a valid user code is present
;                         in flash sector 0.
;                         This mode effectively disables ISP override using the
;                         P2[10] pin. It is up to the user’s application to
;                         provide for flash updates by using IAP calls or by
;                         invoking ISP with UART0.
;                         CAUTION: If CRP3 is selected, no future factory testing
;                         can be performed on the device.
;
;   Flash programming commands use 32 bytes of space in the top portion of the
;   on-chip SRAM0 0x0200FFE0-0x0200FFFF for execution.
;
;   Hints:
;   Flash clock has to match System Clock Frequency (M4_CLK).
;   FLASH.CLocK.AUTO can be used for automatic flash clock measurement.
;   Boot flash cannot be programmed or erased with builtin flash
;   algorithm.
;   Data has to be loaded into flash aligned to page boundaries.
;
; @Chip: LPC5410*
; @Author: PHI
; @Copyright: (C) 1989-2019 Lauterbach GmbH, licensed for use with TRACE32(R) only
; --------------------------------------------------------------------------------
; $Rev: 8458 $
; $Id: lpc54xx.cmm 8458 2020-06-30 14:54:42Z wdoering $

PRIVATE &parameters
ENTRY %LINE &parameters

PRIVATE &param_prepareonly &param_cpu &param_dualport

&param_prepareonly=(STRing.SCAN(STRing.UPpeR("&parameters"),"PREPAREONLY",0)!=-1)
&param_cpu=STRing.SCANAndExtract(STRing.UPpeR("&parameters"),"CPU=","")
&param_dualport=STRing.SCANAndExtract(STRing.UPpeR("&parameters"),"DUALPORT=","1")


; ------------------------------------------------------------------------------
; Setup CPU

IF !SYStem.Up()
(
  SYStem.RESet

  IF "&param_cpu"!=""
    SYStem.CPU &param_cpu
  IF !CPUIS(LPC54*)
    SYStem.CPU LPC54*

  SYStem.CONFIG.DEBUGPORTTYPE SWD

  SYStem.Option ResBreak OFF
  SYStem.Up
)
ELSE
(
  IF CPUIS(LPC54*-M0+)
  (
    PRINT "Wrong CPU, Flash programming can only be done from Cortex-M4 of LPC54x"
    ENDDO
  )
)


; ensure the M0+ is in Reset (Cortex-M0+ only available on LPC5410x and LPC5411x)
IF (CPUIS("LPC5410*"))
  Data.Set SD:0x40000300 %Long 0xc0c4006D
ELSE IF (CPUIS("LPC5411*"))
  Data.Set SD:0x40000800 %Long 0xc0c4006D


; ------------------------------------------------------------------------------
; Flash declaration

FLASH.RESet
GOSUB FlashDeclaration "&param_dualport"

; Flash script ends here if called with parameter PREPAREONLY
IF &param_prepareonly
  ENDDO PREPAREDONE


; ------------------------------------------------------------------------------
; Flash programming

DIALOG.YESNO "Program flash memory?"
PRIVATE &progflash
ENTRY &progflash

IF &progflash
(
  FLASH.Erase.ALL
  FLASH.ReProgram.ALL
  Data.LOAD.auto * /Long
  Data.SUM 0x00000000--0x0000001B /Long  ; Calculate checksum of all (other) vectors
  Data.Set 0x0000001C %Long -Data.SUM()  ; Write the 2's complement in reserved vector's spot
  FLASH.ReProgram.off

  ; Reset device
  SYStem.Down
  SYStem.Up
)

ENDDO

; --------------------------------------------------------------------------------
; Flash declaration depending on selected CPU

FlashDeclaration:
(
  PARAMETERS &param_dualport
  PRIVATE &FlashSize

  IF CPUIS("LPC54*J256*")
    &FlashSize=0x40000
  ELSE IF CPUIS("LPC54*J512*")
    &FlashSize=0x80000
  ELSE
  (
    PRINT %ERROR "FLASH size of CPU type is unknown"
    ENDDO
  )
  IF CPUIS("LPC5410*")
    &RamAddress=0x02000000
  ELSE IF (CPUIS("LPC5411*")||CPUIS("LPC546*"))
    &RamAddress=0x20000000
  ELSE
  (
    PRINT %ERROR "Ram address of CPU type is unknown"
    ENDDO
  )

  FLASH.Create 1. 0x00000000--(&FlashSize-1) 0x8000 TARGET Long

  IF (("&param_dualport"=="0")||SYStem.ACCESS.DENIED())
    FLASH.TARGET &RamAddress (&RamAddress+0x1000) 0x1000 ~~/demo/arm/flash/long/lpc5400.bin /STACKSIZE 0x200
  ELSE
    FLASH.TARGET E:&RamAddress (&RamAddress+0x1000) 0x1000 ~~/demo/arm/flash/long/lpc5400.bin /DualPort /STACKSIZE 0x200
  FLASH.CLocK.AUTO

  IF CPUIS("LPC546*")
  (
    ; Enable power for FRO, ROM and SRAM0 before programming flash
    FLASH.PROLOG.CONDition (Data.Long(ASD:0x40000610)&0x08024010)!=0x0
    FLASH.PROLOG.SEQuence.SET 0x40000630 %Long 0x08024010
    FLASH.PROLOG.ON
  )

  RETURN
)
