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;
}
|