3784 views|23 replies

50

Posts

0

Resources
The OP
 

About the story of Xiaobai writing bootloader [Copy link]

 

Preface: The following content is not guaranteed to be completely correct, but it is based on the author's practice and has undergone routine verification. It is better to have no book than to believe in it blindly. I hope that readers can read it with a skeptical attitude based on their own practice. Of course, the author also welcomes your suggestions for revision and pointing out the fallacies of this post. The author will correct them if there are any, and encourage them if there are none.

This post is from MCU

Latest reply

Can't the F series ferroelectric memory be read and written directly like SRAM?   Details Published on 2020-8-18 15:18
 

50

Posts

0

Resources
2
 
This post was last edited by luaffy on 2020-8-16 14:55

Background conditions:

Chip: MSP430F247 (minimum system)

Programming software: IAR

  • About Bootloader

To borrow a passage from Baidu Encyclopedia, it is as follows:

"In an embedded operating system, BootLoader runs before the operating system kernel runs. It can initialize hardware devices and establish memory space mapping, so as to bring the system's hardware and software environment to a suitable state, so as to prepare the correct environment for the final call to the operating system kernel. In embedded systems, there is usually no firmware program like BIOS (note, some embedded CPUs also have a short startup program embedded), so the loading and startup tasks of the entire system are completely completed by BootLoader. In an embedded system based on ARM7TDMI core, the system usually starts execution from address 0x00000000 when it is powered on or reset, and the system's BootLoader program is usually arranged at this address."

Its functions are summarized as follows: 1. Used to update user programs (hereinafter referred to as APP) through the serial port; 2. Stable storage in the microcontroller ("close to" solidification), clearly separated from the user program storage space; 3. Initialize hardware devices, such as IO ports. As for those "prepare RAM space", "kernel image", "root file system image", I don't need to worry about them for the time being, just do it.

The reason why I say "close to" solidification is that in my programming scheme, when the microcontroller runs the APP, you can enter the password to upgrade the Bootloader. The real solidification in the microcontroller, such as the BSL (also a bootloader) that comes with the 430, is fixed in a certain address of the 430 when it leaves the factory. It can be activated by sending a tool using the UART protocol command and cannot be erased.

In fact, of the two functions (1, 3) listed above, the bootloader written by the author cannot help the APP to complete the initialization work first. The reason is shown in the third point "About interrupt remapping".

This post is from MCU
 
 

50

Posts

0

Resources
3
 
This post was last edited by luaffy on 2020-8-16 15:08
  • About Partitions

The partition of bootloader is very interesting. Generally speaking, the microcontroller needs to be divided into two areas, one for bootloader and the other for APP. To partition the memory space, you must first know the memory address of the microcontroller. For the MSP430 series, you can mainly refer to the official TI " MIXED SIGNAL MICROCONTROLLER" document.

The memory addresses that need attention are: interrupt table: 0xFFFF-oxFFC0, code area: 0xFFFF-0x8000, the programmable code area is actually 0xFFBF-0x8000,

OK, now that we have the key information, let’s divide the regions into different areas, as shown in the figure below.

It's hard to read, right? I think so too! Open the compiler's memory window to see it clearly.

You can see that ④ is the hardware interrupt vector area, ③ is the user interrupt vector area, ② is the password area (used to determine whether to perform the upgrade operation), and ① is the bootloader interrupt vector area. These three interrupt vector areas can be placed together, which looks better, but why don't I place them together here? Because it's a done deal (not really), because I'm too lazy to change it.

After determining the addresses of each partition, you can modify the source xcl file to implement the partition. The source xcl file is generally in the IAR installation directory.

xcl file for bootloader

APP's xcl file

The main modifications are circled in red. The format of the xcl file is briefly explained as follows: (CONST) is generally used to store variable constants, (CODE) is used to store program codes, and the following two, INTVEC is the address where the interrupt vector is stored, and RESET is the reset vector.

After that, you need to modify the project configuration. Right-click the project >> options >> linker >> config, and enter the address of the modified xcl file in the linker configuration file box, or enter: $PROJ_DIR$\file name.xcl, which is the address of the current workspace.

Project Configuration

This is the end of the partitioning work.

This post is from MCU
 
 
 

7422

Posts

2

Resources
4
 

Come on, just do it.

This post is from MCU
 
Personal signature

默认摸鱼,再摸鱼。2022、9、28

 
 

50

Posts

0

Resources
5
 
This post was last edited by luaffy on 2020-8-17 12:22
  • About Interrupt Vector Table

What does it mean to create an interrupt vector table? Explain according to my understanding:

is what I write.

In order to make the flash screenshot at the bottom look better, I set up almost all interrupts, so there is a fully filled interrupt vector area as shown in Figure 3. This is a bad practice, please don't learn it, I suffered a great loss here, I will talk about it in detail later.

If the interrupt of the watchdog timer is not established, for example, the interrupt vector area of the xcl file will be FF, which corresponds to the interrupt vector of timer A1. In the bootloader and app programs of the example, the watchdog timer interrupt is not established, so the corresponding position is ff.

Here is another picture of the memory window:

Msp430f247.h hardware interrupt vector address

0xfff4 is the address of the watchdog timer in the hardware interrupt vector area

The address in the interrupt vector area points to the execution entry of the interrupt program. As shown in the figure above, we know that 0xfff0 is the address of the timer A1 interrupt vector. From the memory window, we can see that the data on 0xfff0 is 8628. Now let's look at the assembly window.

It can be seen that 8628 points to the timer A1 interrupt program entry.

In addition, the most important interrupt is the reset interrupt. The program generally only responds to the interrupt vector in the hardware interrupt vector area. When the power is turned on, the reset interrupt in the hardware interrupt vector area is run first. If the reset interrupt vector writes an error, it is easy to cause the microcontroller to crash.

If you want to do your work well, you must first sharpen your tools. After understanding interrupts, you will understand why you can perfectly run an APP with an interrupt program by simply copying the APP's interrupt vector area to the hardware interrupt vector area.

This is the last step. In the bootloader field, after the data file of the upgraded APP is received and written into the corresponding flash area, or if you want to jump to the APP directly, you can erase the interrupt vector area. Since the current hardware interrupt vector area stores the bootloader interrupt vector, in order not to lose the original bootloader interrupt vector, you must first write the hardware interrupt vector to the pre-opened bootloader interrupt vector area, and then write the APP interrupt vector to the hardware interrupt vector area. Similarly, in the APP field, if you want to return to the bootloader program area, you must save the interrupt vector in the hardware interrupt vector area back to the APP interrupt vector area, and write the bootloader interrupt vector to the hardware interrupt vector area.

It is said that you should try not to enable interrupts in the bootloader, but in the author's solution, you can use the bootloader interrupt, no problem, it's fine. Of course, it's not good to enable it randomly, so as to save some microcontroller resources.

This explains why the bootloader that uses this interrupt handling solution cannot perform global initialization. After the bootloader jumps to the APP, the hardware interrupt vector area has stored the APP interrupt vector. After the system is powered on again, it starts running from the APP reset vector address (currently 0xfffe) without going through the bootloader.

This post is from MCU
 
 
 

50

Posts

0

Resources
6
 
luaffy posted on 2020-8-16 17:09 About the interrupt vector table What does it mean to create an interrupt vector table? Explain according to the author's understanding -&mda ...

Why is there a picture at the bottom of this? It's so ugly.

This post is from MCU

Comments

It should be the picture you uploaded when you posted but didn't actually use.  Details Published on 2020-8-16 17:34
 
 
 

1w

Posts

204

Resources
7
 
luaffy posted on 2020-8-16 17:17 Why is there a picture at the bottom? It's so ugly

It should be the picture you uploaded when you posted but didn't actually use.

This post is from MCU
Add and join groups EEWorld service account EEWorld subscription account Automotive development circle
 
 
 

10

Posts

4

Resources
8
 

support

This post is from MCU
 
 
 

50

Posts

0

Resources
9
 
  • About Communication Protocol

This part of the author in the forum

https://en.eeworld.com/bbs/forum.php?mod=viewthread&tid=1136806&page=1#pid3001957 initiated a discussion.

To borrow the words of Mr. Chunyang (ID) - " Firmware updates must ensure sufficient reliability, and to ensure reliability, they cannot be simply sent directly and continuously in one direction. In that case, if one bit is wrong, the entire firmware will be scrapped, and it may even affect the next update, causing the device to be completely scrapped. This is absolutely not allowed. Therefore, when updating the firmware remotely, the reliability of the data must be guaranteed. In this way, the firmware must be broken into a series of small packets, packaged with a protocol, and strictly verified. Two-way communication is carried out using a session mechanism, and the frame length is limited to the system RAM size. For non-remote upgrades, when the possibility of errors in communication is greatly relaxed, the 9- bit mode of the serial port can be used, that is, sending by byte, parity check, but it must still be conversational. After a byte is programmed, a flag byte is returned, and the host computer / programmer sends the next byte. If the verification fails, a specific flag is returned and then resent. If it fails several times, an error reminder is given. This is a common process for remote updates and all ISP and IAP programming. "

Since the firmware update requires sufficient reliability, when the serial port receives the updated APPtxt file, it is necessary to formulate a communication protocol with strict verification, or use common communication protocols such as Ymodem/Xmodem.

This post is from MCU
 
 
 

50

Posts

0

Resources
10
 
This post was last edited by luaffy on 2020-8-17 12:48
  • About jump instructions

There is no essential difference between APP and bootloader except their functions and storage addresses. The process of updating APP and bootloader is highly consistent, and the two areas cannot "commit suicide". When updating APP, operations need to be performed in the bootloader code area, and when updating bootloader, operations need to be performed in the APP code area. The steps are as follows:

Partition bootloader and APP --> Create interrupts -->

Receive APP (bootloader) update data through the serial port --> write the received data to the corresponding APP (bootloader) program area in the flash --> save the bootloader (APP) interrupt vector in the hardware interrupt vector area, write the APP (bootloader) interrupt vector to the hardware interrupt vector area --> use the jump instruction to make the PC pointer jump to the app (bootloader) program area.

The jump instruction is usually in C language asm assembly embedded syntax: asm("mov &0xFFBE,pc;"); // 0xFFBE is the APP reset interrupt vector address

You can also use function pointers to jump: (*((void(*)())0xFFBE))();

I won’t go into detail because I’m not very familiar with it.

This post is from MCU
 
 
 

50

Posts

0

Resources
11
 
This post was last edited by luaffy on 2020-8-17 12:36
  • About Difficult Points (Updating)

There are always some setbacks when researching new things, but there are also achievements. Time is wasted, but only when you have a thorough understanding of something can you apply it to other situations in the future. If you follow the instructions step by step to complete the experiment, it is difficult to get any inspiration (for example, if I leave the C++ tutorial printed by the teacher to build a simple application, it is as if I have never taken this course).

The following is a list of the problems I encountered during the research phase. Each problem is marked with its current status: solved, on hold, or urgently needed. If you have a good explanation for the on hold or unresolved questions, I welcome your response.

This post is from MCU
 
 
 

50

Posts

0

Resources
12
 
This post was last edited by luaffy on 2020-8-17 12:47

1. The MCU crashes once the APP interrupt is triggered? (Solved)

This is the question I see most often online.

Here is a possibility - the value in the address pointed by the interrupt vector is the null value ff

When the PC pointer runs to an address according to the instruction of the interrupt vector to run the interrupt program, it is found that the content of the so-called interrupt program is the null value ff, and the pointer is lost. The lost pointer can only return to the reset interrupt vector and trigger a reset.

This post is from MCU
 
 
 

50

Posts

0

Resources
13
 

2. Why can't I just randomly create an interrupt vector table when writing a bootloader? (Solved)

I misunderstood the meaning on the Internet at the beginning of the construction, and wasted most of my time on this.

"Both the bootloader and the app need to set up the interrupt vector table separately..." After I set them up, I found a compilation error. The error message indicated that the interrupt area size was insufficient.

Modify the -Z(CODE)INTVEC=FF80-FFBF of the APP xcl file to FF7E-FF8F. The compilation was successful, but the subsequent interrupt response of the APP has always failed. Later I found out that when the interrupt vector was established, the reset interrupt was written in excess. The reset interrupt vector should be fixed in the program (guess). Under normal circumstances, the interrupt vector starts to be loaded from the first address (i.e. FF80) and ends at FFBF. So if the interrupt vector is loaded from FF7E, the normal interrupt vector address will generally increase the offset of two bytes. If the interrupt is not processed additionally, how can it be responded normally?

image.png (34.22 KB, downloads: 0)

image.png
This post is from MCU
 
 
 

50

Posts

0

Resources
14
 

3. Why can't the bootloader intercept all interrupts? (Put on hold)

One of my interrupt handling solutions is to create an interrupt vector only in the bootloader, and let the bootloader intercept all interrupts. After the interrupt is triggered, it is determined whether it is an app or bootloader interrupt based on the flag bit fixed in the flash. If it is an app interrupt, the jump instruction jumps to the corresponding address of the app for execution.

There is nothing wrong with the process, and the serial port receiving interrupt is also successfully tested. However, the timing interrupt response is abnormal and keeps resetting.

This post is from MCU
 
 
 

50

Posts

0

Resources
15
 

4. When it comes to hardware interrupt vectors, why are all subsequent addresses of the flash erased when the flash is erased? (Put on hold)

After the APP is updated, before jumping to the APP program area, you need to operate three interrupt vector areas.

The process is: ① The buffer reads the bootloader interrupt vector in the hardware interrupt vector area (FFC0-FFFF); ② Erase the bootloader interrupt vector area (FF00-FF3F); ③ Fill the bootloader interrupt vector area with the buffer content; ④ The buffer reads the APP interrupt vector in the APP interrupt vector area (FF80-FFBF); ⑤ Erase the hardware interrupt vector area; ⑥ Fill the hardware interrupt vector area with the buffer content.

The ideal is very good, but the reality is that when the second step is erased, the contents of FF00-FFFF have all been erased.

Although it is possible to read the contents of FF00-FFFF at one time and then change the order to fill them into the flash, I am still confused about the cause of the abnormal erasure above.

Additional content (2020-8-20 15:36): (Solved)
This post is from MCU
 
 
 

7422

Posts

2

Resources
16
 

>>>When the hardware interrupt vector is involved, why are all subsequent addresses of the flash erased when the flash is segmented?

Check the device manual to determine the specific erase size. I operated a chip some time ago, which said that each segment was 1K, but it could only erase 4K. Another chip said that it supported 4K, 32K, and 64K erasing, but it could only erase in units of 64K. I don't know why.

This post is from MCU
 
Personal signature

默认摸鱼,再摸鱼。2022、9、28

 
 

50

Posts

0

Resources
17
 
freebsder posted on 2020-8-17 22:28 >>>When it comes to hardware interrupt vectors, why are all subsequent addresses of the flash erased when the flash is segmented? Please check the device manual to confirm...

A segment has 64 bytes. The erase program is used to operate the A, B, C, and D segments. There have been no problems.

This post is from MCU
 
 
 

7422

Posts

2

Resources
18
 

Can't the F series ferroelectric memory be read and written directly like SRAM?

This post is from MCU
 
Personal signature

默认摸鱼,再摸鱼。2022、9、28

 
 

50

Posts

0

Resources
19
 
freebsder posted on 2020-8-18 15:18 Can't F series ferroelectric storage be directly read and written like SRAM?

Thanks for the advice

After experiments, the question was answered.

Reason: msp430f247, flash main memory is erased in 8 segments, 512 bytes at a time, and flash information memory is erased in one segment, 64 bytes at a time. The basis is as follows:

After testing, 2k of data was written to the flash, and a certain section in the middle was selected for erasure, and it can be seen that 512 bytes were erased.

This post is from MCU
 
 
 

50

Posts

0

Resources
20
 

Since the original solution was rejected , I will now share the second interrupt handling solution.

Option 1:

Open up two virtual interrupt vector areas (APP, bootloader) and one hardware interrupt vector area. Before jumping to APP, save the bootloader interrupt vector in the hardware interrupt vector area and write the APP interrupt vector into the hardware interrupt vector area.

Option 2:

Use __no_init to apply for RAM memory space and create a flag that cannot be initialized at power-on. The bootloader remaps the interrupt vector table.

When the interrupt is triggered, the interrupt service function (ISR) is entered. If the APP jump condition is met (the value of the flag is determined), the jump instruction jumps to the APP interrupt service function, that is, jumps to the address pointed to by the vector corresponding to the APP interrupt vector area, and executes the APP interrupt service function; if the condition is not met, the bootloader interrupt program is executed.

The advantages and disadvantages of both are obvious.

Advantages of Solution 1: Simple and straightforward, it avoids errors caused by interrupt remapping address transfer, and there is no coupling between APP and bootloader.

Disadvantages: Three interrupt vector areas need to be divided and operated - APP, bootloader, and hardware; the system is powered on without going through the bootloader. If the APP crashes, the bootloader loses the function of serial port maintenance for the APP; both app upgrades and bootloader updates require erasing the interrupt vector area, which increases the burden of erasing the flash.

Advantages of Solution 2: Only two interrupt vector areas are needed - hardware and APP; the system is powered on through the bootloader, and the bootloader code data is much smaller than the app, so it is not easy to crash; there is no need to erase the interrupt vector area multiple times

Disadvantages: The bootloader and app share a serial port interrupt, which increases the difficulty of programming. (Although the bootloader can send and receive data without serial port interrupt); the coupling degree between the app and the bootloader is high.

Additional content (2020-9-4 09:20): Some content is incorrect. The data defined by __no_init cannot be "not initialized by power-on". In any case, the data in RAM will be lost once the power is off. It should not be "reset initialized"
This post is from MCU
 
 
 

Guess Your Favourite
Just looking around
Find a datasheet?

EEWorld Datasheet Technical Support

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews

Room 1530, Zhongguancun MOOC Times Building, Block B, 18 Zhongguancun Street, Haidian District, Beijing 100190, China Tel:(010)82350740 Postcode:100190

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号
快速回复 返回顶部 Return list