This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Hi,
I am writting a custom bootloader and to manage this I have to create a secondary interrupt table within the application space. Basically, the bootloader would get the 'real' interrupt table. So interrupts would breifly go through this real table, and be passed on to the application code (if valid) to via the interrupt talbe within the application code space..
My new table would be located into an other segment from 0xF0C0 to 0xF0FF
I don't succeed to get my interrupt to work at all so If someone have already achieved to do that I would please to know how.
MCU: MSP430F47166
SW: CCS v4
the linker file:
MEMORY
{
SFR : origin = 0x0000, length = 0x0010
PERIPHERALS_8BIT : origin = 0x0010, length = 0x00F0
PERIPHERALS_16BIT : origin = 0x0100, length = 0x0100
RAM : origin = 0x1100, length = 0x1000
INFOA : origin = 0x10C0, length = 0x0040
INFOB : origin = 0x1080, length = 0x0040
INFOC : origin = 0x1040, length = 0x0040
INFOD : origin = 0x1000, length = 0x0040
/* FLASH : origin = 0x2B00, length = 0xD2C0 /* TAILLE CODE = 53952o + 64o (IT vector) */
FLASH : origin = 0x2B00, length = 0xC2C0 /* TAILLE CODE = 549856o + 64o (IT vector) */
INT00 : origin = 0xF0C0, length = 0x0002 /* Image de la table des vecteurs situé à 0xFDC0 */
INT01 : origin = 0xF0C2, length = 0x0002
INT02 : origin = 0xF0C4, length = 0x0002
INT03 : origin = 0xF0C6, length = 0x0002
INT04 : origin = 0xF0C8, length = 0x0002
INT05 : origin = 0xF0CA, length = 0x0002
INT06 : origin = 0xF0CC, length = 0x0002
INT07 : origin = 0xF0CE, length = 0x0002
INT08 : origin = 0xF0D0, length = 0x0002
INT09 : origin = 0xF0D2, length = 0x0002
INT10 : origin = 0xF0D4, length = 0x0002
INT11 : origin = 0xF0D6, length = 0x0002
INT12 : origin = 0xF0D8, length = 0x0002
INT13 : origin = 0xF0DA, length = 0x0002
INT14 : origin = 0xF0DC, length = 0x0002
INT15 : origin = 0xF0DE, length = 0x0002
INT16 : origin = 0xF0E0, length = 0x0002
INT17 : origin = 0xF0E2, length = 0x0002
INT18 : origin = 0xF0E4, length = 0x0002
INT19 : origin = 0xF0E6, length = 0x0002
INT20 : origin = 0xF0E8, length = 0x0002
INT21 : origin = 0xF0EA, length = 0x0002
INT22 : origin = 0xF0EC, length = 0x0002
INT23 : origin = 0xF0EE, length = 0x0002
INT24 : origin = 0xF0F0, length = 0x0002
INT25 : origin = 0xF0F2, length = 0x0002
INT26 : origin = 0xF0F4, length = 0x0002
INT27 : origin = 0xF0F6, length = 0x0002
INT28 : origin = 0xF0F8, length = 0x0002
INT29 : origin = 0xF0FA, length = 0x0002
INT30 : origin = 0xF0FC, length = 0x0002
INT000 : origin = 0xFFC0, length = 0x0002, fill = 0xF0C0
INT010 : origin = 0xFFC2, length = 0x0002, fill = 0xF0C2
INT020 : origin = 0xFFC4, length = 0x0002, fill = 0xF0C4
INT030 : origin = 0xFFC6, length = 0x0002, fill = 0xF0C6
INT040 : origin = 0xFFC8, length = 0x0002, fill = 0xF0C8
INT050 : origin = 0xFFCA, length = 0x0002, fill = 0xF0CA
INT060 : origin = 0xFFCC, length = 0x0002, fill = 0xF0CC
INT070 : origin = 0xFFCE, length = 0x0002, fill = 0xF0CE
INT080 : origin = 0xFFD0, length = 0x0002, fill = 0xF0D0
INT090 : origin = 0xFFD2, length = 0x0002, fill = 0xF0D2
INT100 : origin = 0xFFD4, length = 0x0002, fill = 0xF0D4
INT110 : origin = 0xFFD6, length = 0x0002, fill = 0xF0D6
INT120 : origin = 0xFFD8, length = 0x0002, fill = 0xF0D8
INT130 : origin = 0xFFDA, length = 0x0002, fill = 0xF0DA
INT140 : origin = 0xFFDC, length = 0x0002, fill = 0xF0DC
INT150 : origin = 0xFFDE, length = 0x0002, fill = 0xF0DE
INT160 : origin = 0xFFE0, length = 0x0002, fill = 0xF0E0
INT170 : origin = 0xFFE2, length = 0x0002, fill = 0xF0E2
INT180 : origin = 0xFFE4, length = 0x0002, fill = 0xF0E4
INT190 : origin = 0xFFE6, length = 0x0002, fill = 0xF0E6
INT200 : origin = 0xFFE8, length = 0x0002, fill = 0xF0E8
INT210 : origin = 0xFFEA, length = 0x0002, fill = 0xF0EA
INT220 : origin = 0xFFEC, length = 0x0002, fill = 0xF0EC
INT230 : origin = 0xFFEE, length = 0x0002, fill = 0xF0EE
INT240 : origin = 0xFFF0, length = 0x0002, fill = 0xF0F0
INT250 : origin = 0xFFF2, length = 0x0002, fill = 0xF0F2
INT260 : origin = 0xFFF4, length = 0x0002, fill = 0xF0F4
INT270 : origin = 0xFFF6, length = 0x0002, fill = 0xF0F6
INT280 : origin = 0xFFF8, length = 0x0002, fill = 0xF0F8
INT290 : origin = 0xFFFA, length = 0x0002, fill = 0xF0FA
INT300 : origin = 0xFFFC, length = 0x0002, fill = 0xF0FC
RESET : origin = 0xFFFE, length = 0x0002
}
/****************************************************************************/
/* SPECIFY THE SECTIONS ALLOCATION INTO MEMORY */
/****************************************************************************/
SECTIONS
{
.bss : {} > RAM /* GLOBAL & STATIC VARS */
.sysmem : {} > RAM /* DYNAMIC MEMORY ALLOCATION AREA */
.stack : {} > RAM (HIGH) /* SOFTWARE SYSTEM STACK */
.text : {}>> FLASH | FLASH2 /* CODE */
.text:_isr : {} > FLASH /* ISR CODE SPACE */
.cinit : {} > FLASH /* INITIALIZATION TABLES */
.const : {} > FLASH | FLASH2 /* CONSTANT DATA */
.cio : {} > RAM /* C I/O BUFFER */
.pinit : {} > FLASH /* C++ CONSTRUCTOR TABLES */
.infoA : {} > INFOA /* MSP430 INFO FLASH MEMORY SEGMENTS */
.infoB : {} > INFOB
.infoC : {} > INFOC
.infoD : {} > INFOD
.int_00 : {} > INT00 /* MSP430 INTERRUPT VECTORS */
.int_01 : {} > INT01
.int_02 : {} > INT02
.int_03 : {} > INT03
.int_04 : {} > INT04
.int_05 : {} > INT05
.int_06 : {} > INT06
.int_07 : {} > INT07
.int_08 : {} > INT08
.int_09 : {} > INT09
.int_10 : {} > INT10
.int_11 : {} > INT11
.int_12 : {} > INT12
.int_13 : {} > INT13
.int_14 : {} > INT14
.int_15 : {} > INT15
.int_16 : {} > INT16
.int_17 : {} > INT17
.int_18 : {} > INT18
.int_19 : {} > INT19
.int_20 : {} > INT20
.int_21 : {} > INT21
.int_22 : {} > INT22
.int_23 : {} > INT23
.int_24 : {} > INT24
.int_25 : {} > INT25
.int_26 : {} > INT26
.int_27 : {} > INT27
.int_28 : {} > INT28
.int_29 : {} > INT29
.int_30 : {} > INT30
.int00 : {} > INT000 /* MSP430 INTERRUPT VECTORS */
.int01 : {} > INT010
.int02 : {} > INT020
.int03 : {} > INT030
.int04 : {} > INT040
.int05 : {} > INT050
.int06 : {} > INT060
.int07 : {} > INT070
.int08 : {} > INT080
.int09 : {} > INT090
.int10 : {} > INT100
.int11 : {} > INT110
.int12 : {} > INT120
.int13 : {} > INT130
.int14 : {} > INT140
.int15 : {} > INT150
.int16 : {} > INT160
.int17 : {} > INT170
.int18 : {} > INT180
.int19 : {} > INT190
.int20 : {} > INT200
.int21 : {} > INT210
.int22 : {} > INT220
.int23 : {} > INT230
.int24 : {} > INT240
.int25 : {} > INT250
.int26 : {} > INT260
.int27 : {} > INT270
.int28 : {} > INT280
.int29 : {} > INT290
.int30 : {} > INT300
.reset : {} > RESET /* MSP430 RESET VECTOR */
}
I tried to manipulate my c file
#pragama void function(void)
#pragama CODE_SECTIONS(function,address) // New interrupt vector Address
_interrupt void function(void)
Hi Emilien,
Did you check out app-note SLAA341 regarding a flash-based UART bootloader? It mirrors the interrupt vector table into the "application" space at a new segment. The bootloader uses the actual vectors and remaps them to the application space. Only caveat is that the app-note was written for IAR. But is should be straight-forward to convert to CCS (maybe the TI guys can revise the app-note source files for CCS too, if they are listening).
Link: http://focus.ti.com/general/docs/litabsmultiplefilelist.tsp?literatureNumber=slaa341
Good Luck and Regards,
Gene M.
Doing what you want requires some effort.
First, you'll need the original vector table point to a jumptable. You cannot point from the original table into your own table directly, as the processor expects CODE it can execute, not just another vector.
I don't know how (or if at all) inline assembly works on CCE or IAR. What you need is an ISR (one for each vector entry!) which has no entry code and jumps directly or indirectly to the real ISR.
Example:
0xf0c0 .DW 0x8000 (address of your ISR)
0xfc00 JMP &0xfc0c (indirect jump to the address stored at 0xf0c0)
0xffc0 .DW 0xfc00 ('fake' vector pointing to the jump)
Stuffing the real vector table with the addresses of the jump(s) can be done by NEVER using the #pragma vector anywhere and assigning function pointer variables to the proper sections as listed in the linker command file. I don't know the CCE/IAR syntax for defining the destination segment of a variable.
The critical part is placing the jumps where they belong - and creating the jumps at all.
On some MSPs, you can redirect the vector table to the end of RAM instead of the end of ROM. This only requires copying the new vector table to RAM, reserving the end of ram (so it isn't used for stack) and switching the control bit. Then you don't need the jumps. It is, however, a bit risky to have the interrupt vectors in ram.
Hi,
To accomplish this, it requires a custom command linker file and an assembly level code. We have a code example that was developed for F5419 devices. However, this code can easily be ported to F47166 device. It contains both code example for IAR and CCS too.
Give it a try and let us know if you find any issues using this package.
Regards,
William
I tried your code example and maked it compatible for the F47166, it works
Thanks to all of you for your help
It is my second try on TI E2E and I am very satisfied of speed and answer's qualities.
Emilien
Hello there,
refering to the project Custom ISR Structure, I had modified my project to relocated my interrupt at 0x8BE0 to 0x8BFF. I had modified the interrupt proxy.asm for the interrupt of the MSP430FG477 and the .cmd. It has build, but I am not able to run the software on debug. Here the message of CCS V4:
MSP430: Can't Run Target CPU: Could not run device (to breakpoint)
I imaging that I did something wrong in my modification. Here my .cmd
MEMORY
{
SFR : origin = 0x0000, length = 0x0010
PERIPHERALS_8BIT : origin = 0x0010, length = 0x00F0
PERIPHERALS_16BIT : origin = 0x0100, length = 0x0100
RAM : origin = 0x0200, length = 0x0400
INFOA : origin = 0x10C0, length = 0x0040
INFOB : origin = 0x1080, length = 0x0040
INFOC : origin = 0x1040, length = 0x0040
INFOD : origin = 0x1000, length = 0x0040
FLASH : origin = 0x8000, length = 0x0A00
/* Reserved segment definition for the main program's interrupt vectors,* reset vector, branch vectors. */
BRINTVEC : origin = 0xFE00, length = 0x180
/* Relocated segment definition for interrupt vectors / reset vector. */
INT00 : origin = 0x8BE0, length = 0x0002
INT01 : origin = 0x8BE2, length = 0x0002
INT02 : origin = 0x8BE4, length = 0x0002
INT03 : origin = 0x8BE6, length = 0x0002
INT04 : origin = 0x8BE8, length = 0x0002
INT05 : origin = 0x8BEA, length = 0x0002
INT06 : origin = 0x8BEC, length = 0x0002
INT07 : origin = 0x8BEE, length = 0x0002
INT08 : origin = 0x8BF0, length = 0x0002
INT09 : origin = 0x8BF2, length = 0x0002
INT10 : origin = 0x8BF4, length = 0x0002
INT11 : origin = 0x8BF6, length = 0x0002
INT12 : origin = 0x8BF8, length = 0x0002
INT13 : origin = 0x8BFA, length = 0x0002
INT14 : origin = 0x8BFC, length = 0x0002
RESET : origin = 0x8BFE, length = 0x0002
/* Reserved main interrupt vectors space. */
MAININTVEC : origin = 0xFF80, length = 0x0080
}
/****************************************************************************/
/* SPECIFY THE SECTIONS ALLOCATION INTO MEMORY */
/****************************************************************************/
SECTIONS
{
.bss : {} > RAM /* GLOBAL & STATIC VARS */
.sysmem : {} > RAM /* DYNAMIC MEMORY ALLOCATION AREA */
.stack : {} > RAM (HIGH) /* SOFTWARE SYSTEM STACK */
.text : {} > FLASH /* CODE */
.text:_isr : {} > FLASH /* ISR CODE SPACE */
.cinit : {} > FLASH /* INITIALIZATION TABLES */
.const : {} > FLASH /* CONSTANT DATA */
.cio : {} > RAM /* C I/O BUFFER */
.pinit : {} > FLASH /* C++ CONSTRUCTOR TABLES */
.infoA : {} > INFOA /* MSP430 INFO FLASH MEMORY SEGMENTS */
.infoB : {} > INFOB
.infoC : {} > INFOC
.infoD : {} > INFOD
.mainintvec : {} > MAININTVEC /* MAIN PROGRAM INT VECTOR TABLE */
.brintvec : {} > BRINTVEC /* BRANCH INST PROGRAM INT VECTOR TABLE */
.int00 : {} > INT00 /* MSP430 INTERRUPT VECTORS */
.int01 : {} > INT01
.int02 : {} > INT02
.int03 : {} > INT03
.int04 : {} > INT04
.int05 : {} > INT05
.int06 : {} > INT06
.int07 : {} > INT07
.int08 : {} > INT08
.int09 : {} > INT09
.int10 : {} > INT10
.int11 : {} > INT11
.int12 : {} > INT12
.int13 : {} > INT13
.int14 : {} > INT14
.reset : {} > RESET /* MSP430 RESET VECTOR */
}
/****************************************************************************/
/* INCLUDE PERIPHERALS MEMORY MAP */
/****************************************************************************/
-l msp430xG47x.cmd
and the interrupt proxy.asm :
;-------------------------------------------------------------------------------
; The following code section is used to define variables to allow
; accessing the interrupt vectors which are defined by the main program.
;-------------------------------------------------------------------------------
BASICTIMER_PROXY .equ 0x8BE0 ; 0x8BE0 Basic Timer
PORT2_PROXY .equ 0x8BE2 ; 0x8BE2 Port 2
; 0x8BE4 None
DAC12_PROXY .equ 0x8BE6 ; 0x8BE6 DAC
PORT1_PROXY .equ 0x8BE8 ; 0x8BE8 Port 1
TIMERA1_PROXY .equ 0x8BEA ; 0x8BEA Timer A CC1-2, TA
TIMERA0_PROXY .equ 0x8BEC ; 0x8BEC Timer A CC0
SD16A_PROXY .equ 0x8BEE ; 0x8BEE ADC SD16A
USCIAB0TX_PROXY .equ 0x8BF0 ; 0x8BF0 USCI A0/B0 Transmit
USCIAB0RX_PROXY .equ 0x8BF2 ; 0x8BF2 USCI A0/B0 Receive
WDT_PROXY .equ 0x8BF4 ; 0x8BF4 Watchdog Timer
COMPARATORA_PROXY .equ 0x8BF6 ; 0x8BF6 Comparator A
TIMERB1_PROXY .equ 0x8BF8 ; 0x8BF8 Timer B CC1-2, TB
TIMERB0_PROXY .equ 0x8BFA ; 0x8BFA Timer B CC0
NMI_PROXY .equ 0x8BFC ; 0x8BFC Non-maskable
RESET_PROXY .equ 0x8BFE ; 0x8BFE Reset vector
.cdecls C,LIST, "msp430xG47x.h"
;-------------------------------------------------------------------------------
; The following code section contains the actual ISR implementation
; for all possible MSP430F5419 interrupt sources. All that is being done
; here is an indirect jump to the address that is stored in the
; main program's virtual interrupt vector table. Other than a 5 CPU
; cycle overhead added to each ISR call, there are no side effects of
; doing this.
; Also, interrupt vectors not implemented on the device are trapped and
; not forwarded to the main program.
;-------------------------------------------------------------------------------
.sect ".brintvec" ; Assemble to branch interrupt
; memory
;-------------------------------------------------------------------------------
BASICTIMER_ISR BR &BASICTIMER_PROXY ; Indirect jump using proxy
PORT2_ISR BR &PORT2_PROXY ; Indirect jump using proxy
DAC12_ISR BR &DAC12_PROXY ; Indirect jump using proxy
PORT1_ISR BR &PORT1_PROXY ; Indirect jump using proxy
TIMERA1_ISR BR &TIMERA1_PROXY ; Indirect jump using proxy
TIMERA0_ISR BR &TIMERA0_PROXY ; Indirect jump using proxy
SD16A_ISR BR &SD16A_PROXY ; Indirect jump using proxy
USCIAB0TX_ISR BR &USCIAB0TX_PROXY ; Indirect jump using proxy
USCIAB0RX_ISR BR &USCIAB0RX_PROXY ; Indirect jump using proxy
WDT_ISR BR &WDT_PROXY ; Indirect jump using proxy
COMPARATORA_ISR BR &COMPARATORA_PROXY ; Indirect jump using proxy
TIMERB1_ISR BR &TIMERB1_PROXY ; Indirect jump using proxy
TIMERB0_ISR BR &TIMERB0_PROXY ; Indirect jump using proxy
NMI_ISR BR &NMI_PROXY ; Indirect jump using proxy
RESET_ISR BR &RESET_PROXY ; Indirect jump using proxy
;-------------------------------------------------------------------------------
; The following code section populates the actual MSP430F5419 interrupt
; vectors to point to code sections within the boot loader code. In these
; code sections, an indirect jump is performed and with this the interrupt
; requests are routed to the main program.
;-------------------------------------------------------------------------------
.sect ".mainintvec"
.word BASICTIMER_ISR ; 0x8BE0 Basic Timer
.word PORT2_ISR ; 0x8BE2 Port 2
.word DAC12_ISR ; 0x8BE6 DAC
.word PORT1_ISR ; 0x8BE8 Port 1
.word TIMERA1_ISR ; 0x8BEA Timer A CC1-2, TA
.word TIMERA0_ISR ; 0x8BEC Timer A CC0
.word SD16A_ISR ; 0x8BEE ADC SD16A
.word USCIAB0TX_ISR ; 0x8BF0 USCI A0/B0 Transmit
.word USCIAB0RX_ISR ; 0x8BF2 USCI A0/B0 Receive
.word WDT_ISR ; 0x8BF4 Watchdog Timer
.word COMPARATORA_ISR ; 0x8BF6 Comparator A
.word TIMERB1_ISR ; 0x8BF8 Timer B CC1-2, TB
.word TIMERB0_ISR ; 0x8BFA Timer B CC0
.word NMI_ISR ; 0x8BFC Non-maskable
.word RESET_ISR ; 0x8BFE Reset vector
;-------------------------------------------------------------------------------
.end
Thank for any help!
Maxime Tardif
I'm a bit puzzled about the memory usage.
Flash begins at 0x8000 and ends at 0xffff. You have a fixed content @0xffe0, but the flash segment where it is in begins at 0xfe00. So why don't you put your branch code there too, as it is also static. And move the application interrupt vectors to 0xfd80, the end of application flash.
Also, if you make the tables as large as possible, you can make it MSP independent.vector table and the branches don't care for the interrupt they are serving. So if you code straight down from 0xfffe, it will fit any device.
Actually, there was no need to modify the original ASM file at all. Only the CMD file.
Teh message 'cannot run device (to breakpoint)' usually means that the debugger has set an automatic breakpoint at main but the code never comes there. However, I don't see why this happens. YOu should do a memory dump (in the debugger?) and see whether things are where you expect them.
Hello,
thanks for fast answers! It might be a little confused the way that I have present my problem.
I'm doing a boot loader and a main application, in two project (as it been advice in many post of TI E2E). The .cmd presented was the boot loader software at 0x8000 to 0x89FF.I wanted to relocated interrupt of the bootloader in segment 0x8A00 to 0x8BFF. The main application is at 0x8C00 to the end (0xFE00).
I was actuelly able to load my main software with my bootloader and make it run! (The two software was sharing the sames interruptions.)The problem is when I return to the boot loader. I'm Jumping in the boot loader and then,interrupt conflict between the two software begin. That why I want to avoid this, by giving to the main software is own interrupt.
This was the way the mapping of my project was when I had post my problem.
As I was searching and reading on TI forums, and had change my mapping to this since our last conversation:
Main App at 0x8000 to 0xF1FF
Main App Interrupt relocated to 0xF200 to 0xF3FF
Boot Loader 0xF400 to 0xFE00
Boot Loader Interrupt 0xFE00 to 0xFFFF (Standard)
I have follow the advice of this post for this mapping:
http://e2e.ti.com/support/microcontrollers/msp43016-bit_ultra-low_power_mcus/f/166/p/99865/353674.aspx#353674
"You have a fixed content @0xffe0, but the flash segment where it is in begins at 0xfe00. So why don't you put your branch code there too, as it is also static. And move the application interrupt vectors to 0xfd80, the end of application flash. Also, if you make the tables as large as possible, you can make it MSP independent.vector table and the branches don't care for the interrupt they are serving. So if you code straight down from 0xfffe, it will fit any device."
I understand your concern about this and I take it has great modification to add! But it can not create problem for now.
"Actually, there was no need to modify the original ASM file at all. Only the CMD file."
I don't understand that statement. The example code interrupt proxy.asm was made for the MSP430F5419. My MSP430FG477 did not have the sames interrupt vectors adress.
For example, the PORT2_ISR is at 0xFFD4 for the MSP430F5419 and at 0xFFE2 for my MSP430FG477! So I need to change it !
And I surely need to specify relocated vector adress too, in that files? I'm a bit confused about that !
This is my first time doing a boot loader, maybe I understand wrong in some point. Tell me if I'm wrong in some way.
"Teh message 'cannot run device (to breakpoint)' usually means that the debugger has set an automatic breakpoint at main but the code never comes there. However, I don't see why this happens. YOu should do a memory dump (in the debugger?) and see whether things are where you expect them."
I have made a dump of my flash after debugging and I did not see something wrong. My software is at 0x8000, is interrupt are at 0xF3E0. And the redirected code is at 0xFE00 segment. I joint the dump files, if you want take a look at it. Again Maybe I'm wrong!
I let you the .cmd of my main code and the interrupt proxy.asm if you need to take a look.
/******************************************************************************/ /* lnk_msp430fg477.cmd - LINKER COMMAND FILE FOR LINKING MSP430FG477 PROGRAMS */ /* */ /* Ver | dd mmm yyyy | Who | Description of changes */ /* =====|=============|======|============================================= */ /* 0.01| 08 Mar 2004 | A.D. | First prototype */ /* 0.02| 26 Mai 2004 | A.D. | Leading symbol underscores removed, */ /* | | | Interrupt vector definition changed */ /* 0.03| 22 Jun 2004 | A.D. | File reformatted */ /* */ /* Usage: lnk430 <obj files...> -o <out file> -m <map file> lnk.cmd */ /* cl430 <src files...> -z -o <out file> -m <map file> lnk.cmd */ /* */ /*----------------------------------------------------------------------------*/ /* These linker options are for command line linking only. For IDE linking, */ /* you should set your linker options in Project Properties */ /* -c LINK USING C CONVENTIONS */ /* -stack 0x0100 SOFTWARE STACK SIZE */ /* -heap 0x0100 HEAP AREA SIZE */ /*----------------------------------------------------------------------------*/ /* 'Allocate' peripheral registers at given addresses */ /*----------------------------------------------------------------------------*/ /****************************************************************************/ /* SPECIFY THE SYSTEM MEMORY MAP */ /****************************************************************************/ MEMORY { SFR : origin = 0x0000, length = 0x0010 PERIPHERALS_8BIT : origin = 0x0010, length = 0x00F0 PERIPHERALS_16BIT : origin = 0x0100, length = 0x0100 RAM : origin = 0x0200, length = 0x0400 INFOA : origin = 0x10C0, length = 0x0040 INFOB : origin = 0x1080, length = 0x0040 INFOC : origin = 0x1040, length = 0x0040 INFOD : origin = 0x1000, length = 0x0040 FLASH : origin = 0x8000, length = 0x73E0 /* Reserved segment definition for the main program's interrupt vectors,* reset vector, branch vectors. */ BRINTVEC : origin = 0xFE00, length = 0x180 /* Relocated segment definition for interrupt vectors / reset vector. */ INT00 : origin = 0xF3E0, length = 0x0002 INT01 : origin = 0xF3E2, length = 0x0002 INT02 : origin = 0xF3E4, length = 0x0002 INT03 : origin = 0xF3E6, length = 0x0002 INT04 : origin = 0xF3E8, length = 0x0002 INT05 : origin = 0xF3EA, length = 0x0002 INT06 : origin = 0xF3EC, length = 0x0002 INT07 : origin = 0xF3EE, length = 0x0002 INT08 : origin = 0xF3F0, length = 0x0002 INT09 : origin = 0xF3F2, length = 0x0002 INT10 : origin = 0xF3F4, length = 0x0002 INT11 : origin = 0xF3F6, length = 0x0002 INT12 : origin = 0xF3F8, length = 0x0002 INT13 : origin = 0xF3FA, length = 0x0002 INT14 : origin = 0xF3FC, length = 0x0002 RESET : origin = 0xF3FE, length = 0x0002 /* Reserved main interrupt vectors space. */ MAININTVEC : origin = 0xFF80, length = 0x0080 } /****************************************************************************/ /* SPECIFY THE SECTIONS ALLOCATION INTO MEMORY */ /****************************************************************************/ SECTIONS { .bss : {} > RAM /* GLOBAL & STATIC VARS */ .sysmem : {} > RAM /* DYNAMIC MEMORY ALLOCATION AREA */ .stack : {} > RAM (HIGH) /* SOFTWARE SYSTEM STACK */ .text : {} > FLASH /* CODE */ .text:_isr : {} > FLASH /* ISR CODE SPACE */ .cinit : {} > FLASH /* INITIALIZATION TABLES */ .const : {} > FLASH /* CONSTANT DATA */ .cio : {} > RAM /* C I/O BUFFER */ .pinit : {} > FLASH /* C++ CONSTRUCTOR TABLES */ .infoA : {} > INFOA /* MSP430 INFO FLASH MEMORY SEGMENTS */ .infoB : {} > INFOB .infoC : {} > INFOC .infoD : {} > INFOD .mainintvec : {} > MAININTVEC /* MAIN PROGRAM INT VECTOR TABLE */ .brintvec : {} > BRINTVEC /* BRANCH INST PROGRAM INT VECTOR TABLE */ .int00 : {} > INT00 /* MSP430 INTERRUPT VECTORS */ .int01 : {} > INT01 .int02 : {} > INT02 .int03 : {} > INT03 .int04 : {} > INT04 .int05 : {} > INT05 .int06 : {} > INT06 .int07 : {} > INT07 .int08 : {} > INT08 .int09 : {} > INT09 .int10 : {} > INT10 .int11 : {} > INT11 .int12 : {} > INT12 .int13 : {} > INT13 .int14 : {} > INT14 .reset : {} > RESET /* MSP430 RESET VECTOR */ } /****************************************************************************/ /* INCLUDE PERIPHERALS MEMORY MAP */ /****************************************************************************/ -l msp430xG47x.cmd
;******************************************************************************* ; interrupt proxy.asm ; ; This file is used to fix the interrupt table and route MSP430F5419 hardware ; interrupt requests to the Main Program using proxy routines / vectors. ;**************** ; W. Goh ; Texas Instruments Inc. ; April 2010 ; Built with Code Composer Studio v4.2 Build: 07005 ;******************************************************************************* ;------------------------------------------------------------------------------- ; The following code section is used to define variables to allow ; accessing the interrupt vectors which are defined by the main program. ;------------------------------------------------------------------------------- BASICTIMER_PROXY .equ 0xF3E0 ; 0x8BE0 Basic Timer PORT2_PROXY .equ 0xF3E2 ; 0x8BE2 Port 2 ; 0x8BE4 None DAC12_PROXY .equ 0xF3E6 ; 0x8BE6 DAC PORT1_PROXY .equ 0xF3E8 ; 0x8BE8 Port 1 TIMERA1_PROXY .equ 0xF3EA ; 0x8BEA Timer A CC1-2, TA TIMERA0_PROXY .equ 0xF3EC ; 0x8BEC Timer A CC0 SD16A_PROXY .equ 0xF3EE ; 0x8BEE ADC SD16A USCIAB0TX_PROXY .equ 0xF3F0 ; 0x8BF0 USCI A0/B0 Transmit USCIAB0RX_PROXY .equ 0xF3F2 ; 0x8BF2 USCI A0/B0 Receive WDT_PROXY .equ 0xF3F4 ; 0x8BF4 Watchdog Timer COMPARATORA_PROXY .equ 0xF3F6 ; 0x8BF6 Comparator A TIMERB1_PROXY .equ 0xF3F8 ; 0x8BF8 Timer B CC1-2, TB TIMERB0_PROXY .equ 0xF3FA ; 0x8BFA Timer B CC0 NMI_PROXY .equ 0xF3FC ; 0x8BFC Non-maskable RESET_PROXY .equ 0xF3FE ; 0x8BFE Reset vector .cdecls C,LIST, "msp430xG47x.h" ;------------------------------------------------------------------------------- ; The following code section contains the actual ISR implementation ; for all possible MSP430F5419 interrupt sources. All that is being done ; here is an indirect jump to the address that is stored in the ; main program's virtual interrupt vector table. Other than a 5 CPU ; cycle overhead added to each ISR call, there are no side effects of ; doing this. ; Also, interrupt vectors not implemented on the device are trapped and ; not forwarded to the main program. ;------------------------------------------------------------------------------- .sect ".brintvec" ; Assemble to branch interrupt ; memory ;------------------------------------------------------------------------------- BASICTIMER_ISR BR &BASICTIMER_PROXY ; Indirect jump using proxy PORT2_ISR BR &PORT2_PROXY ; Indirect jump using proxy DAC12_ISR BR &DAC12_PROXY ; Indirect jump using proxy PORT1_ISR BR &PORT1_PROXY ; Indirect jump using proxy TIMERA1_ISR BR &TIMERA1_PROXY ; Indirect jump using proxy TIMERA0_ISR BR &TIMERA0_PROXY ; Indirect jump using proxy SD16A_ISR BR &SD16A_PROXY ; Indirect jump using proxy USCIAB0TX_ISR BR &USCIAB0TX_PROXY ; Indirect jump using proxy USCIAB0RX_ISR BR &USCIAB0RX_PROXY ; Indirect jump using proxy WDT_ISR BR &WDT_PROXY ; Indirect jump using proxy COMPARATORA_ISR BR &COMPARATORA_PROXY ; Indirect jump using proxy TIMERB1_ISR BR &TIMERB1_PROXY ; Indirect jump using proxy TIMERB0_ISR BR &TIMERB0_PROXY ; Indirect jump using proxy NMI_ISR BR &NMI_PROXY ; Indirect jump using proxy RESET_ISR BR &RESET_PROXY ; Indirect jump using proxy ;------------------------------------------------------------------------------- ; The following code section populates the actual MSP430F5419 interrupt ; vectors to point to code sections within the boot loader code. In these ; code sections, an indirect jump is performed and with this the interrupt ; requests are routed to the main program. ;------------------------------------------------------------------------------- .sect ".mainintvec" .word BASICTIMER_ISR ; 0xFFE0 Basic Timer .word PORT2_ISR ; 0xFFE2 Port 2 .word DAC12_ISR ; 0xFFE6 DAC .word PORT1_ISR ; 0xFFE8 Port 1 .word TIMERA1_ISR ; 0xFFEA Timer A CC1-2, TA .word TIMERA0_ISR ; 0xFFEC Timer A CC0 .word SD16A_ISR ; 0xFFEE ADC SD16A .word USCIAB0TX_ISR ; 0xFFF0 USCI A0/B0 Transmit .word USCIAB0RX_ISR ; 0xFFF2 USCI A0/B0 Receive .word WDT_ISR ; 0xFFF4 Watchdog Timer .word COMPARATORA_ISR ; 0xFFF6 Comparator A .word TIMERB1_ISR ; 0xFFF8 Timer B CC1-2, TB .word TIMERB0_ISR ; 0xFFFA Timer B CC0 .word NMI_ISR ; 0xFFFC Non-maskable .word RESET_ISR ; 0xFFFE Reset vector ;------------------------------------------------------------------------------- .end
Thank for your time !!
Maxime Tardif
Looks more logical now. The bootloader part with the 'real' interrupt vector table is now a block at the end of flash, and the applicaiton begins at start. Less chances to get confused :)Maxime Tardif79507 said:
Main App at 0x8000 to 0xF1FF
Main App Interrupt relocated to 0xF200 to 0xF3FF
Boot Loader 0xF400 to 0xFE00
Boot Loader Interrupt 0xFE00 to 0xFFFF (Standard)
Oh, it has. The vector at 0xfffc is the same vector at 0xffc ont he othe rdevice. On all devices. The meaning of this address may change, but this only affects where the compiler will put the interrupt function address. For the bootloader, i tmakes no difference whether this ISR is placed at that location. It just forwards the first vector to the first, the second to the second, whatever it might be. And if the table has a 20th vector and the MSP has only 19, then th e20th is just unused btu doesn't hurt.Maxime Tardif79507 said:
"Actually, there was no need to modify the original ASM file at all. Only the CMD file."
I don't understand that statement. The example code interrupt proxy.asm was made for the MSP430F5419. My MSP430FG477 did not have the sames interrupt vectors adress.
If you check again, you'll see that you only changed comments, and label names that are not used outside the proxy module. And if you compare the resulting binary, you'll see that it is bit for bit the same.
Mos tpeople never work in this area. It is a rather advanced stuff, so you joined a exclusive club. :)Maxime Tardif79507 said:This is my first time doing a boot loader
Maxime Tardif79507 said:I let you the .cmd of my main code and the interrupt proxy.asm if you need to take a look.
0xFF80: 00 FE 04 FE 08 FE 0C FE 10 FE 14 FE 18 FE 1C FE | ................
0xFF90: 20 FE 24 FE 28 FE 2C FE 30 FE 34 FE 38 FE FF FF | .$.(.,.0.4.8...
0xFFA0: ------- b l a n k ----(all 0xFF)-------
Where's the reset vector pointing to your boot loader? It should be on 0xFFFe, but it is 0xFFFF. So no wonder the debugger cannot run the device. The device doesn't know where to start (or rather tries to start its code execution on 0xFFFE, which of course is no code)
your MAININTVEC section has space for 64 vectors and is filled form beginning. But your vector table for this segment has only 15 setors, which are placed from the begining of the segment. You need to pad your content of this segment, so the last (the reset) vector will end up at 0xfffe.
Another thing:
RESET_ISR BR &RESET_PROXY ; Indirect jump using proxy
.word RESET_ISR ; 0xFFFE Reset vector
The 'real' reset vector shouldn't point to the proxy. It should point to the start of your bootloader instead. And if the bootloader decides to start the application, it should do a BR &RESET_PROXY) at the end to start the application. Else the whole proxy thing makes not much sense.
Looks more logical now. The bootloader part with the 'real' interrupt vector table is now a block at the end of flash, and the applicaiton begins at start. Less chances to get confused :)Maxime Tardif79507 said:
Main App at 0x8000 to 0xF1FF
Main App Interrupt relocated to 0xF200 to 0xF3FF
Boot Loader 0xF400 to 0xFE00
Boot Loader Interrupt 0xFE00 to 0xFFFF (Standard)
Oh, it has. The vector at 0xfffc is the same vector at 0xffc ont he othe rdevice. On all devices. The meaning of this address may change, but this only affects where the compiler will put the interrupt function address. For the bootloader, i tmakes no difference whether this ISR is placed at that location. It just forwards the first vector to the first, the second to the second, whatever it might be. And if the table has a 20th vector and the MSP has only 19, then th e20th is just unused btu doesn't hurt.Maxime Tardif79507 said:
"Actually, there was no need to modify the original ASM file at all. Only the CMD file."
I don't understand that statement. The example code interrupt proxy.asm was made for the MSP430F5419. My MSP430FG477 did not have the sames interrupt vectors adress.
If you check again, you'll see that you only changed comments, and label names that are not used outside the proxy module. And if you compare the resulting binary, you'll see that it is bit for bit the same.
Mos tpeople never work in this area. It is a rather advanced stuff, so you joined a exclusive club. :)Maxime Tardif79507 said:This is my first time doing a boot loader
Maxime Tardif79507 said:I let you the .cmd of my main code and the interrupt proxy.asm if you need to take a look.
0xFF80: 00 FE 04 FE 08 FE 0C FE 10 FE 14 FE 18 FE 1C FE | ................
0xFF90: 20 FE 24 FE 28 FE 2C FE 30 FE 34 FE 38 FE FF FF | .$.(.,.0.4.8...
0xFFA0: ------- b l a n k ----(all 0xFF)-------
Where's the reset vector pointing to your boot loader? It should be on 0xFFFe, but it is 0xFFFF. So no wonder the debugger cannot run the device. The device doesn't know where to start (or rather tries to start its code execution on 0xFFFE, which of course is no code)
your MAININTVEC section has space for 64 vectors and is filled form beginning. But your vector table for this segment has only 15 setors, which are placed from the begining of the segment. You need to pad your content of this segment, so the last (the reset) vector will end up at 0xfffe.
Another thing:
RESET_ISR BR &RESET_PROXY ; Indirect jump using proxy
.word RESET_ISR ; 0xFFFE Reset vector
The 'real' reset vector shouldn't point to the proxy. It should point to the start of your bootloader instead. And if the bootloader decides to start the application, it should do a BR &RESET_PROXY) at the end to start the application. Else the whole proxy thing makes not much sense.
Hi,
I also try to write custom bootloader. I created two projects with separate linker files.
I divided memory as follows:
0x4000 - 0xAE00 - my main program
0xAF80 - 0xAFFF - main program interrupt vector
0xB000 - 0xFE00 - bootloader
0xFF80 - 0xFFFF - bootloader interrupt vector
Writing my main program I based on your code example. I adapted it to processor MSP4306736.
It seems that interrup vector in main program was correctly relocated,
but when I jump from bootloader to main program, it runs, but I dont get any interrupts form Timer0_A0.
I dont know what is wrong with my program.
I attach files with linker and memory dump.
I will be grateful for any help or suggestions.
Assuming you correctly enable interrupts etc, you need to set up the interrupt forwarding properly.eg__ said:but when I jump from bootloader to main program, it runs, but I dont get any interrupts form Timer0_A0.
The boot loader table entries have to point to an ISR code. Not to another vector. This code may be an ISR of teh bootloader that checks whether the bootloader is active, or a simple indirect jump that uses the application interrupt table as source for the destination.
Example:
0xFF80 0xFE00 ; boot loader interrupt vector table entry
0xFF82 0xFE04
0xFE00 MOV &0xAF80, R0 ; 'ISR' for this entry, loading value from 0xFEFC to the PC
0xFE04 MOV &0xAF82, R0 ; 'ISR' for this entry, loading value from 0xFEFC to the PC
0xAD80 0x4000 ; application interrupt vector tabel entry
0xAD82 ...
0x4000 [...] ; application ISR
Hi,
I am trying to do the same with MSP430F2232. I have divided my flash as following:
Main App: 0xE000 - 0xEC00
Main Intr Vec : 0xEFE0 - 0xEFFE
Bootloader: 0xF600 - 0xFFE0
Bootloadr Intr : 0xFFE0 - 0xFFFE
I have modified the asmProxy file, as : 0601.interrupt proxy.asm
I do have some questions as I have not quite gasp the concept. I appreciate your responses to them:
1- Do I need to make any changes to cmd file of the bootloader project aside the start and length of the flash?
/******************************************************************************/ /* lnk_msp430f2232.cmd - LINKER COMMAND FILE FOR LINKING MSP430F2232 PROGRAMS */ /* */ /* Usage: lnk430 <obj files...> -o <out file> -m <map file> lnk.cmd */ /* cl430 <src files...> -z -o <out file> -m <map file> lnk.cmd */ /* */ /*----------------------------------------------------------------------------*/ /* These linker options are for command line linking only. For IDE linking, */ /* you should set your linker options in Project Properties */ /* -c LINK USING C CONVENTIONS */ /* -stack 0x0100 SOFTWARE STACK SIZE */ /* -heap 0x0100 HEAP AREA SIZE */ /* */ /*----------------------------------------------------------------------------*/ /****************************************************************************/ /* SPECIFY THE SYSTEM MEMORY MAP */ /****************************************************************************/ MEMORY { SFR : origin = 0x0000, length = 0x0010 PERIPHERALS_8BIT : origin = 0x0010, length = 0x00F0 PERIPHERALS_16BIT : origin = 0x0100, length = 0x0100 RAM : origin = 0x0200, length = 0x0200 INFOA : origin = 0x10C0, length = 0x0040 INFOB : origin = 0x1080, length = 0x0040 INFOC : origin = 0x1040, length = 0x0040 INFOD : origin = 0x1000, length = 0x0040 FLASH : origin = 0xF600, length = 0x09e0 /* start of bootloader 2kB*/ /* Reserved segment definition for the main program's interrupt vectors, * reset vector, branch vectors. */ // BRINTVEC : origin = 0xFE00, length = 0x180 INT00 : origin = 0xFFE0, length = 0x0002 INT01 : origin = 0xFFE2, length = 0x0002 INT02 : origin = 0xFFE4, length = 0x0002 INT03 : origin = 0xFFE6, length = 0x0002 INT04 : origin = 0xFFE8, length = 0x0002 INT05 : origin = 0xFFEA, length = 0x0002 INT06 : origin = 0xFFEC, length = 0x0002 INT07 : origin = 0xFFEE, length = 0x0002 INT08 : origin = 0xFFF0, length = 0x0002 INT09 : origin = 0xFFF2, length = 0x0002 INT10 : origin = 0xFFF4, length = 0x0002 INT11 : origin = 0xFFF6, length = 0x0002 INT12 : origin = 0xFFF8, length = 0x0002 INT13 : origin = 0xFFFA, length = 0x0002 INT14 : origin = 0xFFFC, length = 0x0002 RESET : origin = 0xFFFE, length = 0x0002 /* Reserved main interrupt vectors space. */ // MAININTVEC : origin = 0xFF80, length = 0x0080 } /****************************************************************************/ /* SPECIFY THE SECTIONS ALLOCATION INTO MEMORY */ /****************************************************************************/ SECTIONS { .bss : {} > RAM /* GLOBAL & STATIC VARS */ .data : {} > RAM /* GLOBAL & STATIC VARS */ .sysmem : {} > RAM /* DYNAMIC MEMORY ALLOCATION AREA */ .stack : {} > RAM (HIGH) /* SOFTWARE SYSTEM STACK */ .text : {} > FLASH /* CODE */ .cinit : {} > FLASH /* INITIALIZATION TABLES */ .const : {} > FLASH /* CONSTANT DATA */ .cio : {} > RAM /* C I/O BUFFER */ .pinit : {} > FLASH /* C++ CONSTRUCTOR TABLES */ .init_array : {} > FLASH /* C++ CONSTRUCTOR TABLES */ .mspabi.exidx : {} > FLASH /* C++ CONSTRUCTOR TABLES */ .mspabi.extab : {} > FLASH /* C++ CONSTRUCTOR TABLES */ .infoA : {} > INFOA /* MSP430 INFO FLASH MEMORY SEGMENTS */ .infoB : {} > INFOB .infoC : {} > INFOC .infoD : {} > INFOD /* MSP430 INTERRUPT VECTORS */ .int00 : {} > INT00 .int01 : {} > INT01 PORT1 : { * ( .int02 ) } > INT02 type = VECT_INIT PORT2 : { * ( .int03 ) } > INT03 type = VECT_INIT .int04 : {} > INT04 ADC10 : { * ( .int05 ) } > INT05 type = VECT_INIT USCIAB0TX : { * ( .int06 ) } > INT06 type = VECT_INIT USCIAB0RX : { * ( .int07 ) } > INT07 type = VECT_INIT TIMERA1 : { * ( .int08 ) } > INT08 type = VECT_INIT TIMERA0 : { * ( .int09 ) } > INT09 type = VECT_INIT WDT : { * ( .int10 ) } > INT10 type = VECT_INIT .int11 : {} > INT11 TIMERB1 : { * ( .int12 ) } > INT12 type = VECT_INIT TIMERB0 : { * ( .int13 ) } > INT13 type = VECT_INIT NMI : { * ( .int14 ) } > INT14 type = VECT_INIT .reset : {} > RESET /* MSP430 RESET VECTOR */ } /****************************************************************************/ /* INCLUDE PERIPHERALS MEMORY MAP */ /****************************************************************************/ -l msp430f2232.cmd
2- I have tried to program the flash with FET-PRO430, though when I try to load the second project with CCS 5.3, it erases the previously written part of the flash. Is there any setting that needs to be set so we can debug the project in CCS?
3- This is what I have done for my main App cmd file:
/******************************************************************************/ /* lnk_msp430f2232.cmd - LINKER COMMAND FILE FOR LINKING MSP430F2232 PROGRAMS */ /* */ /* Usage: lnk430 <obj files...> -o <out file> -m <map file> lnk.cmd */ /* cl430 <src files...> -z -o <out file> -m <map file> lnk.cmd */ /* */ /*----------------------------------------------------------------------------*/ /* These linker options are for command line linking only. For IDE linking, */ /* you should set your linker options in Project Properties */ /* -c LINK USING C CONVENTIONS */ /* -stack 0x0100 SOFTWARE STACK SIZE */ /* -heap 0x0100 HEAP AREA SIZE */ /* */ /*----------------------------------------------------------------------------*/ /****************************************************************************/ /* SPECIFY THE SYSTEM MEMORY MAP */ /****************************************************************************/ MEMORY { SFR : origin = 0x0000, length = 0x0010 PERIPHERALS_8BIT : origin = 0x0010, length = 0x00F0 PERIPHERALS_16BIT : origin = 0x0100, length = 0x0100 RAM : origin = 0x0200, length = 0x0200 INFOA : origin = 0x10C0, length = 0x0040 INFOB : origin = 0x1080, length = 0x0040 INFOC : origin = 0x1040, length = 0x0040 INFOD : origin = 0x1000, length = 0x0040 FLASH : origin = 0xE000, length = 0x0C00 /* Reserved segment definition for the main program's interrupt vectors,* reset vector, branch vectors. */ BRINTVEC : origin = 0xFE00, length = 0x180 INT00 : origin = 0xEFE0, length = 0x0002 INT01 : origin = 0xEFE2, length = 0x0002 INT02 : origin = 0xEFE4, length = 0x0002 INT03 : origin = 0xEFE6, length = 0x0002 INT04 : origin = 0xEFE8, length = 0x0002 INT05 : origin = 0xEFEA, length = 0x0002 INT06 : origin = 0xEFEC, length = 0x0002 INT07 : origin = 0xEFEE, length = 0x0002 INT08 : origin = 0xEFF0, length = 0x0002 INT09 : origin = 0xEFF2, length = 0x0002 INT10 : origin = 0xEFF4, length = 0x0002 INT11 : origin = 0xEFF6, length = 0x0002 INT12 : origin = 0xEFF8, length = 0x0002 INT13 : origin = 0xEFFA, length = 0x0002 INT14 : origin = 0xEFFC, length = 0x0002 RESET : origin = 0xEFFE, length = 0x0002 /* Reserved main interrupt vectors space. */ MAININTVEC : origin = 0xFFE0, length = 0x0020 } /****************************************************************************/ /* SPECIFY THE SECTIONS ALLOCATION INTO MEMORY */ /****************************************************************************/ SECTIONS { .bss : {} > RAM /* GLOBAL & STATIC VARS */ .data : {} > RAM /* GLOBAL & STATIC VARS */ .sysmem : {} > RAM /* DYNAMIC MEMORY ALLOCATION AREA */ .stack : {} > RAM (HIGH) /* SOFTWARE SYSTEM STACK */ .text : {} > FLASH /* CODE */ .cinit : {} > FLASH /* INITIALIZATION TABLES */ .const : {} > FLASH /* CONSTANT DATA */ .cio : {} > RAM /* C I/O BUFFER */ .pinit : {} > FLASH /* C++ CONSTRUCTOR TABLES */ .init_array : {} > FLASH /* C++ CONSTRUCTOR TABLES */ .mspabi.exidx : {} > FLASH /* C++ CONSTRUCTOR TABLES */ .mspabi.extab : {} > FLASH /* C++ CONSTRUCTOR TABLES */ .infoA : {} > INFOA /* MSP430 INFO FLASH MEMORY SEGMENTS */ .infoB : {} > INFOB .infoC : {} > INFOC .infoD : {} > INFOD .mainintvec : {} > MAININTVEC /* MAIN PROGRAM INT VECTOR TABLE */ .brintvec : {} > BRINTVEC /* BRANCH INST PROGRAM INT VECTOR TABLE */ /* MSP430 INTERRUPT VECTORS */ .int00 : {} > INT00 .int01 : {} > INT01 PORT1 : { * ( .int02 ) } > INT02 type = VECT_INIT PORT2 : { * ( .int03 ) } > INT03 type = VECT_INIT .int04 : {} > INT04 ADC10 : { * ( .int05 ) } > INT05 type = VECT_INIT USCIAB0TX : { * ( .int06 ) } > INT06 type = VECT_INIT USCIAB0RX : { * ( .int07 ) } > INT07 type = VECT_INIT TIMERA1 : { * ( .int08 ) } > INT08 type = VECT_INIT TIMERA0 : { * ( .int09 ) } > INT09 type = VECT_INIT WDT : { * ( .int10 ) } > INT10 type = VECT_INIT .int11 : {} > INT11 TIMERB1 : { * ( .int12 ) } > INT12 type = VECT_INIT TIMERB0 : { * ( .int13 ) } > INT13 type = VECT_INIT NMI : { * ( .int14 ) } > INT14 type = VECT_INIT .reset : {} > RESET /* MSP430 RESET VECTOR */ } /****************************************************************************/ /* INCLUDE PERIPHERALS MEMORY MAP */ /****************************************************************************/ -l msp430f2232.cmd
memory dump:
=== Information Memory Segments 0x1000 - 0x10FF ====== 0x1000: ------- b l a n k ----(all 0xFF)------- 0x10F0: FF FF FF FF FF FF AC 8A 81 8F 85 8E 79 8D AF 86 | ............y... ========== Main Memory Segments 0xE000 - 0xFFFF ====== 0xE000: 0A 12 09 12 3F 40 00 00 3F 90 01 00 19 28 3F 40 | ....?@..?....(?@ 0xE010: 00 00 3F 90 01 00 14 28 3A 40 00 00 3A 80 00 00 | ..?....(:@..:... 0xE020: 3A 50 03 00 0A 11 0A 11 39 40 00 00 3C 49 7F 4C | :P......9@..<IL 0xE030: 4F 4F 0F 5F 1F 4F 00 00 3D 49 8F 12 1A 83 F6 23 | OO._.O..=I.....# 0xE040: 3F 40 00 00 3F 90 00 00 08 24 3A 40 00 00 02 3C | ?@..?....$:@...< 0xE050: 3F 4A 8F 12 3A 90 00 00 FB 23 30 40 AA E0 B2 40 | ?J..:....#0@...@ 0xE060: 80 5A 20 01 D2 42 FA 10 56 00 D2 42 FB 10 57 00 | .Z ..B..V..B..W. 0xE070: 32 D2 F2 F0 DF 00 2E 00 F2 D0 20 00 2A 00 F2 F0 | 2......... .*... 0xE080: DF 00 29 00 FF 3F 31 40 00 04 B0 12 B6 E0 0C 93 | ..)..?1@........ 0xE090: 02 24 B0 12 00 E0 0C 43 B0 12 5E E0 B0 12 BA E0 | .$.....C..^..... 0xE0A0: 34 41 35 41 36 41 37 41 38 41 39 41 3A 41 30 41 | 4A5A6A7A8A9A:A0A 0xE0B0: 82 43 20 01 00 13 1C 43 30 41 03 43 FF 3F FF FF | .C ....C0A.C.?.. 0xE0C0: ------- b l a n k ----(all 0xFF)------- 0xEFE0: FF FF FF FF B0 E0 B0 E0 FF FF B0 E0 B0 E0 B0 E0 | ................ 0xEFF0: B0 E0 B0 E0 B0 E0 FF FF B0 E0 B0 E0 B0 E0 86 E0 | ................ 0xF000: ------- b l a n k ----(all 0xFF)------- 0xF600: 0A 12 09 12 3F 40 00 00 3F 90 01 00 19 28 3F 40 | ....?@..?....(?@ 0xF610: 00 00 3F 90 01 00 14 28 3A 40 00 00 3A 80 00 00 | ..?....(:@..:... 0xF620: 3A 50 03 00 0A 11 0A 11 39 40 00 00 3C 49 7F 4C | :P......9@..<IL 0xF630: 4F 4F 0F 5F 1F 4F 00 00 3D 49 8F 12 1A 83 F6 23 | OO._.O..=I.....# 0xF640: 3F 40 00 00 3F 90 00 00 08 24 3A 40 00 00 02 3C | ?@..?....$:@...< 0xF650: 3F 4A 8F 12 3A 90 00 00 FB 23 30 40 DE F6 B2 40 | ?J..:....#0@...@ 0xF660: 80 5A 20 01 D2 42 FA 10 56 00 D2 42 FB 10 57 00 | .Z ..B..V..B..W. 0xF670: 32 D2 F2 F0 DF 00 2E 00 F2 D0 20 00 2A 00 F2 D0 | 2......... .*... 0xF680: 20 00 29 00 B0 12 9E F6 7C 93 04 24 F2 F0 DF 00 | .).....|..$.... 0xF690: 29 00 03 3C F2 D0 20 00 29 00 0C 43 30 41 0C 43 | )..<.. .)..C0A.C 0xF6A0: 3E 40 00 E0 0F 43 3F 90 FF 07 05 34 3C EE 1F 53 | >@...C?....4<..S 0xF6B0: 3F 90 FF 07 FB 3B 4C 4C 30 41 31 40 00 04 B0 12 | ?....;LL0A1@.... 0xF6C0: EA F6 0C 93 02 24 B0 12 00 F6 0C 43 B0 12 5E F6 | .....$.....C..^. 0xF6D0: B0 12 EE F6 34 41 35 41 36 41 37 41 38 41 39 41 | ....4A5A6A7A8A9A 0xF6E0: 3A 41 30 41 82 43 20 01 00 13 1C 43 30 41 03 43 | :A0A.C ....C0A.C 0xF6F0: FF 3F FF FF FF FF FF FF FF FF FF FF FF FF FF FF | .?.............. 0xF700: ------- b l a n k ----(all 0xFF)------- 0xFFE0: FF FF FF FF E4 F6 E4 F6 FF FF E4 F6 E4 F6 E4 F6 | ................ 0xFFF0: E4 F6 E4 F6 E4 F6 FF FF E4 F6 E4 F6 E4 F6 BA F6 | ................
Thank you in advance.
So, I was able to test my two projects (Booloader and main App) and am going to answer my own questions as it might be helpful to other people.
mil meh said:1- Do I need to make any changes to cmd file of the bootloader project aside the start and length of the flash?
Well, Apparently not, the only thing need to be modified is the flash location in which u want to put your bootloader.
mil meh said:2- I have tried to program the flash with FET-PRO430, though when I try to load the second project with CCS 5.3, it erases the previously written part of the flash. Is there any setting that needs to be set so we can debug the project in CCS?
I am still not sure about this part and reading through the forum, implies that there is no direct way of debugging the two projects. Though reading the memory dump can give the idea. Moreover, it might be useful to test each individual part by themselves or create a third project only for debugging to make sure you actually jump to where you are supposed to based on you interrupt type.
mil meh said:3- This is what I have done for my main App cmd file:
3443.AppCmd.txtFullscreen12345678910111213141516171819/******************************************************************************//* lnk_msp430f2232.cmd - LINKER COMMAND FILE FOR LINKING MSP430F2232 PROGRAMS *//* *//* Usage: lnk430 <obj files...> -o <out file> -m <map file> lnk.cmd *//* cl430 <src files...> -z -o <out file> -m <map file> lnk.cmd *//* *//*----------------------------------------------------------------------------*//* These linker options are for command line linking only. For IDE linking, *//* you should set your linker options in Project Properties *//* -c LINK USING C CONVENTIONS *//* -stack 0x0100 SOFTWARE STACK SIZE *//* -heap 0x0100 HEAP AREA SIZE *//* *//*----------------------------------------------------------------------------*//****************************************************************************//* SPECIFY THE SYSTEM MEMORY MAP *//****************************************************************************/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/******************************************************************************/ /* lnk_msp430f2232.cmd - LINKER COMMAND FILE FOR LINKING MSP430F2232 PROGRAMS */ /* */ /* Usage: lnk430 <obj files...> -o <out file> -m <map file> lnk.cmd */ /* cl430 <src files...> -z -o <out file> -m <map file> lnk.cmd */ /* */ /*----------------------------------------------------------------------------*/ /* These linker options are for command line linking only. For IDE linking, */ /* you should set your linker options in Project Properties */ /* -c LINK USING C CONVENTIONS */ /* -stack 0x0100 SOFTWARE STACK SIZE */ /* -heap 0x0100 HEAP AREA SIZE */ /* */ /*----------------------------------------------------------------------------*/ /****************************************************************************/ /* SPECIFY THE SYSTEM MEMORY MAP */ /****************************************************************************/ MEMORY { SFR : origin = 0x0000, length = 0x0010 PERIPHERALS_8BIT : origin = 0x0010, length = 0x00F0 PERIPHERALS_16BIT : origin = 0x0100, length = 0x0100 RAM : origin = 0x0200, length = 0x0200 INFOA : origin = 0x10C0, length = 0x0040 INFOB : origin = 0x1080, length = 0x0040 INFOC : origin = 0x1040, length = 0x0040 INFOD : origin = 0x1000, length = 0x0040 FLASH : origin = 0xE000, length = 0x0C00 /* Reserved segment definition for the main program's interrupt vectors,* reset vector, branch vectors. */ BRINTVEC : origin = 0xFE00, length = 0x180 INT00 : origin = 0xEFE0, length = 0x0002 INT01 : origin = 0xEFE2, length = 0x0002 INT02 : origin = 0xEFE4, length = 0x0002 INT03 : origin = 0xEFE6, length = 0x0002 INT04 : origin = 0xEFE8, length = 0x0002 INT05 : origin = 0xEFEA, length = 0x0002 INT06 : origin = 0xEFEC, length = 0x0002 INT07 : origin = 0xEFEE, length = 0x0002 INT08 : origin = 0xEFF0, length = 0x0002 INT09 : origin = 0xEFF2, length = 0x0002 INT10 : origin = 0xEFF4, length = 0x0002 INT11 : origin = 0xEFF6, length = 0x0002 INT12 : origin = 0xEFF8, length = 0x0002 INT13 : origin = 0xEFFA, length = 0x0002 INT14 : origin = 0xEFFC, length = 0x0002 RESET : origin = 0xEFFE, length = 0x0002 /* Reserved main interrupt vectors space. */ MAININTVEC : origin = 0xFFE0, length = 0x0020 } /****************************************************************************/ /* SPECIFY THE SECTIONS ALLOCATION INTO MEMORY */ /****************************************************************************/ SECTIONS { .bss : {} > RAM /* GLOBAL & STATIC VARS */ .data : {} > RAM /* GLOBAL & STATIC VARS */ .sysmem : {} > RAM /* DYNAMIC MEMORY ALLOCATION AREA */ .stack : {} > RAM (HIGH) /* SOFTWARE SYSTEM STACK */ .text : {} > FLASH /* CODE */ .cinit : {} > FLASH /* INITIALIZATION TABLES */ .const : {} > FLASH /* CONSTANT DATA */ .cio : {} > RAM /* C I/O BUFFER */ .pinit : {} > FLASH /* C++ CONSTRUCTOR TABLES */ .init_array : {} > FLASH /* C++ CONSTRUCTOR TABLES */ .mspabi.exidx : {} > FLASH /* C++ CONSTRUCTOR TABLES */ .mspabi.extab : {} > FLASH /* C++ CONSTRUCTOR TABLES */ .infoA : {} > INFOA /* MSP430 INFO FLASH MEMORY SEGMENTS */ .infoB : {} > INFOB .infoC : {} > INFOC .infoD : {} > INFOD .mainintvec : {} > MAININTVEC /* MAIN PROGRAM INT VECTOR TABLE */ .brintvec : {} > BRINTVEC /* BRANCH INST PROGRAM INT VECTOR TABLE */ /* MSP430 INTERRUPT VECTORS */ .int00 : {} > INT00 .int01 : {} > INT01 PORT1 : { * ( .int02 ) } > INT02 type = VECT_INIT PORT2 : { * ( .int03 ) } > INT03 type = VECT_INIT .int04 : {} > INT04 ADC10 : { * ( .int05 ) } > INT05 type = VECT_INIT USCIAB0TX : { * ( .int06 ) } > INT06 type = VECT_INIT USCIAB0RX : { * ( .int07 ) } > INT07 type = VECT_INIT TIMERA1 : { * ( .int08 ) } > INT08 type = VECT_INIT TIMERA0 : { * ( .int09 ) } > INT09 type = VECT_INIT WDT : { * ( .int10 ) } > INT10 type = VECT_INIT .int11 : {} > INT11 TIMERB1 : { * ( .int12 ) } > INT12 type = VECT_INIT TIMERB0 : { * ( .int13 ) } > INT13 type = VECT_INIT NMI : { * ( .int14 ) } > INT14 type = VECT_INIT .reset : {} > RESET /* MSP430 RESET VECTOR */ } /****************************************************************************/ /* INCLUDE PERIPHERALS MEMORY MAP */ /****************************************************************************/ -l msp430f2232.cmdmemory dump:
2063.MemView.txtand I can see that the reset vector @ 0xFFFE is still pointing at the start of my bootloader main, though, shouldnt it be pointing to the main application vector table?Fullscreen12345678910111213141516171819=== Information Memory Segments 0x1000 - 0x10FF ======0x1000: ------- b l a n k ----(all 0xFF)-------0x10F0: FF FF FF FF FF FF AC 8A 81 8F 85 8E 79 8D AF 86 | ............y...========== Main Memory Segments 0xE000 - 0xFFFF ======0xE000: 0A 12 09 12 3F 40 00 00 3F 90 01 00 19 28 3F 40 | ....?@..?....(?@0xE010: 00 00 3F 90 01 00 14 28 3A 40 00 00 3A 80 00 00 | ..?....(:@..:...0xE020: 3A 50 03 00 0A 11 0A 11 39 40 00 00 3C 49 7F 4C | :P......9@..<IL0xE030: 4F 4F 0F 5F 1F 4F 00 00 3D 49 8F 12 1A 83 F6 23 | OO._.O..=I.....#0xE040: 3F 40 00 00 3F 90 00 00 08 24 3A 40 00 00 02 3C | ?@..?....$:@...<0xE050: 3F 4A 8F 12 3A 90 00 00 FB 23 30 40 AA E0 B2 40 | ?J..:....#0@...@0xE060: 80 5A 20 01 D2 42 FA 10 56 00 D2 42 FB 10 57 00 | .Z ..B..V..B..W.0xE070: 32 D2 F2 F0 DF 00 2E 00 F2 D0 20 00 2A 00 F2 F0 | 2......... .*...0xE080: DF 00 29 00 FF 3F 31 40 00 04 B0 12 B6 E0 0C 93 | ..)..?1@........XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX=== Information Memory Segments 0x1000 - 0x10FF ====== 0x1000: ------- b l a n k ----(all 0xFF)------- 0x10F0: FF FF FF FF FF FF AC 8A 81 8F 85 8E 79 8D AF 86 | ............y... ========== Main Memory Segments 0xE000 - 0xFFFF ====== 0xE000: 0A 12 09 12 3F 40 00 00 3F 90 01 00 19 28 3F 40 | ....?@..?....(?@ 0xE010: 00 00 3F 90 01 00 14 28 3A 40 00 00 3A 80 00 00 | ..?....(:@..:... 0xE020: 3A 50 03 00 0A 11 0A 11 39 40 00 00 3C 49 7F 4C | :P......9@..<IL 0xE030: 4F 4F 0F 5F 1F 4F 00 00 3D 49 8F 12 1A 83 F6 23 | OO._.O..=I.....# 0xE040: 3F 40 00 00 3F 90 00 00 08 24 3A 40 00 00 02 3C | ?@..?....$:@...< 0xE050: 3F 4A 8F 12 3A 90 00 00 FB 23 30 40 AA E0 B2 40 | ?J..:....#0@...@ 0xE060: 80 5A 20 01 D2 42 FA 10 56 00 D2 42 FB 10 57 00 | .Z ..B..V..B..W. 0xE070: 32 D2 F2 F0 DF 00 2E 00 F2 D0 20 00 2A 00 F2 F0 | 2......... .*... 0xE080: DF 00 29 00 FF 3F 31 40 00 04 B0 12 B6 E0 0C 93 | ..)..?1@........ 0xE090: 02 24 B0 12 00 E0 0C 43 B0 12 5E E0 B0 12 BA E0 | .$.....C..^..... 0xE0A0: 34 41 35 41 36 41 37 41 38 41 39 41 3A 41 30 41 | 4A5A6A7A8A9A:A0A 0xE0B0: 82 43 20 01 00 13 1C 43 30 41 03 43 FF 3F FF FF | .C ....C0A.C.?.. 0xE0C0: ------- b l a n k ----(all 0xFF)------- 0xEFE0: FF FF FF FF B0 E0 B0 E0 FF FF B0 E0 B0 E0 B0 E0 | ................ 0xEFF0: B0 E0 B0 E0 B0 E0 FF FF B0 E0 B0 E0 B0 E0 86 E0 | ................ 0xF000: ------- b l a n k ----(all 0xFF)------- 0xF600: 0A 12 09 12 3F 40 00 00 3F 90 01 00 19 28 3F 40 | ....?@..?....(?@ 0xF610: 00 00 3F 90 01 00 14 28 3A 40 00 00 3A 80 00 00 | ..?....(:@..:... 0xF620: 3A 50 03 00 0A 11 0A 11 39 40 00 00 3C 49 7F 4C | :P......9@..<IL 0xF630: 4F 4F 0F 5F 1F 4F 00 00 3D 49 8F 12 1A 83 F6 23 | OO._.O..=I.....# 0xF640: 3F 40 00 00 3F 90 00 00 08 24 3A 40 00 00 02 3C | ?@..?....$:@...< 0xF650: 3F 4A 8F 12 3A 90 00 00 FB 23 30 40 DE F6 B2 40 | ?J..:....#0@...@ 0xF660: 80 5A 20 01 D2 42 FA 10 56 00 D2 42 FB 10 57 00 | .Z ..B..V..B..W. 0xF670: 32 D2 F2 F0 DF 00 2E 00 F2 D0 20 00 2A 00 F2 D0 | 2......... .*... 0xF680: 20 00 29 00 B0 12 9E F6 7C 93 04 24 F2 F0 DF 00 | .).....|..$.... 0xF690: 29 00 03 3C F2 D0 20 00 29 00 0C 43 30 41 0C 43 | )..<.. .)..C0A.C 0xF6A0: 3E 40 00 E0 0F 43 3F 90 FF 07 05 34 3C EE 1F 53 | >@...C?....4<..S 0xF6B0: 3F 90 FF 07 FB 3B 4C 4C 30 41 31 40 00 04 B0 12 | ?....;LL0A1@.... 0xF6C0: EA F6 0C 93 02 24 B0 12 00 F6 0C 43 B0 12 5E F6 | .....$.....C..^. 0xF6D0: B0 12 EE F6 34 41 35 41 36 41 37 41 38 41 39 41 | ....4A5A6A7A8A9A 0xF6E0: 3A 41 30 41 82 43 20 01 00 13 1C 43 30 41 03 43 | :A0A.C ....C0A.C 0xF6F0: FF 3F FF FF FF FF FF FF FF FF FF FF FF FF FF FF | .?.............. 0xF700: ------- b l a n k ----(all 0xFF)------- 0xFFE0: FF FF FF FF E4 F6 E4 F6 FF FF E4 F6 E4 F6 E4 F6 | ................ 0xFFF0: E4 F6 E4 F6 E4 F6 FF FF E4 F6 E4 F6 E4 F6 BA F6 | ................
I believe it is right, so the main interrupt vector always point to the bootloader and then bootloader passes the PC to the start of main applications:
ex: if the program starts at 0xE000 (like in my case) and the main application reset interrupt is at 0xEFFE (again in my case), then you simply need to do :
(*((void (*)(void))(*(unsigned int *)0xEFFE)))();
this is what im doing to test if a program is written at my 0xE000 address:
if(readFlash()==0xFF) // its just for testing and no CRC is being done, where read flash just reads the flash bytes
(*((void (*)(void))(*(unsigned int *)0xFFFE)))(); // start of boot loader
else
(*((void (*)(void))(*(unsigned int *)0xEFFE)))(); // start of main application
------------------------------------------------------------------------------
The last but not the least, it seems like using the custom bootloader has caused my timer_A0 interrupt to happen faster and not consistent. It could be due to ~5cc delay of jumping to the actual interrupt vector table. I still need t look into it and welcome any suggestions or workarounds.
mil meh said:2- I have tried to program the flash with FET-PRO430, though when I try to load the second project with CCS 5.3, it erases the previously written part of the flash. Is there any setting that needs to be set so we can debug the project in CCS?I am still not sure about this part and reading through the forum, implies that there is no direct way of debugging the two projects. Though reading the memory dump can give the idea. Moreover, it might be useful to test each individual part by themselves or create a third project only for debugging to make sure you actually jump to where you are supposed to based on you interrupt type.
[/quote]
IIRC, you can configure the debugger to only erase teh used segments. So if the application you want to debug only uses the area 0x8000 to 0xf1ff (including its moved vector table), the remaining (and any full-segments holes inside the project) will be left untouched. The debugger will only erase those segments it needs to write the new firmware to. The default, however, is erasing the whole MSP, as this is by magnitudes faster (all segments are erased simultaneously by a mass erase, instead of each one after the other)
No, the original reset vector must point to the bootloader, or else it will never be executed. THe bootloader then has to determine whether to do something, or to proceed program execution to the address in the 'moved' vector table, which is the entry point of the application startup code (which is not the address of main, if you use C!)mil meh said:I can see that the reset vector @ 0xFFFE is still pointing at the start of my bootloader main, though, shouldnt it be pointing to the main application vector table?mil meh said:if(readFlash()==0xFF) // its just for testing and no CRC is being done, where read flash just reads the flash bytes
(*((void (*)(void))(*(unsigned int *)0xFFFE)))(); // start of boot loader
else
(*((void (*)(void))(*(unsigned int *)0xEFFE)))(); // start of main applicationWell, actually 0xfffe should point to this test. And it will either forward to the application, through the 0xEFFE secondary reset vector, or enter the bootloader directly, not through the reset vector.
Normally not. However, your bootlaoder may do some adjustments (e.g. to the clock system or the timer config) that differ from power-on defaults, but your application simply assumes power-on defaults. And won't notice that the bootloader has changed something.mil meh said:it seems like using the custom bootloader has caused my timer_A0 interrupt to happen faster and not consistent.
Thank you very much for the response. I still have some questions and appreciate if you could respond to them:
Jens-Michael Gross said:if(readFlash()==0xFF) // its just for testing and no CRC is being done, where read flash just reads the flash bytes
(*((void (*)(void))(*(unsigned int *)0xFFFE)))(); // start of boot loader
else
(*((void (*)(void))(*(unsigned int *)0xEFFE)))(); // start of main applicationWell, actually 0xfffe should point to this test. And it will either forward to the application, through the 0xEFFE secondary reset vector, or enter the bootloader directly, not through the reset vector.
[/quote]
Well, What im doing above is to see if anything is written in my main app flash address (0xE000) and if so, I jump to secondary reset vector. I will later use msp430f2252 and will check if a new FW is written at some location and if so I will copy that to 0xE000 (in my case) and erase the image. so it will be like:
if (new_FW @ 0xXXXX ) then
move new_FW to 0xE000 (my case)
either way
go to 0xEFFE (reset vector of main app)
Though you said:
Jens-Michael Gross said:THe bootloader then has to determine whether to do something, or to proceed program execution to the address in the 'moved' vector table, which is the entry point of the application startup code (which is not the address of main, if you use C!)The question is how can I make 0xFFFE point to this. I mean I know I can declare this as a function and put it on a defined address but how can I make reset vector to point to this new address instead of going to the start of the bootloader. Do i have to make like an asm file to make it branch to that address? or can I do something like:
#pragma vector=RESET_VECTOR,
__interrupt void ISR_Reset(void){
and put the above code in here?
}Another issue is, I realized that I in fact fail in reaching my goals as PC does go to the start of main app but then it jumps to 0xE096 which is for some reason 0x3FFF, which I believe is due to the fact that my main App interrupt vector is not properly set and im in a while loop, I see the following:
0xEFF0: FF FF C2 E0 FF FF FF FF FF FF FF FF FF FF 98 E0
and after doing :
#pragma vector=NMI_VECTOR,WDT_VECTOR,ADC10_VECTOR,TIMERB0_VECTOR,TIMERB1_VECTOR,PORT1_VECTOR,PORT2_VECTOR,USCIAB0RX_VECTOR,
USCIAB0TX_VECTOR
__interrupt void ISR_trap(void){WDTCTL = 0; // Write to WDT with a wrong password
}it changes to :
0xEFF0: FF FF C2 E0 D0 E0 FF FF D0 E0 D0 E0 D0 E0 98 E0
which makes sense as 0xE0C2 is my timer_A0 ISR. So at this point I think there is something wrong with my proxy_asm file. I modified my proxy file as following:
7752.proxy.txt, though the interrupt doesnt go where it s supposed to as it resets the uC (possibly due to writing 0 into WDCTL) and again to bootlaoder. So how can I make sure that the actual interrupt vector gets populated to point to code section whithin the bootloader code as I believe my .sevt "mainintvec" in interrupt_proxy file fails to do so.Fullscreen12345678910111213141516171819;*******************************************************************************; interrupt proxy.asm;; This file is used to fix the interrupt table and route MSP430F5419 hardware; interrupt requests to the Main Program using proxy routines / vectors.;; W. Goh; Texas Instruments Inc.; April 2010; Built with Code Composer Studio v4.2 Build: 07005;*******************************************************************************;-------------------------------------------------------------------------------; The following code section is used to define variables to allow; accessing the interrupt vectors which are defined by the main program.;-------------------------------------------------------------------------------INT0_PROXY .equ 0xEFE0 ; 0xEFE0 RTCINT1_PROXY .equ 0xEFE2 ; 0xEFE2 Port 2PORT1_PROXY .equ 0xEFE4 ; 0xEFE4 USCI B3 Receive/TransmitPORT2_PROXY .equ 0xEFE6 ; 0xEFE8 USCI A3 Receive/TransmitXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX;******************************************************************************* ; interrupt proxy.asm ; ; This file is used to fix the interrupt table and route MSP430F5419 hardware ; interrupt requests to the Main Program using proxy routines / vectors. ; ; W. Goh ; Texas Instruments Inc. ; April 2010 ; Built with Code Composer Studio v4.2 Build: 07005 ;******************************************************************************* ;------------------------------------------------------------------------------- ; The following code section is used to define variables to allow ; accessing the interrupt vectors which are defined by the main program. ;------------------------------------------------------------------------------- INT0_PROXY .equ 0xEFE0 ; 0xEFE0 RTC INT1_PROXY .equ 0xEFE2 ; 0xEFE2 Port 2 PORT1_PROXY .equ 0xEFE4 ; 0xEFE4 USCI B3 Receive/Transmit PORT2_PROXY .equ 0xEFE6 ; 0xEFE8 USCI A3 Receive/Transmit INT4_PROXY .equ 0xEFE8 ; 0x5C5A USCI B1 Receive/Transmit ADC10_PROXY .equ 0xEFEA ; 0xEFEA USCI A1 Receive/Transmit USCIAB0TX_PROXY .equ 0xEFEC ; 0x5C5E Port 1 USCIAB0RX_PROXY .equ 0xEFEE ; 0x5C60 Timer1_A3 CC1-2, TA1 TIMERA1_PROXY .equ 0xEFF0 ; 0x5C62 Timer1_A3 CC0 TIMERA0_PROXY .equ 0xEFF2 ; 0x5C64 DMA WDT_PROXY .equ 0xEFF4 ; 0x5C66 USCI B2 Receive/Transmit INT11_PROXY .equ 0xEFF6 ; 0x5C68 USCI A2 Receive/Transmit TIMERB1_PROXY .equ 0xEFF8 ; 0x5C6A Timer0_A5 CC1-4, TA TIMERB0_PROXY .equ 0xEFFA ; 0x5C6C Timer0_A5 CC0 NMI_PROXY .equ 0xEFFC ; 0x5C6E ADC RESET_PROXY .equ 0xEFFE ; 0xEFFE USCI B0 Receive/Transmit .cdecls C,LIST, "msp430.h" ;------------------------------------------------------------------------------- ; The following code section contains the actual ISR implementation ; for all possible MSP430F5419 interrupt sources. All that is being done ; here is an indirect jump to the address that is stored in the ; main program's virtual interrupt vector table. Other than a 5 CPU ; cycle overhead added to each ISR call, there are no side effects of ; doing this. ; Also, interrupt vectors not implemented on the device are trapped and ; not forwarded to the main program. .sect ".brintvec" ; Assemble to branch interrupt ; memory ;------------------------------------------------------------------------------- INT0_ISR BR &INT0_PROXY ; Indirect jump using proxy INT1_ISR BR &INT1_PROXY ; Indirect jump using proxy PORT1_ISR BR &PORT1_PROXY ; Indirect jump using proxy PORT2_ISR BR &PORT2_PROXY ; Indirect jump using proxy INT4_ISR BR &INT4_PROXY ; Indirect jump using proxy ADC10_ISR BR &ADC10_PROXY ; Indirect jump using proxy USCIAB0TX_ISR BR &USCIAB0TX_PROXY ; Indirect jump using proxy USCIAB0RX_ISR BR &USCIAB0RX_PROXY ; Indirect jump using proxy TIMERA1_ISR BR &TIMERA1_PROXY ; Indirect jump using proxy TIMERA0_ISR BR &TIMERA0_PROXY ; Indirect jump using proxy WDT_ISR BR &WDT_PROXY ; Indirect jump using proxy INT11_ISR BR &INT11_PROXY ; Indirect jump using proxy TIMERB1_ISR BR &TIMERB1_PROXY ; Indirect jump using proxy TIMERB0_ISR BR &TIMERB0_PROXY ; Indirect jump using proxy NMI_ISR BR &NMI_PROXY ; Indirect jump using proxy RESET_ISR BR &RESET_PROXY ; Indirect jump using proxy DUMMY_ISR mov.w #0,&WDTCTL ;------------------------------------------------------------------------------- ; The following code section populates the actual MSP430F5419 interrupt ; vectors to point to code sections within the boot loader code. In these ; code sections, an indirect jump is performed and with this the interrupt ; requests are routed to the main program. ;------------------------------------------------------------------------------- .sect ".mainintvec" .word DUMMY_ISR ; 0xFFD2 RTC .word DUMMY_ISR ; 0xFFD2 RTC .word PORT1_ISR ; 0xFFD4 Port 2 .word PORT2_ISR ; 0xFFD6 USCI B3 Receive/Transmit .word DUMMY_ISR ; 0xFFD8 USCI A3 Receive/Transmit .word ADC10_ISR ; 0xFFEA Timer0_A5 CC1-4, TA .word USCIAB0TX_ISR ; 0xFFEC Timer0_A5 CC0 .word USCIAB0RX_ISR ; 0xFFEE ADC .word TIMERA1_ISR ; 0xFFF0 USCI B0 Receive/Transmit .word TIMERA0_ISR ; 0xFFF2 USCI A0 Receive/Transmit .word WDT_ISR ; 0xFFF4 Watchdog Timer .word DUMMY_ISR ; 0xFFF6 Timer0_B7 CC1-6, TB .word TIMERB1_ISR ; 0xFFF8 Timer0_B7 CC0 .word TIMERB0_ISR ; 0xFFFA User Non-maskable .word NMI_ISR ; 0xFFFC System Non-maskable .word RESET_ISR ; 0xFFFE Reset ;------------------------------------------------------------------------------- .endThanx
Well, the typical way to do it would be to integrate this test into the bootloader. The test will either jump to the application or continue (copy the data). So 0xFFFE points to the bootloader which does the check by itself.mil meh said:The question is how can I make 0xFFFE point to this. I mean I know I can declare this as a function and put it on a defined address but how can I make reset vector to point to this new address instead of going to the start of the bootloader.
mil meh said:The question is how can I make 0xFFFE point to this. [...]how can I make reset vector to point to this new address instead of going to the start of the bootloader. Do i have to make like an asm file to make it branch to that address? or can I do something like:#pragma vector=RESET_VECTOR,
__interrupt void ISR_Reset(void){
and put the above code in here?
}
I don't know whether it works for IAR or CCS this way, but it is exactly how I did put my own reset handler in place with MSPGCC. (well, slightly different syntax)
Note that this ISR cannot exit. There is no return address on the stack. In fact, the stack isn't initialized at this point and the stack pointer likely points to 0x0000, causing trouble if you want to put something on stack or use local variables.
Your proxy file looks as if it could do what it should.
However, I noticed that the comments won't match the labels.:
" .word ADC10_ISR ; 0xFFEA Timer0_A5 CC1-4, TA"
The address info in the comments matches the position of the entry (assuming that the size of .mainintvec and the number of vectors match, so RESET_ISR ends up at 0xFFFE), but the labels make the CPU jumping to the wrong proxy then.
Jens-Michael Gross said:Your proxy file looks as if it could do what it should.
However, I noticed that the comments won't match the labels.:
" .word ADC10_ISR ; 0xFFEA Timer0_A5 CC1-4, TA"
Yeah, I didnt change the comments but the labels are correct, however for some reason, i'm unable to branch to secondary table. I'm thinking of using an alternative and manually make the intr vectors jump to my secondary intr vector table in bootloader, like:
#pragma vector=TIMERA0_VECTOR
__interrupt void timera0_ISR(void){
(*((void (*)(void))(*(unsigned int *)0xEFF2)))(); // where 0xEFF2 is where my timer_A0 ISR located in main application.
}
The above works partially as it jumps to application's timer's ISR but after it goes back to bootloader which resets the main application. Therefore, Im still trying to get use of proxy file if I find out wuts wrong with it! Like, do I need to include the asm file anywhere or the linker knows wut it is automatically? Because when I check the map file i see:
BRINTVEC 0000fe00 00000022 00000000 00000022 RWIX
MAININTVEC 0000ffe0 00000020 00000000 00000020 RWIX
which means I defined them but never used them!!
mil meh said:I'm thinking of using an alternative and manually make the intr vectors jump to my secondary intr vector table in bootloader, like:
#pragma vector=TIMERA0_VECTOR
__interrupt void timera0_ISR(void){
(*((void (*)(void))(*(unsigned int *)0xEFF2)))(); // where 0xEFF2 is where my timer_A0 ISR located in main application.
}
That's a bad idea. THis will generate a whole ISR that calls an ISR. You cannot call an ISR. An ISR ends with an RTI whcih expects the status register on stack. But you cannot put the status register on stack yourself. Not where you would need it.
Also, even if this were possible, the compiler will generate framing code. Since you call a function, the processor registers used for funciton parameter passing need to be preserved on stack. So you waste a lot of processor scycles and additional stack space.
You need to add it to the project source file settings, so it is processed by the assembler and included into the build by the linker.mil meh said:do I need to include the asm file anywhere
Jens-Michael Gross said:You need to add it to the project source file settings, so it is processed by the assembler and included into the build by the linker.
I've been searching the project properties up and down and still couldnt find anything to help me solve the issue. I have looked over the properties of the the example project and there s nothing set to read the asm. so any help will be appreciated in this regard.
I think i found my own answer:
Its in Project Properties -> Build -> MSP430 Compiler -> Processor Options -> Silicon version :application binary interface : coffabi
According to Compiler manual:
"COFF ABI :
COFF ABI is the only ABI supported by older compilers. To generate object files compatible with older
COFF ABI object files, you must use COFF ABI (--abi=coffabi, the default). This option must also be
when assembly hand-coded assembly source files intended to be used in a COFF ABI application."
It works as expected now.However, now I need to think of a way of using the bootloader as whats happening now is: the main application points all the main interrupt to my secondary table and they do the trick but it means that bootloader is useless.
I think, now I know wuat Jens-Michael meant by having 0xFFFE always point to bootloader, which will decide if it needs to jump to main app or nor. So here is what i changed in interrupt_proxy. asm
.word 0xf6b6 ; where 0xf6b6 is the start of bootlader. where it will jump to main app if there exists any.
Now, whuts happening is as follows:
When i debug the main application, it takes a while and then it shows:
Can't find a source file at "/tmp/TI_MKLIB3cHxjO/SRC/boot.c"
Locate the file or edit the source lookup path to include its location.
Though, after this message I can start the debug and it works just fine. I think the problem is it takes along time for the uC to set up that it shows the message. I used to have the same problem with msp430f5419 which in that case I added : WDTCTL = WDTPW + WDTHOLD; in pre_init.c file. I did the same for this uC and named it boot.c. The error doesnt get generated and works just fine.
However, when I debug my LED which is blinking by every interrupt that I get from TimerA0 is way faster than when I program the flash. So, I assume Im not totally out of the woods but hopefully will fix this bug and report the solution here.
So, I'll post my last thoughts on this subject. Unfortunately, I wasnt able to use COFFABI as my program wouldnt fit in the uC that I chose. So, I came up with a better solution, I stuck to the previous eabi settings which reduced the code size, but as I mentioned before, I couldnt use the asm file with the project. So, wut I did is, instead of creating a secondary table for all the interrupt, I created another reset vector which would be only pointing to the start of my bootloader, while my main application reset vector is pointing to the start of the main app. Hence, all the interrupts are at their default location and only the RESET vector has different address.
RESET : origin = 0xFE9E, length = 0x0002 // main app reset vector
RESET_env : origin = 0xFFFE, length = 0x0002 // default reset
Then I placed this segment in the code:
#pragma DATA_SECTION( az , ".reset_env" );
const unsigned short az = 0xFB44; // reset to start of bootloader
It should be noted that the compiler most likely ignore the above code due to optimization, hence, one need to use param az somewhere in the code. So upon startup, PC goes to 0xFB44, where my bootloader is in which I check for new FW and after copying the new FW. I jump to the main application reset vector(0xFE9E, in my case).
Hi,
Following this topic ive created a bootloader and main application with the bootloader jumping to the main app and visa versa.
The problem im having is with using the proxy asm example, as the Main application is in the 20bit Flash memory region the ASM proxy example doesnt work. I dont really want to move the main application to the 16bit area. Does anybody have any ideas on how to resolve?
Thanking you in advance.
D
Ive totally separated the flash memory region for the two applications as shown below.
----------MSP430F5228------------------------------------------------------------------
Main App = 0x10000-0x2437F
Main App Interrupt Vec table = 0x24380 - 0x243FF
----------------------------------------------------------------------------
Bootloader App = 0x4400 - 0xFDFF
Bootloader App Interrupt Vec table = 0xFF80 - 0xFFFF
----------------------------------------------------------------------------
Des said:The problem im having is with using the proxy asm example, as the Main application is in the 20bit Flash memory region the ASM proxy example doesnt work. I dont really want to move the main application to the 16bit area. Does anybody have any ideas on how to resolve?
The addresses stored in the vector table at FF80-FFFF can only be 16-bit addresses. As such, if you want to access code that is in 20-bit upper memory, you need an additional jump table in 16-bit memory that includes the "long" jumps to your 20-bit addresses.
Des,
Read this thread: http://e2e.ti.com/support/microcontrollers/msp430/f/166/t/324839.aspx
As the smallest block of Flash you can clear is 512bytes.
1: The upper 512byte memory that have IRQ vectors should be fixed and never cleared.
I has a list of addresses to fixed IRQ service locations, these fixed locations has a rewritable list of re-jumps to new location due to new firmware will compile in to different lengths and segment addresses etc.
2: You need to take care of if a crash happens right between clearing this table and a new one is reloaded does not hang the BSL.
It could probably be 99% fool proof, I'm not sue if 100% is doable until I think about it some more.
My simple NMI UART BSL, simple writes back the RST and NMI vector right away (points to the BSL) after doing a mass-erase and pray that nothing happens during those uS when in a limbo state.
And the BLS simple don't write to memory that are not $ffff when it's block filling in the rest of the vector table.
For the main application i have successfully mapped the interrupt vectors to RAM (reserved by *.xcl file) and proven the code runs in the 16bit Flash area using the example http://processors.wiki.ti.com/index.php/MSP430_FAQ#Is_there_a_way_to_re-allocate_the_interrupt_vector_on_MSP430.3F. Happy days.
Im still having a problem with the application when it is pushed up to the 20bit flash area. The application runs, but as soon as one of the interrupts fires the application fails.
1. Any suggestions?
2. Ive found no reference to how a typical *xcl file is set up for a bootloader and main application. Does anybody have and IAR examples?
Thanking you in advance.
D
PS. Also the main application uses printf statement, would this cause any problems with an application running in 20bit flash region?
If your ISR is located above 64k (has a 20-bit address), then you need to generate a stub that resides in lower 64k (16-bit address) and does a jump to the upper address location. The vector table can only point to code in the lower 64k. Of course the stub can also jump to an ISR in the lower 64k, so if you use this approach, it is universal. But does cost some additional clock cycles.
You can create your secondary interrupt table as an array of 32 bit address values. The real vector table points to an array of indirect jump instructions in the lower 64k (can be fused together with the vector table to the flash segment 0x0FE00-.0x0FFFF) which do an indirect jump using the (twice as large) secondary vector table. You won’t declare the ISR then with the vector pragma (the interrupt attribute is still needed), but rather manually insert their function name into the array that forms the secondary vector table.
..interesting. Ive already implemented the secondary interrupt table (32bit) but its held in RAM using SYSRIVECT. Ive made sure that a segment in RAM is clear and the secondary Interrupt table mapped to it.
My thoughts were that leaving the original vector table in flash with size (0xFF80 - FFFF) (16bit) would allow the bootloader application to function correctly then mapping int vectors to RAM would allow the main application to run (which it does but the interrupt doesnt work - or course), its always the last bit that fails lol
Any other ideas?
Des
The secondary interrupt table is the very same as the primary one – only the address it is read from is changed to the end of ram instead of end of lower 64k. So it makes no difference – it still points to lower 64k only and your ISRs must begin there.
...does this mean that the lower 64k of flash of the MSP430F5228 can only contain ISR.
Also is SYSRIVECT (used to map interrupt vectors to ram) compatible with upper 20bit flash memory? Nothing ive read so far tells me it isnt but all tests have worked on applications in the 16bit area and not 20bit.
Is there anyway of having it placed in the upper 20bit flash segment and executing ISR's from there?
Im looking to put together a bootloader application in 16bit flash and main application in the 20bit flash area. Has anybody succeed in this? The MSP430 architecture is proven playful to say the least.
Any views would be grateful.
D
Yes, the entry point of an ISR needs to be in the lower 64k. Always. No exception. However, it may then branch to code in the extended memory area. That’s why I suggested the vectors pointing to a fixed location with an indirect jump, while the jump utilized 20/32 bit addresses from a custom jumptable (a function-pointer table that points to the ISRs). However, there is one problem: the compiler/linker will automatically put all ISRs with the interrupt keyword into lower 64k. And without this keyword, the compiler won’t generate the proper entry and exit code (like saving R12-R15, and doing a RETI instead of a RETA at the end). You’d have to manipulate the linker script to allow ISRs going into upper memory, while the jumps are fixed in lower memory.
Instead of a jump, you may declare the ISR just containing an (indirect) call to the real ISR which turns into a normal function then. But this raises another problem: since the ISR is a normal function now, you’ll add execution time for call and return, and the compiler will need to save R12 to R15 before (and restore them after) the call, even if not needed. This significantly increases the ISR latency and execution overhead. It’s your choice which way to go.
Jens-Michael Gross said:Instead of a jump, you may declare the ISR just containing an (indirect) call to the real ISR which turns into a normal function then.
If you go this route, I believe that means that you lose the capability to use the intrinsics that modify the SR (to exit LPM, for instance). Or you then have to do something crafty like putting that part in the 16-bit code section.
Hi All,
Thank you all for your comments,
Ive managed to get this working after a bit of playing. It looks like (as suggested) the ISR need to be within the 16bit flash segment. With this said ive insured that the bootloader occupies a 20k area of 16 bit flash, and the rest assigned to the main application spread over 16 to 20bit flash. The main application uses RAM vector mapping with ISR defined in 16 bit flash for main application. Magic :)
Des
I
You’re right, if you use a function call inside an ISR; you cannot modify the stored status (e.g. for exiting LPM) inside the called function.
As I said the called function is a normal function then, and therefore cannot use the “exit” intrinsic.
So this way may be a bit more convenient, as it can be done in pain C, but limits the compatibility regarding these special features.
(that's a problem you also had with the ISR stubs generated by GRACE - I don't know whether this has changed since the early versions)
Looking at the TI MSP430 compiler there are two aspects for interrupts:Jens-Michael Gross said:However, there is one problem: the compiler/linker will automatically put all ISRs with the interrupt keyword into lower 64k. And without this keyword, the compiler won’t generate the proper entry and exit code (like saving R12-R15, and doing a RETI instead of a RETA at the end). You’d have to manipulate the linker script to allow ISRs going into upper memory, while the jumps are fixed in lower memory.
a) The #pragma vector is what places the function in the lower 64K.
b) The __interrupt keyword is what causes the compiler to use the RETI instruction.
Therefore, with a interrupt function which is to be called via an indirect jump table, the __interrupt vector should be used, but with no #pragma vector. This is shown in the MSPBoot example applications.
**Attention** This is a public forum