1 Introduction
Following the previous ADS simple program compilation analysis, we obtained a relatively independent compiled program creation method that can run on ucos ii. The following is to study how to update the user program to the high-level flash (the bottom level is the ucos ii program).
2 Code Description
Refer to the LPC2148 data sheet, LPC2148 supports IAP mode, that is, user programming mode. Refer to Zhou Ligong's AN070701, iap-yingyong.pdf and combine with the LPC21xx manual (Zhou Ligong's manual corresponds to LPC2300), and make your own programming function. The following is a detailed description:
First, referring to the data, the chip can call the IAP burning function by writing the corresponding command to the address 0x7FFFFFF1. The default process of powering on the chip to move the program code is not discussed here. Zhou Ligong's data explains how ARM switches to the THUMB instruction set working state:
The IAP program is Thumb code, located at address 0x7FFF FFF0. The instruction to implement state transition in the ARM system is "BX Addr". The lowest bit (bit0) of the target address Addr is only used to determine the final state. The actual "destination address = Addr & 0xFFFF FFFE".
In fact, the BX assembly command has been explained in the previous ADS simple program compilation analysis, that is, if the lowest bit of the jump instruction is 1, it will enter THUMB mode. Here, the command address is set to 0x7FFFFFF1 to enter THUMB mode. In fact, it jumps to 0x7FFFFFF0.
Here you need to set the ARM/Thumb Interworking under the ATPCS tab in the ARM C Compiler of ADS, otherwise the state cannot be switched and IAP cannot be executed.
There is such a macro definition in ucos ii:
#define iap_entry(a, b) ((void (*)())(0x7ffffff1))(a, b)
1
That is, the entry point for calling IAP in the form of a function.
The user manual of LPC21XXX states that when jumping to 0x7FFFFFF1, r0 stores the address of the command array and r1 stores the address of the return value array. In C language, it is agreed that the first parameter of a function call is stored in r0 and the second parameter is stored in r1, so an IAP call can be implemented in the following way:
static unsigned long command[5], result[3];
unsigned long IAP_PREPARE(unsigned long start, unsigned long end)
{
OS_ENTER_CRITICAL();
command[0] = IAP_PREPARE_SECTOR;
command[1] = start;
command[2] = end;
iap_entry(command, result);
OS_EXIT_CRITICAL();
return result[0];
}
In this example, the command array is the command array passed to r0, and r1 is the command array that receives the results. In C language, the array name is the address. OS_ENTER_CRITICAL() is to let ucos ii disable interrupts, because it cannot be interrupted during the burning process, otherwise an error will occur. If you do not use ucos, you can do without these commands. In the command array, the corresponding functions of the corresponding array members are agreed upon. For details, please refer to the LPC21XXX user manual.
Before burning or erasing a sector, you must use a command to prepare the corresponding sector. That is, the code of the above program. However, the flash sectors of ARM are not of equal length. Referring to the data sheet, the following code can return the corresponding sector number through the address. Other chips can also modify it in the same way:
/*********************************
** Function name: get_sector
** Function: Calculate the sector number where the address is located.
** Entry parameter: addr address
** Export parameter: sector sector number
**********************************/
static int get_sector(unsigned int addr)
{
if(addr <= 0x000fff) return 0;
if(addr <= 0x001fff) return 1;
if(addr <= 0x002fff) return 2;
if(addr <= 0x003fff) return 3;
if(addr <= 0x004fff) return 4;
if(addr <= 0x005fff) return 5;
if(addr <= 0x006fff) return 6;
if(addr <= 0x007fff) return 7;
if(addr <= 0x00ffff) return 8;
if(addr <= 0x017fff) return 9;
if(addr <= 0x01ffff) return 10;
if(addr <= 0x027fff) return 11;
if(addr <= 0x02ffff) return 12;
if(addr <= 0x037fff) return 13;
if(addr <= 0x03ffff) return 14;
if(addr <= 0x047fff) return 15;
if(addr <= 0x04ffff) return 16;
if(addr <= 0x057fff) return 17;
if(addr <= 0x05ffff) return 18;
if(addr <= 0x067fff) return 19;
if(addr <= 0x06ffff) return 20;
if(addr <= 0x077fff) return 21;
if(addr <= 0x078fff) return 22;
if(addr <= 0x079fff) return 23;
if(addr <= 0x07afff) return 24;
if(addr <= 0x07bfff) return 25;
if(addr <= 0x07cfff) return 26;
return 0xff;
}
This design implements three functions of IAP, namely prepare sector, erase sector, and write sector. The following are the descriptions:
2.1 Prepare sector function:
/******************************************************************************************
** Function name: IAP_PREPARE
** Function: IAP operation buffer selection, code is 50.
** Entry parameter: start starting sector
** end end sector
** Export parameter: IAP operation status code
** IAP return value (result buffer)
******************************************************************************************/
unsigned long IAP_PREPARE(unsigned long start, unsigned long end)
{
OS_ENTER_CRITICAL();
command[0] = IAP_PREPARE_SECTOR;
command[1] = start;
command[2] = end;
iap_entry(command, result);
OS_EXIT_CRITICAL();
return result[0];
}
If the returned code is not 0, it indicates an error. For the specific meaning, please refer to the data manual.
2.2 Erase sector function:
/******************************************************************************************
** Function name: EraseSector
** Function: Erase sector, command code 52.
** Entry parameter: start starting sector
** end end sector
** Export parameter: IAP operation status code
** IAP return value (result buffer)
******************************************************************************************/
unsigned long IAP_ERASER(unsigned long start,unsigned long end)
{
OS_ENTER_CRITICAL();
command[0] = IAP_ERASE_SECTOR; // Set command word
command[1] = start; // Set parameters
command[2] = end;
command[3] = IAP_FCCLK;
iap_entry(command, result); // Call IAP service program
OS_EXIT_CRITICAL();
return(result[0]); // Return status code
}
The FCCLK here needs to be modified according to the chip settings, and the unit is KHz.
2.3 Write sector function
/******************************************************************************************
** Function name: IAP_COPY
** Function: Copy RAM data to FLASH, command code 51.
** Entry parameters: dst destination address, i.e. FLASH start address, with 256 bytes as the boundary
** src source address, that is, RAM address, the address must be word-aligned
** no The number of bytes to copy is 256/512/1024/4096
** Export parameter: IAP operation status code
** IAP return value (result buffer)
******************************************************************************************/
unsigned long IAP_COPY(unsigned long dst, unsigned long src, unsigned long no)
{
OS_ENTER_CRITICAL();
command[0] = IAP_COPY_RAM_TO_FLASH;
command[1] = dst;
command[2] = src;
command[3] = no;
command[4] = IAP_FCCLK;
iap_entry(command, result);
OS_EXIT_CRITICAL();
return(result[0]); // Return status code
}
The FCCLK here needs to be modified according to the chip settings, and the unit is KHz.
In addition, it should be noted that the function of writing sectors does not write the entire sector at once, but can be repeatedly written to multiple locations in segments, such as writing the first 256 bytes for the first time, and then continuing to write 1024 bytes again. It only needs to comply with the address alignment requirements and the number of words written to be a multiple of 256. In addition, it is stated in the reference that the content to be burned in the memory must be in the on-chip RAM. In my application, all variable definitions are in RAM without any problems. If there is off-chip memory or other on-chip space such as the USB stack is used, this needs to be noted.
3 Appendix
Below is the complete IAP function file:
#define iap_entry(a, b) ((void (*)())(0x7ffffff1))(a, b)
#define IAP_PREPARE_SECTOR 50
#define IAP_COPY_RAM_TO_FLASH 51
#define IAP_ERASE_SECTOR 52
#define IAP_FCCLK Fcclk / 1000; //(fill in your own main frequency)
/******************************************************************************************
** Function name: IAP_PREPARE
** Function: IAP operation buffer selection, code is 50.
** Entry parameter: start starting sector
** end end sector
** Export parameter: IAP operation status code
** IAP return value (result buffer)
******************************************************************************************/
static unsigned long command[5], result[3];
unsigned long IAP_PREPARE(unsigned long start, unsigned long end)
{
OS_ENTER_CRITICAL();
command[0] = IAP_PREPARE_SECTOR;
command[1] = start;
command[2] = end;
iap_entry(command, result);
OS_EXIT_CRITICAL();
return result[0];
}
/******************************************************************************************
** Function name: EraseSector
** Function: Erase sector, command code 52.
** Entry parameter: start starting sector
** end end sector
** Export parameter: IAP operation status code
** IAP return value (result buffer)
******************************************************************************************/
unsigned long IAP_ERASER(unsigned long start,unsigned long end)
{
OS_ENTER_CRITICAL();
command[0] = IAP_ERASE_SECTOR; // Set command word
command[1] = start; // Set parameters
command[2] = end;
command[3] = IAP_FCCLK;
iap_entry(command, result); // Call IAP service program
OS_EXIT_CRITICAL();
return(result[0]); // Return status code
}
/******************************************************************************************
Previous article:LPC2138 startup.s
Next article:A brief analysis of embedded MCU hardware design solutions
- Popular Resources
- Popular amplifiers
- Learn ARM development(16)
- Learn ARM development(17)
- Learn ARM development(18)
- Embedded system debugging simulation tool
- A small question that has been bothering me recently has finally been solved~~
- Learn ARM development (1)
- Learn ARM development (2)
- Learn ARM development (4)
- Learn ARM development (6)
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- LED chemical incompatibility test to see which chemicals LEDs can be used with
- Application of ARM9 hardware coprocessor on WinCE embedded motherboard
- What are the key points for selecting rotor flowmeter?
- LM317 high power charger circuit
- A brief analysis of Embest's application and development of embedded medical devices
- Single-phase RC protection circuit
- stm32 PVD programmable voltage monitor
- Introduction and measurement of edge trigger and level trigger of 51 single chip microcomputer
- Improved design of Linux system software shell protection technology
- What to do if the ABB robot protection device stops
- Analysis of the application of several common contact parts in high-voltage connectors of new energy vehicles
- Wiring harness durability test and contact voltage drop test method
- From probes to power supplies, Tektronix is leading the way in comprehensive innovation in power electronics testing
- From probes to power supplies, Tektronix is leading the way in comprehensive innovation in power electronics testing
- Sn-doped CuO nanostructure-based ethanol gas sensor for real-time drunk driving detection in vehicles
- Design considerations for automotive battery wiring harness
- Do you know all the various motors commonly used in automotive electronics?
- What are the functions of the Internet of Vehicles? What are the uses and benefits of the Internet of Vehicles?
- Power Inverter - A critical safety system for electric vehicles
- Analysis of the information security mechanism of AUTOSAR, the automotive embedded software framework
- How to use LM337 to generate negative voltage
- Newbie help, what is this thing?
- [ESP32-S2-Kaluga-1 Review] Running ESP32 Four Bitter B Test
- Please advise, what software is used for microcontroller simulation?
- What is the difference between the on and off of a dip switch?
- "Playing with the board" + Zhou Hangci's book Chapter 6, Example 2
- STM32CubeMX uses LL library to set timer to use external clock mode to control gpio flip
- Uncle Cat's FPGA Timing Constraint Tutorial
- Where did the official website of lattice's Adder_Subtractor put its IP information? I spent the whole afternoon searching but couldn't find it.
- About the serial port receiving problem of stm32f4