Hi All, I'm writing a test code trying to send a character using UART. Now that is running perfectly fine as long as i declare the character in main. void sendchar(char ch) { U0THR= ch; while (!(U0LSR & 0x20)); } int main() { unsigned char tc= 'a'; .................... .................... while(1) { sendchar(tc); } } This runs like anything but when i make the character global, nothing is sent. I figure it has something to do wid my ROM.ld which looks like: ENTRY(_boot) STACK_SIZE = 0x800; /* Memory Definitions */ /* lpc2129 mt */ MEMORY { ROM (rx) : ORIGIN = 0x00000000, LENGTH = 0x0003E000 RAM (rw) : ORIGIN = 0x40000000, LENGTH = 0x00004000 } /* Section Definitions */ SECTIONS { /* first section is .text which is used for code */ .text : { KEEP(*(.init)) /* Startup code from .init-section */ *(.text .text.*) /* remaining code */ *(.gnu.linkonce.t.*) *(.glue_7) *(.glue_7t) *(.gcc_except_table) *(.rodata) /* read-only data (constants) */ *(.rodata*) *(.gnu.linkonce.r.*) } > ROM /***** old: .text : { *crt0.o (.text) *(.text) *(.rodata) *(.rodata*) *(.glue_7) *(.glue_7t) } > ROM *****/ . = ALIGN(4); /* .ctors .dtors are used for c++ constructors/destructors */ /* added by Martin Thomas 4/2005 based on Anglia Design example */ .ctors : { PROVIDE(_ctors_start_ = .); KEEP(*(SORT(.ctors.*))) KEEP(*(.ctors)) PROVIDE(_ctors_end_ = .); } >ROM .dtors : { PROVIDE(_dtors_start_ = .); KEEP(*(SORT(.dtors.*))) KEEP(*(.dtors)) PROVIDE(_dtors_end_ = .); } >ROM . = ALIGN(4); /* mthomas - end */ _etext = . ; PROVIDE (etext = .); /* .data section which is used for initialized data */ .data : AT (_etext) { _data = .; *(.data) *(.data.*) *(.gnu.linkonce.d*) SORT(CONSTRUCTORS) /* mt 4/2005 */ . = ALIGN(4); *(.fastrun) } > RAM . = ALIGN(4); _edata = . ; PROVIDE (edata = .); /* .bss section which is used for uninitialized data */ .bss (NOLOAD): { __bss_start = . ; _bss_start_ = . ; *(.bss) *(.gnu.linkonce.b*) *(COMMON) . = ALIGN(4); } > RAM . = ALIGN(4); _bss_end_ = . ; PROVIDE (__bss_end = .); .stack : { . = ALIGN(256); . += STACK_SIZE; PROVIDE (_stack = .); } > RAM _end = . ; PROVIDE (end = .); Is there any problem here or the *(COMMON)? I tried deleting (NOLOAD) but that caused .stack to fail. Other functions werent being called so i assumed that.. Can anyone tell wat i'm doing wrong?
Also global variables should be in the data section i presume, I have no idea wats going wrong then!
So you posted the code that works but merely described the code that fails! Now let's think... what could possibly be the flaw in that approach to asking questions!? It seems to be if nothing is being sent than sendchar is not being called. How are you testing this? If the global is not initialised it may be sending NUL and most terminal emulators will ignore NUL characters. Make sure you are using a tool that will show all characters. If the global is initialised in your code there may be a problem with your C runtime initialisation (typically in crt0.s). This is responsible for copying the initialisation data to the DATA segment in RAM. The simplest way to work out what is wrong is to step the code in the debugger. Clifford
To Clifford, Quite interestingly my code runs well with all other compilers that do not boast of compliance with so called standards, though they do comply, being proprietary however i cant use them for free. I'm very satisfied with winarm however, being able to solve the problems myself. I know you'll like that. Now, upon initialization of a global variable during declaration itself assigning a value other than null the value still remains null if not assigned a value during execution before its use. I'm really new to this compiler, I started only few days back and things that I've taken for granted with other compilers don't work. Many changes I've made to crt0.s which are not even relevant to target machine, to make it work. Thanks to this forum for that. Also, thanks for your prompt replies you seem to have spent lot of time doing this, while i spent that time doing something else, still worthwhile. And yes debugger, it sure is there. Abhijit
Abhijeet Bokil wrote: > Quite interestingly my code runs well with all other compilers that do > not boast of compliance with so called standards, though they do comply, > being proprietary however i cant use them for free. Code that runs when built with another compiler is not the same as correct code. The conclusion: "it works in another compiler so it cannot be the code" is a dangerous and usually flawed conclusion. A different compiler (or even the same compiler with different options) will generate different code and allocate memory differently; so for example a bug that corrupts memory will only cause an observable error is that corrupt memory is later used - and even then it may not do-so - it depends on the nature of the corruption and the affect that has on the code that uses it. Another cause of execution differences is the use of undefined or implementation defined language behaviour. Clifford
> Code that runs when built with another compiler is not the same as > correct code. The conclusion: "it works in another compiler so it cannot > be the code" is a dangerous and usually flawed conclusion. Aaaah! You get me wrong! I haven't used the word "correct" or "incorrect" code i've merely remarked upon the tendency, by which know, that i only mean not working here. From my, > things that I've taken for granted with other compiler you can understand that i know c is implemented differently depending on compiler and that it is the ability of the cross compiler to make "Whatever" of the code. So correct code may not actually be correct, or output sub optimal. In this case the corruption as you said is exactly what i'm pointing at.
Abhijeet Bokil wrote: > So correct code may not actually be correct, ... No you are still making no sense. You are implying that the compiler is generating incorrect object code from correct source, when that is the least likely explanation. Apply Occam's razor to this. I can only assume that you have either solved this problem or that you do not wish to solve it as you are not providing the requested information: 1) Post the non-working code (you only posted code that works, which I find bizarre!) 2) Use a tool such as portmon (http://www.microsoft.com/technet/sysinternals/utilities/portmon.mspx) to determine exactly what is being output if anything. 3) Confirm whether or not the 'global' is being correctly assigned or initialised. You have not been clear about this. (which is why you ought to post the code!). 4) I suggested using a debugger and you merely said "it sure is there". I don't know what that even means! Being 'there' is insufficient - you have to use it! If you have modified crt0.s you may have messed up global initialisation. But no one here reads minds. You have possibly over-localised your problem. but you did not even posted the code to which you have localised it that does not help in any case. If you cannot coherently address these points I doubt I can assist further. Clifford
>No you are still making no sense. You are implying that the compiler is >generating incorrect object code from correct source, when that is >the least likely explanation. See, by compiler i meant the entire toolchain, linker as well. Lets say thats my mistake. I'm NOT doubtful about the object code. Here is the non-working code: #include <LPC21xx.h> unsigned char ch='a'; void sendchar(char ch) { U0THR= ch; while (!(U0LSR & 0x20)); } void sys_config() { PINSEL0 = 0x00000005; IO0DIR = 0x00000000; U1LCR = 0x83; /* 8 bits, no Parity, 1 Stop bit */ U1DLL = 0x034; U1DLM = 0x00; /* 57600 Baud Rate @ 60MHz VPB Clock */ U1LCR = 0x03; /* DLAB = 0 */ PLLCFG = 0x22; /* Settings Pclk <-3* XTAL */ PLLCON = 0x01; PLLFEED = 0xAA; PLLFEED = 0x55; while(!(PLLSTAT & 0x400)); PLLCON = 0x03; PLLFEED = 0xAA; /* Set the PLL settings */ PLLFEED = 0x55; VPBDIV = 0x00000001; /* PCLK SET TO 60 MHz */ /* Uart0 Serial Port Baud Settings */ U0FCR = 0x01; U0LCR = 0x83; U0DLL = 0x41; /* BAUD RATE UART0 57600 */ U0DLM = 0x00; U0LCR = 0x03; } int main() { sys_config(); while(1) { sendchar(ch); } return 0; } And here is my crt0.S //////////////////////////////////////////////////////////////////////// // /* crt0.S for LPC2xxx - based on examples from R O Software - based on examples from newlib-lpc - based on an example from Anglia Designs collected and modified by Martin Thomas */ .global _etext // -> .data initial values in ROM .global _data // -> .data area in RAM .global _edata // end of .data area .global __bss_start // -> .bss area in RAM .global _bss_end_ // end of .bss area .global _stack // top of stack // Stack Sizes .set UND_STACK_SIZE, 0x00000004 .set ABT_STACK_SIZE, 0x00000004 .set FIQ_STACK_SIZE, 0x00000004 .set IRQ_STACK_SIZE, 0X00000080 .set SVC_STACK_SIZE, 0x00000004 .set USR_STACK_SIZE, 0x00000400 // modified // Standard definitions of Mode bits and Interrupt (I & F) flags in PSRs .set MODE_USR, 0x10 // User Mode .set MODE_FIQ, 0x11 // FIQ Mode .set MODE_IRQ, 0x12 // IRQ Mode .set MODE_SVC, 0x13 // Supervisor Mode .set MODE_ABT, 0x17 // Abort Mode .set MODE_UND, 0x1B // Undefined Mode .set MODE_SYS, 0x1F // System Mode .equ I_BIT, 0x80 // was 0x80 when I bit is set, IRQ is disabled .equ F_BIT, 0x40 // when F bit is set, FIQ is disabled .text .arm .section .init, "ax" .code 32 .align 2 .global _boot .func _boot _boot: // Runtime Interrupt Vectors // ------------------------- Vectors: b _start // reset - _start ldr pc,_undf // undefined - _undf ldr pc,_swi // SWI - _swi ldr pc,_pabt // program abort - _pabt ldr pc,_dabt // data abort - _dabt nop // reserved ldr pc,[pc,#-0xFF0] // IRQ - read the VIC ldr pc,_fiq // FIQ - _fiq #if 0 // Use this group for production _undf: .word _reset // undefined - _reset _swi: .word _reset // SWI - _reset _pabt: .word _reset // program abort - _reset _dabt: .word _reset // data abort - _reset _irq: .word _reset // IRQ - _reset _fiq: .word _reset // FIQ - _reset #else // Use this group for development _undf: .word __undf // undefined _swi: .word __swi // SWI _pabt: .word __pabt // program abort _dabt: .word __dabt // data abort _irq: .word __irq // IRQ _fiq: .word __fiq // FIQ __undf: b . // undefined __swi: b . // SWI __pabt: b . // program abort __dabt: b . // data abort __irq: b . // IRQ __fiq: b . // FIQ #endif .size _boot, . - _boot .endfunc // Setup the operating mode & stack. // --------------------------------- .global _start, start, _mainCRTStartup .func _start _start: start: _mainCRTStartup: // Initialize Interrupt System // - Set stack location for each mode // - Leave in System Mode with Interrupts Disabled // ----------------------------------------------- ldr r0,=_stack msr CPSR_c,#MODE_UND|I_BIT|F_BIT // Undefined Instruction Mode mov sp,r0 sub r0,r0,#UND_STACK_SIZE msr CPSR_c,#MODE_ABT|I_BIT|F_BIT // Abort Mode mov sp,r0 sub r0,r0,#ABT_STACK_SIZE msr CPSR_c,#MODE_FIQ|I_BIT|F_BIT // FIQ Mode mov sp,r0 sub r0,r0,#FIQ_STACK_SIZE msr CPSR_c,#MODE_IRQ|I_BIT|F_BIT // IRQ Mode mov sp,r0 sub r0,r0,#IRQ_STACK_SIZE msr CPSR_c,#MODE_SVC|I_BIT|F_BIT // Supervisor Mode mov sp,r0 sub r0,r0,#SVC_STACK_SIZE // msr CPSR_c,#MODE_SYS|I_BIT|F_BIT // System Mode if commented using modified code for USR mode // mov sp,r0 msr CPSR_c,#MODE_USR mov sp, r0 # Setup a default Stack Limit (when compiled with "-mapcs-stack-check") sub sl, sp, #USR_STACK_SIZE // Clear .bss // ---------- mov r0,#0 // get a zero ldr r1,=__bss_start // -> bss start ldr r2,=__bss_end__ // -> bss end 2: cmp r1,r2 // check if data to clear strlo r0,[r1],#4 // clear 4 bytes blo 2b // loop until done // Copy initialized data to its execution address in RAM // ----------------------------------------------------- #ifdef ROM_RUN ldr r1,=_etext // -> ROM data start ldr r2,=_data // -> data start ldr r3,=_edata // -> end of data 1: cmp r2,r3 // check if data to move ldrlo r0,[r1],#4 // copy it strlo r0,[r2],#4 blo 1b // loop until done #endif /* Call C++ constructors (for objects in "global scope") ctor loop added by Martin Thomas 4/2005 based on a Anglia Design example-application for ST ARM */ LDR r0, =__ctors_start__ LDR r1, =__ctors_end__ ctor_loop: CMP r0, r1 BEQ ctor_end LDR r2, [r0], #4 STMFD sp!, {r0-r1} MOV lr, pc MOV pc, r2 LDMFD sp!, {r0-r1} B ctor_loop ctor_end: // Call main program: main(0) // -------------------------- mov r0,#0 // no arguments (argc = 0) mov r1,r0 mov r2,r0 mov fp,r0 // null frame pointer mov r7,r0 // null frame pointer for thumb ldr r10,=main mov lr,pc /* Enter the C code, use BX instruction so as to never return */ /* use BLX (?) main if you want to use c++ destructors below */ bx r10 // enter main() /* "global object"-dtors are never called and it should not be needed since there is no OS to exit to. */ /* Call destructors */ # LDR r0, =__dtors_start__ # LDR r1, =__dtors_end__ dtor_loop: # CMP r0, r1 # BEQ dtor_end # LDR r2, [r0], #4 # STMFD sp!, {r0-r1} # MOV lr, pc # MOV pc, r2 # LDMFD sp!, {r0-r1} # B dtor_loop dtor_end: .size _start, . - _start .endfunc .global _reset, reset, exit, abort .func _reset _reset: reset: exit: abort: #if 0 // Disable interrupts, then force a hardware reset by driving P23 low // ------------------------------------------------------------------- mrs r0,cpsr // get PSR orr r0,r0,#I_BIT|F_BIT // disable IRQ and FIQ msr cpsr,r0 // set up status register ldr r1,=(PS_BASE) // PS Base Address ldr r0,=(PS_PIO) // PIO Module str r0,[r1,#PS_PCER_OFF] // enable its clock ldr r1,=(PIO_BASE) // PIO Base Address ldr r0,=(1<<23) // P23 str r0,[r1,#PIO_PER_OFF] // make sure pin is contolled by PIO str r0,[r1,#PIO_CODR_OFF] // set the pin low str r0,[r1,#PIO_OER_OFF] // make it an output #endif b . // loop until reset .size _reset, . - _reset .endfunc .end //////////////////////////////////////////////////////////////////////// //// I use the commands: arm-elf-gcc -g -c -O2 -mcpu=arm7tdmi filename.c -o filename.o arm-elf-ld -g -M -T LPC2119-ROM.ld crt0.o filename.o -o filename.elf -L "C:\Program Files\WINARM\lib\gcc\arm-elf\4.1.1" -lgcc -lc arm-elf-objcopy -O ihex filename.elf filename.hex This hex file when i put in my target LPC2119, sends a character(garbage) to my computer's serial port that i'm observing on hyperterminal. While if in main() i assign a value to the variable 'ch'. Here, #include <LPC21xx.h> unsigned char ch='a'; void sendchar(char ch) { U0THR= ch; while (!(U0LSR & 0x20)); } void sys_config() { PINSEL0 = 0x00000005; IO0DIR = 0x00000000; U1LCR = 0x83; /* 8 bits, no Parity, 1 Stop bit */ U1DLL = 0x034; U1DLM = 0x00; /* 57600 Baud Rate @ 60MHz VPB Clock */ U1LCR = 0x03; /* DLAB = 0 */ PLLCFG = 0x22; /* Settings Pclk <-3* XTAL */ PLLCON = 0x01; PLLFEED = 0xAA; PLLFEED = 0x55; while(!(PLLSTAT & 0x400)); PLLCON = 0x03; PLLFEED = 0xAA; /* Set the PLL settings */ PLLFEED = 0x55; VPBDIV = 0x00000001; /* PCLK SET TO 60 MHz */ /* Uart0 Serial Port Baud Settings */ U0FCR = 0x01; U0LCR = 0x83; U0DLL = 0x41; /* BAUD RATE UART0 57600 */ U0DLM = 0x00; U0LCR = 0x03; } int main() { sys_config(); ch= 'a'; /* Assigned value here */ while(1) { sendchar(ch); } return 0; } In this case the correct value 'a' is sent to serial port from UART. I've also given my ROM.ld above that i have not further modified. The problem therefore still stands why i dont understand the global variable's initialized value not copied in memory?
You had suggested using a program that could display all characters, so i used serial port library in linux, i've used it earlier, it works. The character was 'K' when i building once, the other time it was '\n'.
Abhijeet Bokil wrote: > See, by compiler i meant the entire toolchain, linker as well. Lets say > thats my mistake. I'm NOT doubtful about the object code. No you still entirely misunderstand me - the tool-chain being wrong is the *least likely proposition. Thousands of developers use the GNU tools every day. Your code or your build settings are at fault. Abhijeet Bokil wrote: > // Copy initialized data to its execution address in RAM > // ----------------------------------------------------- > #ifdef ROM_RUN > ldr r1,=_etext // -> ROM data start > ldr r2,=_data // -> data start > ldr r3,=_edata // -> end of data > 1: cmp r2,r3 // check if data to move > ldrlo r0,[r1],#4 // copy it > strlo r0,[r2],#4 > blo 1b // loop until done > #endif > [...] > > I use the commands: > > arm-elf-gcc -g -c -O2 -mcpu=arm7tdmi filename.c -o filename.o > arm-elf-ld -g -M -T LPC2119-ROM.ld crt0.o filename.o -o filename.elf -L > "C:\Program Files\WINARM\lib\gcc\arm-elf\4.1.1" -lgcc -lc > arm-elf-objcopy -O ihex filename.elf filename.hex > Where is ROM_RUN defined? If it is not defined global and static data will not be initialised. Abhijeet Bokil wrote: > You had suggested using a program that could display all characters, so > i used serial port library in linux, i've used it earlier, it works. The > character was 'K' when i building once, the other time it was '\n'. In your original report you wrote: > ...when i make the character global, nothing is sent. Which is not what you are saying now. I wonder why you did not report the change in findings earlier? This is why I asked you to check with a more appropriate tool. I suspected a global initialisation problem from the start and teh questions I asked were aimed at confirming this suspicion. Ultimately had you use a debugger as I suggested, you could have seen that the global variable had an incorrect value. I would advise against using the same name for both global and local variables (including parameters). The local will 'shadow' the global. This can cause problems in a debugger if for example you set a watch on the global variable when the local variable is in scope. Clifford
>Where is ROM_RUN defined? If it is not defined global and static data >will not be initialised. That should now end the problem. Thanks! Dude! Some kind of mis-communication between us. Nevermind! >Thousands of developers use the GNU tools >every day. Your code or your build settings are at fault. I completely believe thousands of developers use it which is why i'm using it and I've just become one of them! :-) Also i wont declare variable local n global with same name, u can see in main in the non-working code, it isn't a declaration. Anyway, thanks!
I'll post here as the problem's solved. I'll also verify with debugger bfor putting in target.
Abhijeet Bokil wrote: > Also i wont declare > variable local n global with same name, u can see in main in the > non-working code, it isn't a declaration. Anyway, thanks! Nonsense! Here: > unsigned char ch='a'; > > void sendchar(char ch) > { > U0THR= ch; > while (!(U0LSR & 0x20)); > } The parameter ch shadows the global ch. Clifford
Abhijeet Bokil wrote: > I'll post here as the problem's solved. I'll also verify with debugger > bfor putting in target. Eh!? The debugger runs the code on the target! There is a simulator, but since that will have its own C runtime start-up and it seems that is where your problem was it may not have helped. Clifford
>Nonsense! Here: >> unsigned char ch='a'; >> >> void sendchar(char ch) >> { >> U0THR= ch; >> while (!(U0LSR & 0x20)); >> } >The parameter ch shadows the global ch. God!! I mean is it about trying to sort out the problem or "see here u made a mistake" or "lets test ur C first". If i can understand that i shd not be declaring a var wid same name in main() which is declared global, to avoid prbs to monitor it in debugger, rest assure i wont use it in any other function. That code was tell u the real problem. plz refer my first post there u can see the name of var diff. But do u think it is abt tht? About the debugger: I knew it about the debugger n so dint mention anything. I've my own means to debug code that don't require the debugger. I'm using them and getting by for the last 10 yrs, out of sarcasm if u wish to know abt them i can tell u.
Please log in before posting. Registration is free and takes only a minute.
Existing account
Do you have a Google/GoogleMail account? No registration required!
Log in with Google account
Log in with Google account
No account? Register here.