I'm trying to move my _start function to 0x0, as it is the bootloader.
Flash ROM exists from 0x0 to the first 128MB (=1Gb), other memory is DDR3 RAM but we will map RAM to 0x80000000 to 0xFFFFFFFF.
The issue is with the directive .section ".vect", the _start address is not going into the .vect section, it is going into the .text section.
_start:
.section ".vect" /* I've tried .section .vect and I've tried moving above _start */
b ResetHandler
b UndefHandler
b SVC_Handler
b PrefetchAbortHandler
b DataAbortHandler
b NotUsedHandler
b IRQ_Handler
b FIQ_Handler
1:
b 1b /* Hang and don't return */
In my linker script, the MEMORY command and then the start of SECTIONS is:
MEMORY
{
vect (rx) : o = 0x0, l = 1M
rom (rx) : o = 1M, l = 127M
ram (wx) : o = 0x80000000, l = 0x80000000
}
SECTIONS
{
.vect : ALIGN(64)
{
. = 0x0;
*(.vect*)
VectTableEnd = .;
VectTableSize = SIZEOF(.vect);
} > vect
.... (.text, .bss, .data, .stack, etc are other SECTIONS entries)
}
But no matter what, the _start assembly function code gets shoved into the standard .text section, not at address 0x0. Does anyone know what I'm going wrong?
The code is targetted at bare-metal ARMv7A machines, compiled/linked with arm-none-eabi-as/ld
Cheers.
No surprises here if your _start label ends up in .text:
/* implicitly default section .text */
_start:
/* still the same section .text */
.section .vect
/* explicitly the section .vect */
b ResetHandler
You probably want to switch the section before defining the _start label to make that label end up in the intended section.
/* implicitly default section .text */
.section .vect
/* explicitly the section .vect */
_start:
b ResetHandler
Using the name _start as the symbol for a vector table is a bit weird (I would have expected a symbol like __vectors or vector_table), but that is beyond the scope of this question.
Related
I have my linker script with such memory layout
MEMORY{
ram : ORIGIN = 0x0, LENGTH = 0x1000 /* 4KB of RAM starting at address 0x0 */
flash : ORIGIN = 0x20000000, LENGTH = 0xC000 /* 48KB of flash starting at address 0x20000000 */
}
and I want to add two section in the very end of my flash(let's say .section1 and .section2)
but I don't know the length of my section unless I compile it
In my expectation, my flash layout will look like this:
start address
section
0x20000000
.text
0x20000000+.text size
.data
0x20000000+.text size + .data size
.mdata
0x20000000+.text size + .data size + .mdata
(empty flash)
0x2000C000-.section2 size - section1 size
.section1
0x2000C000-.section2 size
.section2
How should I do in my linker script?
I don't know how to wrote it for now I just force my address like this. but its not what I want.
.section1 :{
*(.section1)
} >flash :AT (0x2000A000)
.section2 :{
*(.section2)
} >flash :AT (0x2000B000)
I am trying to execute a simple code from RAM, but for some reason the program halts/throws hard fault. I am using CCMRAM for my data, heap and stack while SRAM1 for executing code. Here is my linker script and startup file.
LinkerScript.ld
/*
******************************************************************************
**
** File : LinkerScript.ld
**
** Author : Auto-generated by Ac6 System Workbench
**
** Abstract : Linker script for STM32F407ZETx Device from STM32F4 series
** 112Kbytes SRAM1
** 16Kbytes SRAM2
** 64Kbytes CCMRAM
** 512Kbytes ROM
**
** Set heap size, stack size and stack location according
** to application requirements.
**
** Set memory bank area and size if external memory is used.
**
** Target : STMicroelectronics STM32
**
** Distribution: The file is distributed �as is,� without any warranty
** of any kind.
**
*****************************************************************************
** #attention
**
** <h2><center>© COPYRIGHT(c) 2019 Ac6</center></h2>
**
** Redistribution and use in source and binary forms, with or without modification,
** are permitted provided that the following conditions are met:
** 1. Redistributions of source code must retain the above copyright notice,
** this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright notice,
** this list of conditions and the following disclaimer in the documentation
** and/or other materials provided with the distribution.
** 3. Neither the name of Ac6 nor the names of its contributors
** may be used to endorse or promote products derived from this software
** without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
*****************************************************************************
*/
/* Entry Point */
ENTRY(Reset_Handler)
/* Highest address of the user mode stack */
/*_estack = 0x2001C000; /* start of SRAM2 */
_estack = 0x10010000; /* end of CCMRAM */
_Min_Heap_Size = 0; /* required amount of heap */
_Min_Stack_Size = 0x400; /* required amount of stack */
/* Memories definition */
MEMORY
{
SRAM1 (xrw) : ORIGIN = 0x20000000, LENGTH = 112K
SRAM2 (xrw) : ORIGIN = 0x2001C000, LENGTH = 16K
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 512K
CCMRAM (rw) : ORIGIN = 0x10000000, LENGTH = 64K
}
/* Sections */
SECTIONS
{
/* The startup code into ROM memory */
.isr_vector :
{
. = ALIGN(4);
KEEP(*(.isr_vector)) /* Startup code */
. = ALIGN(4);
} >FLASH
/*sram1 section for code and data*/
_sisram1 = LOADADDR(.sram1);
.sram1 :
{
. = ALIGN(4);
_s_sram1 = .;
*(.sram1);
*(.sram1*);
. = ALIGN(4);
_e_sram1 = .;
} > SRAM1 AT >FLASH
/*sram2 section for code and data*/
_sisram2 = LOADADDR(.sram2);
.sram2 :
{
. = ALIGN(4);
_s_sram2 = .;
*(.sram2);
*(.sram2*);
. = ALIGN(4);
_e_sram2 = .;
} > SRAM2 AT >FLASH
/* The program code and other data into FLASH memory */
.text :
{
. = ALIGN(4);
*(.text) /* .text sections (code) */
*(.text*) /* .text* sections (code) */
*(.glue_7) /* glue arm to thumb code */
*(.glue_7t) /* glue thumb to arm code */
*(.eh_frame)
KEEP (*(.init))
KEEP (*(.fini))
. = ALIGN(4);
_etext = .; /* define a global symbols at end of code */
} >FLASH
/* Constant data into FLASH memory*/
.rodata :
{
. = ALIGN(4);
*(.rodata) /* .rodata sections (constants, strings, etc.) */
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
. = ALIGN(4);
} >FLASH
.ARM.extab : {
. = ALIGN(4);
*(.ARM.extab* .gnu.linkonce.armextab.*)
. = ALIGN(4);
} > FLASH
.ARM : {
. = ALIGN(4);
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
. = ALIGN(4);
} >FLASH
.preinit_array :
{
. = ALIGN(4);
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array*))
PROVIDE_HIDDEN (__preinit_array_end = .);
. = ALIGN(4);
} >FLASH
.init_array :
{
. = ALIGN(4);
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array*))
PROVIDE_HIDDEN (__init_array_end = .);
. = ALIGN(4);
} >FLASH
.fini_array :
{
. = ALIGN(4);
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT(.fini_array.*)))
KEEP (*(.fini_array*))
PROVIDE_HIDDEN (__fini_array_end = .);
. = ALIGN(4);
} >FLASH
/* Used by the startup to initialize data */
_sidata = LOADADDR(.data);
/* Initialized data sections into RAM memory */
.data :
{
. = ALIGN(4);
_sdata = .; /* create a global symbol at data start */
*(.data) /* .data sections */
*(.data*) /* .data* sections */
. = ALIGN(4);
_edata = .; /* define a global symbol at data end */
} >CCMRAM AT> FLASH
/* Uninitialized data section into RAM memory */
. = ALIGN(4);
.bss :
{
/* This is used by the startup in order to initialize the .bss secion */
_sbss = .; /* define a global symbol at bss start */
__bss_start__ = _sbss;
*(.bss)
*(.bss*)
*(COMMON)
. = ALIGN(4);
_ebss = .; /* define a global symbol at bss end */
__bss_end__ = _ebss;
} >CCMRAM
/* User_heap_stack section, used to check that there is enough RAM left */
._user_heap_stack :
{
. = ALIGN(8);
PROVIDE ( end = . );
PROVIDE ( _end = . );
. = . + _Min_Heap_Size;
. = . + _Min_Stack_Size;
. = ALIGN(8);
} >CCMRAM
/* Remove information from the compiler libraries */
/DISCARD/ :
{
libc.a ( * )
libm.a ( * )
libgcc.a ( * )
}
.ARM.attributes 0 : { *(.ARM.attributes) }
}
And here is part of my startup file
/**
******************************************************************************
* #file startup_stm32.s dedicated to STM32F407ZETx device
* #author Ac6
* #version V1.0.0
* #date 2019-03-30
******************************************************************************
*/
.syntax unified
.cpu cortex-m4
.fpu softvfp
.thumb
.global g_pfnVectors
.global Default_Handler
/* start address for the initialization values of the .data section.
defined in linker script */
.word _sidata
/* start address for the .data section. defined in linker script */
.word _sdata
/* end address for the .data section. defined in linker script */
.word _edata
/* start address for the .bss section. defined in linker script */
.word _sbss
/* end address for the .bss section. defined in linker script */
.word _ebss
/**
* #brief This is the code that gets called when the processor first
* starts execution following a reset event. Only the absolutely
* necessary set is performed, after which the application
* supplied main() routine is called.
* #param None
* #retval : None
*/
.section .text.Reset_Handler
.weak Reset_Handler
.type Reset_Handler, %function
Reset_Handler:
ldr r0, =_estack
mov sp, r0 /* set stack pointer */
/* Copy the data segment initializers from flash to SRAM */
ldr r0, =_sdata
ldr r1, =_edata
ldr r2, =_sidata
movs r3, #0
b LoopCopyDataInit
CopyDataInit:
ldr r4, [r2, r3]
str r4, [r0, r3]
adds r3, r3, #4
LoopCopyDataInit:
adds r4, r0, r3
cmp r4, r1
bcc CopyDataInit
/* Zero fill the bss segment. */
ldr r2, =_sbss
ldr r4, =_ebss
movs r3, #0
b LoopFillZerobss
FillZerobss:
str r3, [r2]
adds r2, r2, #4
LoopFillZerobss:
cmp r2, r4
bcc FillZerobss
///////////// Following blocks are for SRAM1 /////////////////////
// Copy from flash to SRAM1
ldr r0, =_s_sram1
ldr r1, =_e_sram1
ldr r2, =_sisram1
movs r3, #0
b LoopCopySRAM1Init
CopySRAM1Init:
ldr r4, [r2, r3]
str r4, [r0, r3]
adds r3, r3, #4
LoopCopySRAM1Init:
adds r4, r0, r3
cmp r4, r1
bcc CopySRAM1Init
// End of data copy from Flash to SRAM1
// Zero fill the SRAM1 segment.
ldr r2, =_s_sram1
b LoopFillZeroSRAM1
FillZeroSRAM1:
movs r3, #0
str r3, [r2]
adds r2, r2, #4
LoopFillZeroSRAM1:
ldr r3, = _e_sram1
cmp r2, r3
bcc FillZeroSRAM1
//////////////// End of SRAM1 Blocks /////////////////
///////////// Following blocks are for SRAM2 /////////////////////
// Copy from flash to SRAM2
ldr r0, =_s_sram2
ldr r1, =_e_sram2
ldr r2, =_sisram2
movs r3, #0
b LoopCopySRAM2Init
CopySRAM2Init:
ldr r4, [r2, r3]
str r4, [r0, r3]
adds r3, r3, #4
LoopCopySRAM2Init:
adds r4, r0, r3
cmp r4, r1
bcc CopySRAM2Init
// End of data copy from Flash to SRAM2
// Zero fill the SRAM2 segment.
ldr r2, =_s_sram2
b LoopFillZeroSRAM2
FillZeroSRAM2:
movs r3, #0
str r3, [r2]
adds r2, r2, #4
LoopFillZeroSRAM2:
ldr r3, = _e_sram2
cmp r2, r3
bcc FillZeroSRAM2
//////////////// End of SRAM2 Blocks /////////////////
/* Call the clock system intitialization function.*/
bl SystemInit
/* Call static constructors */
bl __libc_init_array
/* Call the application's entry point.*/
bl main
LoopForever:
b LoopForever
Can anybody please help me if there is any bug here. Lets say, for now we are only trying to run code from SRAM1 since that is the one which is connected to I-bus and D-bus ports of the Cortex M4 on this MCU. With respect to the picture below, I would expect bl to be jumping to beginning of SRAM1.. Can you please shed some light on it:
According to the screen captures, your code is jumping to SRAM (as expected) but there is no code in SRAM (MOV R0 R0 indicates the memory is filled with 0s) hence the hardFault.
You have to copy from Flash to RAM the code that you want to execute in RAM.
I'm currently writing a program on STM32 that uses a simple bootloader and two sub-applications. The sub-applications are located in flash memory and the bootloader loads one of them (both code and data) into the RAM memory and then starts executing it. The copying is done simply by iterating over the addresses in flash and copying data from these addresses to RAM.
Recently I've encountered some strange bug. I was trying to read some data from a globally defined array. I was getting back wrong values, e.g. when I tried to read array[0] I was getting back the value of array[1].
I did some debugging and disassembly of the .elf and .hex files and I think I've found the cause of this bug. It turned out that there is an empty space between the .ARM section of the .elf file of this project.
Surprisingly, this empty space is not present in the .hex file (which I use for flashing the STM32 board).
This is what I am talking about:
.elf file:
2000ee70: 469e mov lr, r3
2000ee72: 4770 bx lr
Disassembly of section .ARM:
2000ee74 <__exidx_start>:
2000ee74: 7fff267c svcvc 0x00ff267c
2000ee78: 00000001 andeq r0, r0, r1
Disassembly of section .data:
2000ee80 <evnames.5255>:
2000ee80: 00000000 andeq r0, r0, r0
2000ee84: 08030104 stmdaeq r3, {r2, r8}
.hex file:
802de70: 4770469e
802de74: 7fff267c svcvc 0x00ff267c
802de78: 00000001 andeq r0, r0, r1
802de7c: 00000000 andeq r0, r0, r0
802de80: 08030104 stmdaeq r3, {r2, r8}
Obviously, the addresses are different because the addresses in the .elf file are VMA and the addresses in the .hex file are LMA.
What I've noticed here is that after the .ARM section, the next memory address should be 2000ee7C but from unknown reasons, the .data section begins at 2000ee80. So there is one unexplained, empty word between them. But this empty word is not present in the .hex file. The 00000001 is immediately followed by 00000000.
So basically, I think the disassembly of the .hex file should output the following result:
802de70: 4770469e
802de74: 7fff267c svcvc 0x00ff267c
802de78: 00000001 andeq r0, r0, r1
802de7c: <something here>
802de80: 00000000 andeq r0, r0, r0
802de84: 08030104 stmdaeq r3, {r2, r8}
Because of this empty memory space, which disappears in the .hex file, when my bootloader loads the data to RAM, the array[0] which LMA is 2000eec8 ends up being at the address 2000eec4.
This is the troubling snippet of the linker script that I use:
/* ARM specific sections, they also go to FLASH and are copied to RAM */
.ARM.extab : {
*(.ARM.extab* .gnu.linkonce.armextab.*)
} > RAMAPP AT> FLASH_APP
.ARM : {
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
} > RAMAPP AT> FLASH_APP
/* Initialized data sections - variables etc. */
.data :
{
. = ALIGN(4);
*(.data) /* .data sections */
*(.data*) /* .data* sections */
. = ALIGN(4);
} >RAMAPP AT> FLASH_APP /* Data section is placed in FLASH_APP but its Virtual Memory Address is in RAM_APP */
I use the following command to link the .o files into one .elf file:
arm-none-eabi-gcc -Wl,--gc-sections -mthumb -mthumb-interwork -mcpu=cortex-m4 --specs=nosys.specs -L[path_to_library_files] -T[path_to_ld_file] [long_list_of_object_files] -o [output_elf_file]
I use the following command to convert the .elf file into the .hex file:
arm-none-eabi-objcopy -O ihex [elf_file] [output_hex_file]
I've tried to experiment with the parameters I give to the arm-none-eabi-objcopy and arm-none-eabi-gcc to get rid of this padding, for example --file-alignment or --gap-fill but to no success so far.
Does anyone have an idea about where does this empty space come from and how to get rid of it (or include it in the .hex file)?
EDIT: According to the suggestions from the first two comments, I've tried:
* using the newest versions of arm-none-eabi-gcc and arm-none-eabi-objcopy in my toolchain,
* ALIGN(4) of the .ARM section,
* not copying the .ARM section to RAM.
Unfortunately, none of these solutions fixed this problem.
What I've noticed recently is that sometimes the data is aligned correctly in the .elf file (the first address of the .data section is the address that immediately follows the end of the .ARM section). It depends on the address where the .ARM section happens to end. I can manipulate that by adding some extra function invocations in the code (resulting in the larger .text area), for example:
2000ee84: 469e mov lr, r3
2000ee86: 4770 bx lr
Disassembly of section .ARM:
2000ee88 <__exidx_start>:
2000ee88: 7fff2668 svcvc 0x00ff2668
2000ee8c: 00000001 andeq r0, r0, r1
Disassembly of section .data:
2000ee90 <evnames.5255>:
2000ee90: 00000000 andeq r0, r0, r0
2000ee94: 2001111c andcs r1, r1, ip, lsl r1
This way, I've estabilished that:
* when .ARM section ends at address 0x*******0 the .data section incorrectly starts at 0x*******8 (should be 0x*******4)
* when .ARM section ends at address 0x*******8 the .data section incorrectly starts at 0x*******0 (should be 0x*******C)
* when .ARM section ends at address 0x*******4 the .data section CORRECTLY starts at 0x*******8
* when .ARM section ends at address 0x*******C the .data section CORRECTLY starts at 0x*******0
Okay, It turned out I had to add ALIGN_WITH_INPUT to the .data section in the linker script. Like this:
.data : ALIGN_WITH_INPUT
{
. = ALIGN(4);
*(.data) /* .data sections */
*(.data*) /* .data* sections */
. = ALIGN(4);
} >RAMAPP AT> FLASH_APP
This parameter causes the LMAs of the section to be aligned in the same way the VMAs are.
Now the alignment in the .hex file is identical to the one in the .elf file.
Shout out to reddit user FreddieChopin who helped me to resolve this issue.
Trying to get an interrupt on A3, to wake the cpu up from sleep on a rx char, but it's not firing.
What is it that defines which interrupt the GPIO pin will trigger? I can't find it in the reference manual
static void EXTI0_1_IRQHandler_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* Enable GPIOA clock */
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitStructure.Mode = GPIO_MODE_IT_RISING;
GPIO_InitStructure.Pull = GPIO_NOPULL;
GPIO_InitStructure.Pin = GPIO_PIN_3;
HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Enable and set EXTI line 0 Interrupt to the lowest priority */
HAL_NVIC_SetPriority(EXTI0_1_IRQn, 2, 0);
HAL_NVIC_EnableIRQ(EXTI0_1_IRQn);
}
Interrupt functions are (briefly) described in Chapter 11 Interrpts and events, Section 11.1.3 Interrupt and exception vectors.
So, the interrupt number is EXTI2_3_IRQn, and you should define EXTI2_3_IRQHandler() to call HAL_GPIO_EXTI_IRQHandler().
Some background
There are a couple of steps involved in getting a callback function called when an interrupt request occurs.
Each interrupt request has an interrupt number assigned to it, see the Position entry in the table above. The number is defined by the hardware, the symbolic name is assigned somewhere in the machine headers.
typedef enum {
[...]
EXTI0_1_IRQn = 5, /*!< EXTI Line 0 and 1 Interrupt */
EXTI2_3_IRQn = 6, /*!< EXTI Line 2 and 3 Interrupt */
[...]
} IRQn_Type;
There is a corresponding function pointer in the vector table, which should contain the address of the handler function. This vector table is filled out in the startup module, which is called startup_stm32f030x8.s or something similar, and the linker configuration file ensures that the table ends up at the proper physical address when programming the flash.
g_pfnVectors:
.word _estack
.word Reset_Handler
.word NMI_Handler
.word HardFault_Handler
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word SVC_Handler
.word 0
.word 0
.word PendSV_Handler
.word SysTick_Handler
.word WWDG_IRQHandler /* Window WatchDog */
.word 0 /* Reserved */
.word RTC_IRQHandler /* RTC through the EXTI line */
.word FLASH_IRQHandler /* FLASH */
.word RCC_IRQHandler /* RCC */
.word EXTI0_1_IRQHandler /* EXTI Line 0 and 1 */
.word EXTI2_3_IRQHandler /* EXTI Line 2 and 3 */
...
The entries are in fixed order, since the hardware only cares about the numeric address. Whenever an EXTI2 or EXTI3 event occurs, and IRQ6 is enabled, it jumps to the address at 0x00000058. The table above ensures that the address of EXTI2_3_IRQHandler() goes into the vector table at 0x00000058.
Digging further in the startup module we find this
.weak EXTI0_1_IRQHandler
.thumb_set EXTI0_1_IRQHandler,Default_Handler
.weak EXTI2_3_IRQHandler
.thumb_set EXTI2_3_IRQHandler,Default_Handler
and this
Default_Handler:
Infinite_Loop:
b Infinite_Loop
It means that if there is no definition for EXTI0_1_IRQHandler() or EXTI2_3_IRQHandler(), then they invoke an infinite loop, good for debugging but nothing else. In order to actually use it, you must override this symbol in your program. If you look at the GPIO_EXTI example, it has this handler
void EXTI0_1_IRQHandler(void)
{
HAL_GPIO_EXTI_IRQHandler(USER_BUTTON_PIN);
}
defined in stm32f0xx_it.c to call HAL_GPIO_EXTI_IRQHandler() when an EXTI0 interrupt occurs. If you'd like to act on EXTI3, then you should have a similar function
void EXTI2_3_IRQHandler(void)
{
HAL_GPIO_EXTI_IRQHandler(3);
}
to call HAL_GPIO_EXTI_IRQHandler().
I work on Atom-32bit-intel, I have to port MicroC OS II, so there is no code to make any configuration on the Atom (No GDT, no LDT...):
my question is more about the state of the Atom-32bit after a reset, is the Atom in protecte mode or not ? and the most important how do i check which mode is it (which registers have to be checked nad how)?
Remark:
The CR0.PE = 1 (I checked it), is that enough to prove that the Atom is in protected mode ?
************ UPDATE : *****************
/*Read the IDTR*/
sidt (idt_ptr)
/*Read the GDTR*/
sgdt (gdt_ptr)
So I tried just to use IDT's address to link my ISR to the IDT :
fill_interrupt(ISR_Nbr,(unsigned int) isr33, 0x08, 0x8E);
static void fill_interrupt(unsigned char num, unsigned int base, unsigned short sel, unsigned char flags)
{
unsigned short *Interrupt_Address;
/*address = idt_ptr.base + num * 8 byte*/
Interrupt_Address = (unsigned short *)(idt_ptr.base + num*8);
*(Interrupt_Address) = base&0xFFFF;
*(Interrupt_Address+1) = sel;
*(Interrupt_Address+1) = (flags>>8)&0xFF00;
*(Interrupt_Address+1) = (base>>16)&0xFFFF;
}
my ISR a imple one :
isr33:
nop
nop
cli
push %ebp //save the context to swith back
mov %esp,%ebp
pop %ebp //Return to the calling function
sti
ret
Chapter 9 of volume 3 of the Intel Software Developer's Manual says that the reset value of CR0 is 60000010H. As you can see, bit 0, aka PE, is clear.
Regardless, you can setup the descriptor tables in Protected Mode as well as in Real Mode. You just have to be more careful about it.
I suggest you check if the BIOS or OS are setting this bit at a stage before you read it.
Atom is x86 instruction set, and as such, should be starting in real mode for compatibility. I don't have one on hand to test with though.
Resolved, I use N450 Atom board, it has already a BIOS, the BIOS configures the board in Protected Mode.