FreeRTOS Support Archive
The FreeRTOS support forum is used to obtain active support directly from Real
Time Engineers Ltd. In return for using our top quality software and services for
free, we request you play fair and do your bit to help others too! Sign up
to receive notifications of new support topics then help where you can.
This is a read only archive of threads posted to the FreeRTOS support forum.
The archive is updated every week, so will not always contain the very latest posts.
Use these archive pages to search previous posts. Use the Live FreeRTOS Forum
link to reply to a post, or start a new support thread.
[FreeRTOS Home] [Live FreeRTOS Forum] [FAQ] [Archive Top] [February 2006 Threads] ARM Error: invalid literal constant: pool neePosted by Nobody/Anonymous on February 23, 2006 Hi, I'm experimenting an odd problem with a FreeRTOS macro as the code grows bigger:
I'm using an ATMEL EB40A ev. board and GCC 4.02 WinARM dev. environment, and my application runs fairly good. The problem is that my code has grown big (.text is about 0x12000 bytes large) and the portSAVE_CONTEXT() and restore() macros stopped working: the compiler stops reporting: "Error: invalid literal constant: pool needs to be closer" several times (one per far data reference). It looks that the referred variables like: asm volatile ( "LDRR0, =ulCriticalNesting " ); are now too far to be directly referred (the compiler address them storing their address in local constants). I hope to have clearly pointed out the problem but, sorry, my knowledge of the ARM assembly language is not enough to solve this problem by myself... Can anybody help me? Thank you in advance.
RE: ARM Error: invalid literal constant: pool neePosted by Nobody/Anonymous on February 23, 2006 I would guess that the difference in address to the critical nesting function from where it is called is too great for encoding into the instruction but this is a guess. Try searching on the net for the error message.
RE: ARM Error: invalid literal constant: pool neePosted by Nobody/Anonymous on February 23, 2006 Yes, you are almost right: ulCriticalNesting is a variable, that this ARM asm code addresses using an offset based on the current PC. ARM relative indirection tange is somewhat limited and the distance between my last ISR routine (referring the variable) and the variable itself is too large to be covered by this kind of address mode. But I'm not an ARM asm coder and I don't know how to work it out :(
RE: ARM Error: invalid literal constant: pool neePosted by Nobody/Anonymous on February 23, 2006 Yes, I think this is the problem too: ulCriticalNesting is a variable, that this ARM asm code addresses using an offset based on the current PC. ARM relative indirection tange is somewhat limited and the distance between my last ISR routine (referring the variable) and the variable itself is too large to be covered by this kind of address mode. But, sorry, I'm not an ARM asm coder and I don't know how to work it out :(
RE: ARM Error: invalid literal constant: poolPosted by Jokke on February 24, 2006 The trick is to use another addressing mode. You put the value ulCriticalNesting in aplace close to the code, and then you refer to that location. You shall be able to see examples of this in the start-up code, where they have used this tecnique. In boot.s in one of the gcc example projects you find: ldrr1, .LC3 ... .LC3: .word __data_beg__
From this you should be able to solve your problem.
Regards Jokke
RE: ARM Error: invalid literal constant: pool neePosted by Nobody/Anonymous on February 24, 2006 Hi Jokke, sure, I considered using this workaround (this is the trick used by the C compiler to address it), but it doesn't solve the main problem: I'd like to place this declaration INSIDE the macros themselves, by using something like the old "local" or "private" directive to avoid generating duplicate symbols... I don't know if this kind of construct exists in this asm. Using a location OUTSIDE of the macro implies that I have to change the location name inside the macro at any usage, so I cannot use the plain macro... (but perhaps one can write a C macro substituting the "__var_addr__" symbol automagically). Does anybody know the ARM gas syntax well enough to manage this problem? Thank you.
RE: ARM Error: invalid literal constant: poolPosted by Oliver on November 14, 2007 Hi,
I have the same problem, as my code size increases.
I'm using FreeRTOS 4.6.0 with WinARM-20060606, compiling for a LPC2294.
Here is an example of the error message: arm-elf-gcc -c -mcpu=arm7tdmi-s -I. -gdwarf-2 -DXRAM_RUN -D GCC_ARM7 -D__WinARM__ -I ./import -I ./serial -I ./candrv -I ./debugTask -I ./canTask -I ./eeprom -O0 -Wall -Wextra -Wshadow -Wpointer-arith -Wbad-function-cast -Wcast-align -Wsign-compare -Waggregate-return -Wunused -I../FreeRTOS/V4.6.0/Source/include -fomit-frame-pointer -fsigned-char -save-temps -MD -MP -MF .dep/main.o.d -std=gnu99 -Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations main.c -o main.o main.s: Assembler messages: main.s:598: Error: invalid literal constant: pool needs to be closer
The assembler listing for this reads (Line 598 is the one refering to ulCriticalNesting): SUBLR, LR, #60 MRSR0, SPSR STMDBLR!, {R0} LDRR0, =ulCriticalNesting LDRR0, [R0] STMDBLR!, {R0} LDRR0, =pxCurrentTCB LDRR0, [R0] STRLR, [R0]
Has someone already improved the portSAVE_CONTEXT / portRESTORE_CONTEXT macros to be able to handle larger code sizes?
Regards, Oliver
RE: ARM Error: invalid literal constant: pool neePosted by Quantum Leaps on November 15, 2007 Try the GCC-ARM option -mlong-calls. This option replaces BL instructions with BX r? instructions. The B/BL instruction can reach only +/-4MB in Thumb in +/-32MB in ARM. The BX instruciton has access to the whole 32-bit address space (4GB).
RE: ARM Error: invalid literal constant: poolPosted by Oliver on November 15, 2007 Hi,
thanks for your response. I tried -mlong-calls, but unfortunately it doesn't make any difference.
I'm just beginning to learn ARM ASM but as far as I understand the code, it's not a branch that fails but the instruction that's trying to load the address of the C-variable ulCriticalNesting into R0.
Regards, Oliver
RE: ARM Error: invalid literal constant: poolPosted by madis on November 15, 2007 Hi!
I encountered that problem in a project coded entirely in asm. I solved it by inserting .ltorg to some places the problem occured. Try googling for it and try to insert it into your code somewhere. I don't know how to insert it within c function so that arm wont execute your literals (I added it to the asm file, then it was really straightforward).
Try playing with asm() and check assembler output how it compiles. That .ltorg needs to get inserted between two functions, basically. Or you can try to branch over it within asm()... just few ideas.
Madis
RE: ARM Error: invalid literal constant: poolPosted by Oliver on November 15, 2007 Hi, I had no luck with the .ltorg. Maybe because it is used inside an asm() statement. I were able to work around it manually, but this requires a branch over the data definition.
I feel that there must be a more elegant solution using input and clobber lists to the asm statement.
This might not be optimal, but it works for now:
#define portSAVE_CONTEXT() \ { \ extern volatile void * volatile pxCurrentTCB; \ extern volatile unsigned portLONG ulCriticalNesting; \ \ asm volatile ( \ "b 2f /* skip pool */ \n\t" \ "1: \n\t" \ ".word pxCurrentTCB \n\t" \ ".word ulCriticalNesting \n\t" \ "2: \n\t" \ /* Push R0 as we are going to use the register. */ \ "STMDB SP!, {R0} \n\t" \ \ /* Set R0 to point to the task stack pointer. */ \ "STMDB SP,{SP}^ \n\t" \ "NOP \n\t" \ "SUB SP, SP, #4 \n\t" \ "LDMIA SP!,{R0} \n\t" \ \ /* Push the return address onto the stack. */ \ "STMDB R0!, {LR} \n\t" \ \ /* Now we have saved LR we can use it instead of R0. */ \ "MOV LR, R0 \n\t" \ \ /* Pop R0 so we can save it onto the system mode stack. */ \ "LDMIA SP!, {R0} \n\t" \ \ /* Push all the system mode registers onto the task stack. */ \ "STMDB LR,{R0-LR}^ \n\t" \ "NOP \n\t" \ "SUB LR, LR, #60 \n\t" \ \ /* Push the SPSR onto the task stack. */ \ "MRS R0, SPSR \n\t" \ "STMDB LR!, {R0} \n\t" \ \ "LDR R0, 1b+4 /* =ulCriticalNesting */ \n\t" \ "LDR R0, [R0] \n\t" \ "STMDB LR!, {R0} \n\t" \ \ /* Store the new top of stack for the task. */ \ "LDR R0, 1b /* =pxCurrentTCB */ \n\t" \ "LDR R0, [R0] \n\t" \ "STR LR, [R0] \n\t" \ ); \ ( void ) ulCriticalNesting; \ ( void ) pxCurrentTCB; \ }
#define portRESTORE_CONTEXT() \ { \ extern volatile void * volatile pxCurrentTCB; \ extern volatile unsigned portLONG ulCriticalNesting; \ \ asm volatile ( \ "b 2f /* skip pool */ \n\t" \ "1: \n\t" \ ".word pxCurrentTCB \n\t" \ ".word ulCriticalNesting \n\t" \ "2: \n\t" \ /* Set the LR to the task stack. */ \ "LDR R0, 1b /* =pxCurrentTCB */ \n\t" \ "LDR R0, [R0] \n\t" \ "LDR LR, [R0] \n\t" \ \ /* The critical nesting depth is the first item on the stack. */ \ /* Load it into the ulCriticalNesting variable. */ \ "LDR R0, 1b+4 /* =ulCriticalNesting */ \n\t" \ "LDMFD LR!, {R1} \n\t" \ "STR R1, [R0] \n\t" \ \ /* Get the SPSR from the stack. */ \ "LDMFD LR!, {R0} \n\t" \ "MSR SPSR, R0 \n\t" \ \ /* Restore all system mode registers for the task. */ \ "LDMFD LR, {R0-R14}^ \n\t" \ "NOP \n\t" \ \ /* Restore the return address. */ \ "LDR LR, [LR, #+60] \n\t" \ \ /* And return - correcting the offset in the LR to obtain the */ \ /* correct address. */ \ "SUBS PC, LR, #4 \n\t" \ ); \ ( void ) ulCriticalNesting; \ ( void ) pxCurrentTCB; \ }
Regards, Oliver
RE: ARM Error: invalid literal constant: poolPosted by Oliver on April 17, 2009 Hi,
Because the code is still the same in V5.2.0 I suggest again to include the following code in the LPC2000 port (portRESTORE_CONTEXT was slightly improved compared to my last post, i moved the data behing the code, eliminating the branch). If somebody has a more elegant solution, I would be also very happy. At least this fixes the "Error: invalid literal constant: pool needs to be closer" error that can happen if the code grows bigger.
#define portRESTORE_CONTEXT() \ { \ extern volatile void * volatile pxCurrentTCB; \ extern volatile unsigned portLONG ulCriticalNesting; \ \ asm volatile ( \ /* Set the LR to the task stack. */ \ "LDR R0, 1f /* =pxCurrentTCB */ \n\t" \ "LDR R0, [R0] \n\t" \ "LDR LR, [R0] \n\t" \ \ /* The critical nesting depth is the first item on the stack. */ \ /* Load it into the ulCriticalNesting variable. */ \ "LDR R0, 2f /* =ulCriticalNesting */ \n\t" \ "LDMFD LR!, {R1} \n\t" \ "STR R1, [R0] \n\t" \ \ /* Get the SPSR from the stack. */ \ "LDMFD LR!, {R0} \n\t" \ "MSR SPSR, R0 \n\t" \ \ /* Restore all system mode registers for the task. */ \ "LDMFD LR, {R0-R14}^ \n\t" \ "NOP \n\t" \ \ /* Restore the return address. */ \ "LDR LR, [LR, #+60] \n\t" \ \ /* And return - correcting the offset in the LR to obtain the */ \ /* correct address. */ \ "SUBS PC, LR, #4 \n\t" \ \ /* Place the pool behind the code. This is never reached. */ \ "1: .word pxCurrentTCB \n\t" \ "2: .word ulCriticalNesting \n\t" \ ); \ ( void ) ulCriticalNesting; \ ( void ) pxCurrentTCB; \ } /*-----------------------------------------------------------*/
#define portSAVE_CONTEXT() \ { \ extern volatile void * volatile pxCurrentTCB; \ extern volatile unsigned portLONG ulCriticalNesting; \ \ asm volatile ( \ "b 3f /* skip data */ \n\t" \ "1: .word pxCurrentTCB \n\t" \ "2: .word ulCriticalNesting \n\t" \ "3: \n\t" \ /* Push R0 as we are going to use the register. */ \ "STMDB SP!, {R0} \n\t" \ \ /* Set R0 to point to the task stack pointer. */ \ "STMDB SP,{SP}^ \n\t" \ "NOP \n\t" \ "SUB SP, SP, #4 \n\t" \ "LDMIA SP!,{R0} \n\t" \ \ /* Push the return address onto the stack. */ \ "STMDB R0!, {LR} \n\t" \ \ /* Now we have saved LR we can use it instead of R0. */ \ "MOV LR, R0 \n\t" \ \ /* Pop R0 so we can save it onto the system mode stack. */ \ "LDMIA SP!, {R0} \n\t" \ \ /* Push all the system mode registers onto the task stack. */ \ "STMDB LR,{R0-LR}^ \n\t" \ "NOP \n\t" \ "SUB LR, LR, #60 \n\t" \ \ /* Push the SPSR onto the task stack. */ \ "MRS R0, SPSR \n\t" \ "STMDB LR!, {R0} \n\t" \ \ "LDR R0, 2b /* =ulCriticalNesting */ \n\t" \ "LDR R0, [R0] \n\t" \ "STMDB LR!, {R0} \n\t" \ \ /* Store the new top of stack for the task. */ \ "LDR R0, 1b /* =pxCurrentTCB */ \n\t" \ "LDR R0, [R0] \n\t" \ "STR LR, [R0] \n\t" \ ); \ ( void ) ulCriticalNesting; \ ( void ) pxCurrentTCB; \ }
Regards, Oliver
RE: ARM Error: invalid literal constant: poolPosted by Richard on April 17, 2009 Hi Oliver - could you post that to a feature request please? That way it won't get lost in the crowd. Thanks ;o)
Regards.
RE: ARM Error: invalid literal constant: pool neePosted by cynergizer on July 7, 2011 Oliver, I ran into the exact same problem as my code size grew to 104Kbytes. I used your solution and it fixed the problem! Thank you so much for posting this (as well as what didn't work). You saved me some hurt!
Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.
|