| Hi, I'd like to know how to implement a dual core LPC4357 firmware upgrade using IAP. The aim is to upgrade m0 fw through M4, using IAP. 1) I create a *.bin file of the m0 code. Then I'v extrected the bytes needed for the upgrade and I've placed them into M4 code 2) using IAP from M4, I simply program FlashB, starting from sector 0 I tried this procedure but the m0 code doesn't start after the upgrade (and after an LPC4357 reset). Any sugegstions? Thanks Pietro | 
| 
int main(void) { //m0 core
int i;
const int time=500000;//10000=fast 500000=slow  //<<<<--- I just change this value to change the blinky frequency
#if defined (M0_SLAVE_PAUSE_AT_MAIN)
    // Pause execution until debugger attaches and modifies variable
    while (pause_at_main == 0) {}
#endif
    SystemCoreClockUpdate();
    Board_UART_Init(0);//needed, or it will not compile ..??..
// LED setup
//pin SODIMM-GPIO76=P9_0=GPIO4[12] pin 57 del J5
Chip_SCU_PinMuxSet(4, 12, SCU_MODE_FUNC0 | SCU_MODE_INACT);  //SCU_MODE_INACT disable pull up/down  // la SCU_MODE_FUNC0/1/2/.. la trovi sull'U.M. (User Manual)
  Chip_GPIO_SetPinDIROutput(LPC_GPIO_PORT, 4, 12);
    Chip_GPIO_SetPinOutHigh(LPC_GPIO_PORT,4, 12); //led high
  Chip_GPIO_SetPinOutLow(LPC_GPIO_PORT, 4, 12);//led low
    while(1) {
    for(i=0;i<time;i++);
    Chip_GPIO_SetPinOutHigh(LPC_GPIO_PORT, 4, 12); //led high
    for(i=0;i<time;i++);
Chip_GPIO_SetPinOutLow(LPC_GPIO_PORT, 4, 12);//led low
    }
    return 0 ;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
/// This code runs on PC to convert *.bin file into ascii *.h file
///////////////////////////////////////////////////////////////////////////////////////////////////
#include <stdio.h>
int main(int argc, char *argv[])
{
FILE *fpi, *fpo;
unsigned char v;
  if (argc < 3)
  {
    printf("USAGE: BINconvert <sourcefile.bin> <destfile.h>\n");
    return 0;
  }
  
  fpi = fopen(argv[1], "rb");
  if (fpi == 0)
  {
    printf("Cannot open file %s\n", argv[1]);
    return -1;
  }
  fpo = fopen(argv[2], "w");
  if (fpo == 0)
  {
    printf("Cannot create file %s\n", argv[2]);
    return -1;
  }
  
  fread(&v, 1, 1, fpi);
  while (!feof(fpi))
  {
    fprintf(fpo, "%d,\n", (int)v);
    fread(&v, 1, 1, fpi);
  }
  
  fclose(fpo);
  fclose(fpi);
  return 0;
}
 | 
| 
//*****************************************************************************
//   +--+
//   | ++----+
//   +-++    |
//     |     |
//   +-+--+  |
//   | +--+--+
//   +----+    Copyright (c) 2013 Code Red Technologies Ltd.
//
// cr_start_m0.c
//
// Provides function for CM4 'master' CPU in an NXP LPC43xx MCU to release
// CM0 'slave' CPUs from reset and begin executing.
//
// Version : 130410
//
// Software License Agreement
//
// The software is owned by Code Red Technologies and/or its suppliers, and is
// protected under applicable copyright laws.  All rights are reserved.  Any
// use in violation of the foregoing restrictions may subject the user to criminal
// sanctions under applicable laws, as well as to civil liability for the breach
// of the terms and conditions of this license.
//
// THIS SOFTWARE IS PROVIDED "AS IS".  NO WARRANTIES, WHETHER EXPRESS, IMPLIED
// OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
// USE OF THIS SOFTWARE FOR COMMERCIAL DEVELOPMENT AND/OR EDUCATION IS SUBJECT
// TO A CURRENT END USER LICENSE AGREEMENT (COMMERCIAL OR EDUCATIONAL) WITH
// CODE RED TECHNOLOGIES LTD.
//
//*****************************************************************************
#include "cr_start_m0.h"
// Provide defines for accessing peripheral registers necessary to release
// CM0 slave processors from reset. Note that this code does not use the
// CMSIS register access mechanism, as there is no guarantee that the
// project has been configured to use CMSIS.
#define RGU_RESET_CTRL1          (*((volatile uint32_t *) 0x40053104))
#define RGU_RESET_ACTIVE_STATUS1  (*((volatile uint32_t *) 0x40053154))
#define RGU_RESET_CTRL0          (*((volatile uint32_t *) 0x40053100))
#define RGU_RESET_ACTIVE_STATUS0  (*((volatile uint32_t *) 0x40053150))
#define CREG_M0APPMEMMAP        (*((volatile uint32_t *) 0x40043404))
#define CREG_M0SUBMEMMAP          (*((volatile uint32_t *) 0x40043308))
/*******************************************************************
 * Static function to Release SLAVE processor from reset
 *******************************************************************/
 void startSlave(uint32_t slavenum) {
volatile uint32_t u32REG, u32Val;
if (slavenum <= SLAVE_M0SUB) {
if (slavenum == SLAVE_M0APP) {
/* Release Slave from reset, first read status */
/* Notice, this is a read only register !!! */
u32REG = RGU_RESET_ACTIVE_STATUS1;
/* If the M0 is being held in reset, release it */
/* 1 = no reset, 0 = reset */
while (!(u32REG & (1u << 24))) {
u32Val = (~(u32REG) & (~(1 << 24)));
RGU_RESET_CTRL1 = u32Val;
u32REG = RGU_RESET_ACTIVE_STATUS1;
};
}
else { // (slavenum == SLAVE_M0SUB)
/* Release Slave from reset, first read status */
/* Notice, this is a read only register !!! */
u32REG = RGU_RESET_ACTIVE_STATUS0;
/* If the M0 is being held in reset, release it */
/* 1 = no reset, 0 = reset */
while (!(u32REG & (1u << 12))) {
u32Val = (~(u32REG) & (~(1 << 12)));
RGU_RESET_CTRL0 = u32Val;
u32REG = RGU_RESET_ACTIVE_STATUS0;
};
}
}
}
/*******************************************************************
 * Static function to put the SLAVE processor back in reset
 *******************************************************************/
 void haltSlave(uint32_t slavenum) {
volatile uint32_t u32REG, u32Val;
if (slavenum <= SLAVE_M0SUB) {
if (slavenum == SLAVE_M0APP) {
/* Check if M0 is reset by reading status */
u32REG = RGU_RESET_ACTIVE_STATUS1;
/* If the M0 has reset not asserted, halt it... */
/* in u32REG, status register, 1 = no reset */
while ((u32REG & (1u << 24))) {
u32Val = ((~u32REG) | (1 << 24));
RGU_RESET_CTRL1 = u32Val;
u32REG = RGU_RESET_ACTIVE_STATUS1;
}
} else { // (slavenum == SLAVE_M0SUB)
/* Check if M0 is reset by reading status */
u32REG = RGU_RESET_ACTIVE_STATUS0;
/* If the M0 has reset not asserted, halt it... */
/* in u32REG, status register, 1 = no reset */
while ((u32REG & (1u << 12))) {
u32Val = ((~u32REG) | (1 << 12));
RGU_RESET_CTRL0 = u32Val;
u32REG = RGU_RESET_ACTIVE_STATUS0;
}
}
}
}
/*******************************************************************
 * Function to start required CM0 slave cpu executing
 *******************************************************************/
void cr_start_m0(uint32_t slavenum, uint8_t *CM0image_start)  {
if (slavenum <= SLAVE_M0SUB) {
// Make sure M0 is not running
haltSlave(slavenum);
// Set M0's vector table to point to start of M0 image
if (slavenum == SLAVE_M0APP) {
CREG_M0APPMEMMAP = (uint32_t) CM0image_start;
} else { // (slavenum == SLAVE_M0SUB)
CREG_M0SUBMEMMAP = (uint32_t) CM0image_start;
}
// Release M0 from reset
startSlave(slavenum);
}
}
 | 
| 
int main(void) {
uint8_t result8=0;
    // Read clock settings and update SystemCoreClock variable
    SystemCoreClockUpdate();
    // Set up and initialize all required blocks and
    // functions related to the board hardware
    Board_Init();
    // Set the LED to the state of "On"
//    Board_LED_Set(0, true);
    // Start M0APP slave processor
#if defined (__MULTICORE_MASTER_SLAVE_M0APP)
    cr_start_m0(SLAVE_M0APP,&__core_m0app_START__);
#endif
    if(result8!=0){// it enters here only during debug...
//haltSlave(SLAVE_M0APP);//halt the slave ???
result8 = fw_upgrade_m0();//used to copy blinky.h file into Flash BankA in the traditional way. Routine from flash
 result8 += verify_fw_copy();//verify
 if(result8!=0){
 while(1);//error!
 }
    }
    while(1) {
    }
    return 0 ;
}
// we're copying fw upgrade data from .h file into flash bankB, starting from sector 0
uint8_t fw_upgrade_m0(void){
uint32_t sector_bankb_start_map[15];
uint32_t sector_bankb_end_map[15];
uint32_t fw_lenght, fw_index,sector_address;
int i;
uint8_t result8=0;
//Define start address of B Flash sector
sector_bankb_start_map[0]= 0x1B000000;
sector_bankb_start_map[1]= 0x1B002000;
sector_bankb_start_map[2]= 0x1B004000;
sector_bankb_start_map[3]= 0x1B006000;
sector_bankb_start_map[4]= 0x1B008000;
sector_bankb_start_map[5]= 0x1B00A000;
sector_bankb_start_map[6]= 0x1B00C000;
sector_bankb_start_map[7]= 0x1B00E000;
sector_bankb_start_map[8]= 0x1B010000;
sector_bankb_start_map[9]= 0x1B020000;
sector_bankb_start_map[10]=0x1B030000;
sector_bankb_start_map[11]=0x1B040000;
sector_bankb_start_map[12]=0x1B050000;
sector_bankb_start_map[13]=0x1B060000;
sector_bankb_start_map[14]=0x1B070000;
//Define end address of B Flash sector
sector_bankb_end_map[0]=0x1B001FFF;
sector_bankb_end_map[1]=0x1B003FFF;
sector_bankb_end_map[2]=0x1B005FFF;
sector_bankb_end_map[3]=0x1B007FFF;
sector_bankb_end_map[4]=0x1B009FFF;
sector_bankb_end_map[5]=0x1B00BFFF;
sector_bankb_end_map[6]=0x1B00DFFF;
sector_bankb_end_map[7]=0x1B00FFFF;
sector_bankb_end_map[8]=0x1B01FFFF;
sector_bankb_end_map[9]=0x1B02FFFF;
sector_bankb_end_map[10]=0x1B03FFFF;
sector_bankb_end_map[11]=0x1B04FFFF;
sector_bankb_end_map[12]=0x1B05FFFF;
sector_bankb_end_map[13]=0x1B06FFFF;
sector_bankb_end_map[14]=0x1B07FFFF;
Chip_IAP_Initialise();
uint32_t n_sector=STARTING_SECTOR_N;//we start writing data here, the first sector of bank B
 __disable_irq();
sector_address=sector_bankb_start_map[n_sector];
    result8 = Chip_IAP_PreSectorForReadWrite(n_sector, n_sector, 1); //sector 14(64KB) of flashBankB=1//prepare first
    result8+= Chip_IAP_EraseSector(n_sector, n_sector, 1);//erase first sector!
 fw_lenght=sizeof(new_firmware);
 fw_index=0;
 //scrivo 1024 dati da 32bit per volta. Dato che accedo a singoli byte, vuol dire che scrivo 1024*4 bytes per volta.
 while(fw_index<fw_lenght){
for(i=0;i<FLASH_DWORD_BLOCK;i++){ //filling 4k bytes into 1k dword
flash_data=(new_firmware[fw_index]<<24)|(new_firmware[fw_index+1]<<16)|(new_firmware[fw_index+2]<<8)|new_firmware[fw_index+3];//creating 32bit data
fw_index +=4;
if(!(fw_index<fw_lenght)){//last_iteration?
   for(i=i+1;i<FLASH_DWORD_BLOCK;i++) flash_data=0xFFFFFFFF;// fill with erased data
break;//fine del ciclo for
}
}
//storing data into flash
//prepare
//copy ram
result8 += Chip_IAP_PreSectorForReadWrite(n_sector, n_sector, 1); // flashBankA=0
    result8+= Chip_IAP_CopyRamToFlash(sector_address, flash_data, FLASH_BLOCK);//we have written 1024*4=4096bytes sulla flash
//ora cambia indirizzo su flash
sector_address +=FLASH_BLOCK;
if(!(sector_address<sector_bankb_end_map[n_sector])){//if needed, change sector
n_sector++; //new sector
if(!(n_sector<MAX_FLASH_SECTOR)){
//fail !!
}
sector_address=sector_bankb_start_map[n_sector];//new address
//nuovo settore:
//ret_val=(*longfunc_)(sector_number);//prepare
//ret_val +=(*longfunc2)(sector_number);//erase
    result8 += Chip_IAP_PreSectorForReadWrite(n_sector, n_sector, 1); //sector x of flashBankB=1//prepare first
    result8 += Chip_IAP_EraseSector(n_sector, n_sector, 1);//erase first sector!
}
 }
 __enable_irq();
 return result8;
}
 | 
