Владимир В. Р.
Nov 14 2008, 12:21
Добрый день... Начал пробовать программировать на С++, переделываю старый поект написанный на С и сталкнулся с проблемой, у классов обьявленных как глобальные не вызываються конструкторы. Есть предположение что это фишка IAR. В чём может быть проблема? Где можно почитать про использование C++ и в частности ООП для программирования контроллеров? Заранее благодарен.
VladimirYU
Nov 14 2008, 12:30
Цитата(Владимир В. Р. @ Nov 14 2008, 15:21)

Добрый день... Начал пробовать программировать на С++, переделываю старый поект написанный на С и сталкнулся с проблемой, у классов обьявленных как глобальные не вызываються конструкторы. Есть предположение что это фишка IAR. В чём может быть проблема? Где можно почитать про использование C++ и в частности ООП для программирования контроллеров? Заранее благодарен.
Нет. примерчик покажите.
Владимир В. Р.
Nov 14 2008, 12:52
Забыл написать что для проца AT91SAM7X256:
Исходники:
astartup.s79:
#define AIC_IVR (256) // IRQ Vector Register
#define AIC_FVR (260) // FIQ Vector Register
#define AIC_EOICR (304) // End of Interrupt Command Register
#include <ioat91sam7x256.h>
;------------------------------------------------------------------------------
EXTERN OS_CPU_IRQ_ISR
EXTERN OS_CPU_FIQ_ISR
; EXTERN AT91F_LowLevelInit
;------------------------------------------------------------------------------
; ?RESET
; Reset Vector.
; Normally, segment INTVEC is linked at address 0.
; For debugging purposes, INTVEC may be placed at other addresses.
; A debugger that honors the entry point will start the
; program in a normal way even if INTVEC is not at address 0.
;------------------------------------------------------------------------------
PUBLIC __program_start
PROGRAM ?RESET ;- Begins a program module
RSEG INTRAMEND_REMAP ;- Begins a relocatable segment
RSEG INTVEC:CODE (2) ;- Begins a relocatable segment : corresponding address is 32-bit aligned
CODE32 ;- Always ARM mode after reset
;------------------------------------------------------------------------------
;- Exception vectors
;------------------------------------------------------------------------------
;- These vectors can be read at address 0 or at RAM address
;- They ABSOLUTELY requires to be in relative addresssing mode in order to
;- guarantee a valid jump. For the moment, all are just looping.
;- If an exception occurs before remap, this would result in an infinite loop.
;- To ensure if a exeption occurs before start application to infinite loop.
;------------------------------------------------------------------------------
__program_start
reset
org 0x00
ldr pc,[pc,#24] ; Absolute jump can reach 4 GByte
org 0x04
ldr pc,[pc,#24] ; Branch to undef_handler
org 0x08
ldr pc,[pc,#24] ; Branch to swi_handler
org 0x0c
ldr pc,[pc,#24] ; Branch to prefetch_handler
org 0x10
ldr pc,[pc,#24] ; Branch to data_handler
org 0x18
ldr pc,[pc,#24] ; Branch to irq_handler
org 0x1c
ldr pc,[pc,#24] ; Branch to fiq_handler
; Constant table entries (for ldr pc) will be placed at 0x20
; Exception vectors can be specified in C code by #pragma vector or by filling
; in the vectors below. The vector address is the ARM vector number + 0x20.
org 0x20
dc32 InitReset
org 0x24
dc32 ?call_exit
org 0x28
dc32 ?call_exit
org 0x2c
dc32 ?call_exit
org 0x30
dc32 ?call_exit
org 0x38
dc32 OS_CPU_IRQ_ISR
org 0x3c
dc32 OS_CPU_FIQ_ISR
RSEG INTRAMEND_REMAP ;- Begins a relocatable segment
RSEG ICODE:CODE (2)
InitReset:
;------------------------------------------------------------------------------
;- Low level Init is performed in a C function: AT91F_LowLevelInit
;- Init Stack Pointer to a valid memory area before calling AT91F_LowLevelInit
;------------------------------------------------------------------------------
;- Retrieve end of RAM address
__iramend EQU SFB(INTRAMEND_REMAP) ;- Segment begin
EXTERN AT91F_LowLevelInit
ldr r13,=__iramend ;- Temporary stack in internal RAM for Low Level Init execution
ldr r0, =AT91F_LowLevelInit
mov lr, pc
bx r0 ;- Branch on C function (with interworking)
;------------------------------------------------------------------------------
;- Top of Stack Definition
;------------------------------------------------------------------------------
;- Interrupt and Supervisor Stack are located at the top of internal memory in
;- order to speed the exception handling context saving and restoring.
;- ARM_MODE_SVC (Application, C) Stack is located at the top of the external memory.
;------------------------------------------------------------------------------
IRQ_STACK_SIZE EQU (3*8*4) ; 3 words to be saved per interrupt priority level
ARM_MODE_FIQ EQU 0x11
ARM_MODE_IRQ EQU 0x12
ARM_MODE_SVC EQU 0x13
I_BIT EQU 0x80
F_BIT EQU 0x40
;------------------------------------------------------------------------------
;- Setup the stack for each mode
;------------------------------------------------------------------------------
ldr r0, =__iramend
;- Set up Fast Interrupt Mode and set FIQ Mode Stack
msr CPSR_c, #ARM_MODE_FIQ | I_BIT | F_BIT
;- Init the FIQ register
ldr r8, =AT91C_BASE_AIC
;- Set up Interrupt Mode and set IRQ Mode Stack
msr CPSR_c, #ARM_MODE_IRQ | I_BIT | F_BIT
mov r13, r0 ; Init stack IRQ
sub r0, r0, #IRQ_STACK_SIZE
;- Enable interrupt & Set up Supervisor Mode and set Supervisor Mode Stack
msr CPSR_c, #ARM_MODE_SVC | I_BIT | F_BIT
mov r13, r0
;------------------------------------------------------------------------------
; Initialize segments.
;------------------------------------------------------------------------------
; __segment_init is assumed to use
; instruction set and to be reachable by BL from the ICODE segment
; (it is safest to link them in segment ICODE).
;------------------------------------------------------------------------------
EXTERN __segment_init
ldr r0,=__segment_init
mov lr, pc
bx r0
;------------------------------------------------------------------------------
;- Branch on C code Main function (with interworking)
;------------------------------------------------------------------------------
EXTERN main
PUBLIC __main
?jump_to_main:
ldr lr,=?call_exit
ldr r0,=main
__main:
bx r0
;------------------------------------------------------------------------------
;- Loop for ever
;------------------------------------------------------------------------------
;- End of application. Normally, never occur.
;- Could jump on Software Reset ( B 0x0 ).
;------------------------------------------------------------------------------
?call_exit:
End
b End
;------------------------------------------------------------------------------
;- Exception Vectors
;------------------------------------------------------------------------------
PUBLIC AT91F_Default_FIQ_handler
PUBLIC AT91F_Default_IRQ_handler
PUBLIC AT91F_Spurious_handler
CODE32 ; Always ARM mode after exeption
AT91F_Default_FIQ_handler
b AT91F_Default_FIQ_handler
AT91F_Default_IRQ_handler
b AT91F_Default_IRQ_handler
AT91F_Spurious_handler
b AT91F_Spurious_handler
ENDMOD ;- Terminates the assembly of the current module
END ;- Terminates the assembly of the last module in a file
cstatup_sam7.c
#include <ioat91sam7x256.h>
#include "bsp.h"
// The following functions must be write in ARM mode this function called directly by exception vector
extern void AT91F_Spurious_handler(void);
extern void AT91F_Default_IRQ_handler(void);
extern void AT91F_Default_FIQ_handler(void);
//extern void AT91F_LowLevelInit(void);
#define MC_FLASH_MODE_MASTER_CLK_IN_MHZ(x) ((unsigned int)(x) << 16)
//*----------------------------------------------------------------------------
//* \fn AT91F_LowLevelInit
//* \brief This function performs very low level HW initialization
//* this function can use a Stack, depending the compilation
//* optimization mode
//*----------------------------------------------------------------------------
_C_LIB_DECL
void AT91F_LowLevelInit(void)
{
//AT91C_BASE_RSTC->RSTC_RCR = (0xA5<<24)|(1<<2);
//while(AT91C_BASE_RSTC->RSTC_RSR & AT91C_RSTC_SRCMP);
if (!(AT91C_BASE_MC->MC_FSR & AT91C_MC_GPNVM0))
{
AT91C_BASE_MC->MC_FCR = ((unsigned int) 0x5A << 24) | ((unsigned int) 0x0 << 8) | AT91C_MC_FCMD_SET_GP_NVM;
while(!(AT91C_BASE_MC->MC_FSR & AT91C_MC_FRDY));
}
if (!(AT91C_BASE_MC->MC_FSR & AT91C_MC_GPNVM1))
{
AT91C_BASE_MC->MC_FCR = ((unsigned int) 0x5A << 24) | ((unsigned int) 0x1 << 8) | AT91C_MC_FCMD_SET_GP_NVM;
while(!(AT91C_BASE_MC->MC_FSR & AT91C_MC_FRDY));
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
// EFC Init
/////////////////////////////////////////////////////////////////////////////////////////////////////
// 1 Wait State necessary to work at 48MHz
AT91C_BASE_MC->MC_FMR = AT91C_MC_FWS_1FWS | (73<<16);
/////////////////////////////////////////////////////////////////////////////////////////////////////
// Init PMC Step 1. Enable Main Oscillator
// Main Oscillator startup time is board specific:
// Main Oscillator Startup Time worst case (3MHz) corresponds to 15ms (0x40 for AT91C_CKGR_OSCOUNT field)
// 1) ?ac?aoeou ?aaioo iniiaiiai oaeoiaiai aaia?aoi?a
/////////////////////////////////////////////////////////////////////////////////////////////////////
AT91C_BASE_PMC->PMC_MOR = (( AT91C_CKGR_OSCOUNT & (0x40 <<8) | AT91C_CKGR_MOSCEN ));
// Wait Main Oscillator stabilization
while(!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MOSCS));
/////////////////////////////////////////////////////////////////////////////////////////////////////
// Init PMC Step 2.
// Set PLL to 96MHz (96,109MHz) and UDP Clock to 48MHz
// PLL Startup time depends on PLL RC filter: worst case is choosen
// UDP Clock (48,058MHz) is compliant with the Universal Serial Bus Specification (+/- 0.25% for full
/////////////////////////////////////////////////////////////////////////////////////////////////////
AT91C_BASE_PMC->PMC_PLLR = AT91C_CKGR_USBDIV_1 | AT91C_CKGR_OUT_0 | AT91C_CKGR_PLLCOUNT |
(AT91C_CKGR_MUL & ((AT91_MUL-1) << 16)) | (AT91C_CKGR_DIV & AT91_DIV);
// Wait for PLL stabilization
while( !(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_LOCK) );
// Wait until the master clock is established for the case we already turn on the PLL
while( !(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY) );
/////////////////////////////////////////////////////////////////////////////////////////////////////
// Init PMC Step 3.
// Selection of Master Clock MCK (equal to Processor Clock PCK) equal to PLL/2 = 48MHz
// The PMC_MCKR register must not be programmed in a single write operation (see. Product Errata //Sheet)
/////////////////////////////////////////////////////////////////////////////////////////////////////
AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_PRES_CLK_2;
// Wait until the master clock is established
while( !(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY) );
AT91C_BASE_PMC->PMC_MCKR |= AT91C_PMC_CSS_PLL_CLK;
// Wait until the master clock is established
while( !(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY) );
/////////////////////////////////////////////////////////////////////////////////////////////////////
if (!(AT91C_BASE_PMC->PMC_SCSR & AT91C_PMC_PCK))AT91C_BASE_PMC->PMC_SCER = AT91C_PMC_PCK;
if (!(AT91C_BASE_PMC->PMC_SCSR & AT91C_PMC_UDP))AT91C_BASE_PMC->PMC_SCER = AT91C_PMC_UDP;
//AT91C_BASE_PMC->PMC_SCER = AT91C_PMC_PCK | AT91C_PMC_UDP;
// EFC Init
/////////////////////////////////////////////////////////////////////////////////////////////////////
AT91C_BASE_MC->MC_FMR = AT91C_MC_FWS_1FWS| MC_FLASH_MODE_MASTER_CLK_IN_MHZ(73); // 1 Wait State necessary to work at 48MHz
/////////////////////////////////////////////////////////////////////////////////////////////////////
// Disable Watchdog (write once register)
/////////////////////////////////////////////////////////////////////////////////////////////////////
AT91C_BASE_WDTC->WDTC_WDMR = AT91C_WDTC_WDDIS;
#ifdef SHIFT_CODE_REMAP
volatile unsigned int *pSourceIVEC = (volatile unsigned int *)0x00102000;
volatile unsigned int *pDistIVEC = (volatile unsigned int *)0x00200000;
remap_test = *((volatile unsigned int *)0x00000000);
*((volatile unsigned int *)0x00000000) = ++remap_test;
if (*((volatile unsigned int *)0x00000000) != remap_test)
{
AT91C_BASE_MC->MC_RCR = 1;
}
for (unsigned char i = 0; i < 16; i++)
{
pDistIVEC[i] = pSourceIVEC[i];
}
#endif
////////////////////////////////////////////////////////////////////////////////////////////////////
// Init AIC: assign corresponding handler for each interrupt source
/////////////////////////////////////////////////////////////////////////////////////////////////////
//AT91C_BASE_AIC->AIC_SVR[0] = (int) AT91F_Default_FIQ_handler ;
//for (i = 1; i < 31; i++) {
// AT91C_BASE_AIC->AIC_SVR[i] = (int) AT91F_Default_IRQ_handler ;
//}
//AT91C_BASE_AIC->AIC_SPU = (unsigned int) AT91F_Spurious_handler;
}
_END_C_LIB_DECL
FLASH.xcl
//*************************************************************************
-carm
//*************************************************************************
// Internal Ram segments mapped AFTER REMAP 64 K.
//*************************************************************************
-Z(CONST)INTRAMSTART_REMAP=00200000
-Z(CONST)INTRAMEND_REMAP=0020FFFF
//*************************************************************************
// Read-only segments mapped to Flash 256 K.
//*************************************************************************
-DROMSTART=00000040
-DROMEND=0003FEFF
//*************************************************************************
// Read/write segments mapped to 64 K RAM.
//*************************************************************************
-DRAMSTART=00200000
-DRAMEND=0020FFFF
//*************************************************************************
// Address range for reset and exception
// vectors (INTVEC).
// The vector area is 32 bytes,
// an additional 32 bytes is allocated for the
// constant table used by ldr PC in cstartup.s79.
//*************************************************************************
-Z(CODE)INTVEC=00-3F
//*************************************************************************
// Startup code and exception routines (ICODE).
//*************************************************************************
-Z(CODE)ICODE,DIFUNCT=ROMSTART-ROMEND
-Z(CODE)SWITAB=ROMSTART-ROMEND
//*************************************************************************
// Code segments may be placed anywhere.
//*************************************************************************
-Z(CODE)CODE=ROMSTART-ROMEND
//*************************************************************************
// Various constants and initializers.
//*************************************************************************
-Z(CONST)INITTAB,DATA_ID,DATA_C=ROMSTART-ROMEND
-Z(CONST)CODE_ID=ROMSTART-ROMEND
-Z(CONST)CHECKSUM=ROMSTART-ROMEND
-Z(CONST)RAWIMAGE=ROMSTART-ROMEND
//*************************************************************************
// Data segments.
//*************************************************************************
-Z(DATA)DATA_I,DATA_Z,DATA_N=RAMSTART-RAMEND
//*************************************************************************
// __ramfunc code copied to and executed from RAM.
//*************************************************************************
-Z(DATA)CODE_I=RAMSTART-RAMEND
-DCOMMONRAMSTART=0020FF00
-DCOMMONRAMEND=0020FFFF
//*************************************************************************
// ICCARM produces code for __ramfunc functions in
// CODE_I segments. The -Q XLINK command line
// option redirects XLINK to emit the code in the
// debug information associated with the CODE_I
// segment, where the code will execute.
//*************************************************************************
-QCODE_I=CODE_ID
//*************************************************************************
// Stack and heap segments.
//*************************************************************************
-D_CSTACK_SIZE=(200*4)
-D_IRQ_STACK_SIZE=(3*8*4)
-D_FIQ_STACK_SIZE=(32*4)
-D_UBT_STACK_SIZE=(32*4)
-D_SVC_STACK_SIZE=(200*4)
-D_ABT_STACK_SIZE=(32*4)
-D_HEAP_SIZE=0
-Z(DATA)CSTACK+_CSTACK_SIZE=RAMSTART-RAMEND
-Z(DATA)IRQ_STACK+_IRQ_STACK_SIZE=RAMSTART-RAMEND
-Z(DATA)FIQ_STACK+_FIQ_STACK_SIZE=RAMSTART-RAMEND
-Z(DATA)UBT_STACK+_UBT_STACK_SIZE=RAMSTART-RAMEND
-Z(DATA)SVC_STACK+_SVC_STACK_SIZE=RAMSTART-RAMEND
-Z(DATA)ABT_STACK+_ABT_STACK_SIZE=RAMSTART-RAMEND
-Z(DATA)HEAP+_HEAP_SIZE=RAMSTART-RAMEND
//*************************************************************************
// My segments.
//*************************************************************************
-Z(DATA)COMMON_DATA_RAM=COMMONRAMSTART-COMMONRAMEND
//*************************************************************************
// ELF/DWARF support.
//
// Uncomment the line "-Felf" below to generate ELF/DWARF output.
// Available format specifiers are:
//
// "-yn": Suppress DWARF debug output
// "-yp": Multiple ELF program sections
// "-yas": Format suitable for debuggers from ARM Ltd (also sets -p flag)
//
// "-Felf" and the format specifiers can also be supplied directly as
// command line options, or selected from the Xlink Output tab in the
// IAR Embedded Workbench.
//*************************************************************************
// -Felf
main.c
.....
void AT91F_InitDBGU(void)
{
// AT91F_DBGU_CfgPMC(); // DBGU is always clocked
AT91F_DBGU_CfgPIO(); // Open PIO for DBGU
AT91F_US_Configure ((AT91PS_USART) AT91C_BASE_DBGU,
AT91C_MASTER_CLOCK,
AT91C_US_ASYNC_MODE, // mode Register to be programmed
AT91C_BAUDRATE_115200, // baudrate to be programmed
0); // timeguard to be programmed
// Enable Transmitter
AT91F_US_EnableTx((AT91PS_USART) AT91C_BASE_DBGU);
}
class tst
{
public:
tst();
void run();
private:
int x;
};
tst::tst()
{
x = 1;
}
tst s;
//------------------------------------------------------------------------------------
// \fn main
// \brief main îí â àôðèêå main
//------------------------------------------------------------------------------------
int main(void)
{
AT91F_InitDBGU();
for(;;){
TRACE_INFO("\n\n\bla-bla");
}
}
Вот... собственно всё что есть... смотрю трасировщиком, ставлю break-point в конструктор класса tst, если обьявить tst s внутри main то попадаю в конструктор
mdmitry
Nov 14 2008, 12:55
Предположение: переменная нигде в main не используется, не грех и выкинуть оптимизатору.
Владимир В. Р.
Nov 14 2008, 12:58
Оптимизация: None (best debug support)
Сергей Борщ
Nov 14 2008, 13:40
Цитата(Владимир В. Р. @ Nov 14 2008, 14:52)

Вот... собственно всё что есть...
Для оформления исходников существует кнопка '#' на форме ввода. Читать неформатированный исходник очень трудно.
Цитата(Владимир В. Р. @ Nov 14 2008, 14:52)

Исходники:
astartup.s79:
А попробуйе для эксперимента убрать этот файл из проекта. IAR подключит свой библиотечный файл, в котором точно вызываются конструкторы.
Цитата(Владимир В. Р. @ Nov 14 2008, 14:52)

Код
;------------------------------------------------------------------------------
; Initialize segments.
;------------------------------------------------------------------------------
; __segment_init is assumed to use
; instruction set and to be reachable by BL from the ICODE segment
; (it is safest to link them in segment ICODE).
;------------------------------------------------------------------------------
EXTERN __segment_init
ldr r0,=__segment_init
mov lr, pc
bx r0
;------------------------------------------------------------------------------
;- Branch on C code Main function (with interworking)
;------------------------------------------------------------------------------
EXTERN main
PUBLIC __main
?jump_to_main:
ldr lr,=?call_exit
ldr r0,=main
__main:
bx r0
Собственно между этими двумя кусками кода и должен быть вызов конструкторов. Вот эта информация может вам помочь:
Код
/*
* Function: __call_ctors
*
* Description: Call each constructor for each global object defined
* in the application.
*
* The constructors are placed in a segment named DIFUNCT.
* This function is assumed to be called from the cstartup
* assembler routine using code similar to:
* MOV SFB DIFUNCT, <first argument register>
* MOV SFE DIFUNCT, <second argument register>
*/
void __call_ctors(__difunct_ptr start0, __difunct_ptr end_plus_one)
LessNik
Nov 14 2008, 14:49
Также может помочь: "Папка с иаром"\arm\src\lib\crt . Там два файла. В cmain_ctx.s79 объясняется, как вызвать конструкторы глобальных объектов.
Владимир В. Р.
Nov 17 2008, 05:07
Цитата(Сергей Борщ @ Nov 14 2008, 21:40)

Для оформления исходников существует кнопка '#' на форме ввода. Читать неформатированный исходник очень трудно.
А попробуйе для эксперимента убрать этот файл из проекта. IAR подключит свой библиотечный файл, в котором точно вызываются конструкторы.Собственно между этими двумя кусками кода и должен быть вызов конструкторов. Вот эта информация может вам помочь:
Код
/*
* Function: __call_ctors
*
* Description: Call each constructor for each global object defined
* in the application.
*
* The constructors are placed in a segment named DIFUNCT.
* This function is assumed to be called from the cstartup
* assembler routine using code similar to:
* MOV SFB DIFUNCT, <first argument register>
* MOV SFE DIFUNCT, <second argument register>
*/
void __call_ctors(__difunct_ptr start0, __difunct_ptr end_plus_one)
отключил свой astartup.s79, сstartup_sam7.c и переписал вектор прерываний как:
NAME __vector_table:
EXTERN __program_start
EXTERN OS_CPU_IRQ_ISR
EXTERN OS_CPU_FIQ_ISR
Код
CODE32
COMMON INTVEC:CODE:ROOT
org 0x00
ldr pc,[pc,#24]; Absolute jump can reach 4 GByte
org 0x04
ldr pc,[pc,#24]; Branch to undef_handler
org 0x08
ldr pc,[pc,#24]; Branch to swi_handler
org 0x0c
ldr pc,[pc,#24]; Branch to prefetch_handler
org 0x10
ldr pc,[pc,#24]; Branch to data_handler
org 0x18
ldr pc,[pc,#24]; Branch to irq_handler
org 0x1c
ldr pc,[pc,#24]; Branch to fiq_handler
; Constant table entries (for ldr pc) will be placed at 0x20
; Exception vectors can be specified in C code by #pragma vector or by filling
; in the vectors below. The vector address is the ARM vector number + 0x20.
org 0x20
dc32 __program_start
org 0x24
dc32 ?call_exit
org 0x28
dc32 ?call_exit
org 0x2c
dc32 ?call_exit
org 0x30
dc32 ?call_exit
org 0x38
dc32 OS_CPU_IRQ_ISR
org 0x3c
dc32 OS_CPU_FIQ_ISR
;------------------------------------------------------------------------------
;- Loop for ever
;------------------------------------------------------------------------------
;- End of application. Normally, never occur.
;- Could jump on Software Reset ( B 0x0 ).
;------------------------------------------------------------------------------
?call_exit:
End
b End
END
Помогло, конструкторы вызываються, хотя смущает что выдаёт предупреждение, где он второй вектор нашёл?:
Warning[w52]: More than one definition for the byte at address 0 in common segment INTVEC. It is defined in module "?RESET" as well as in module "__vector_table"
P.S. Всем отписавшимся в теме спасибо!
P.S.S Сергею Борщу отдельное спасибо за '#'
Сергей Борщ
Nov 17 2008, 10:57
Цитата(Владимир В. Р. @ Nov 17 2008, 07:07)

Помогло, конструкторы вызываються, хотя смущает что выдаёт предупреждение, где он второй вектор нашёл?:
У себя в библиотеке, вестимо. Выкиньте из своего кода
Код
org 0x00
ldr pc,[pc,#24]; Absolute jump can reach 4 GByte
org 0x20
dc32 __program_start
"и сразу польется вода!"