Trying to compile this code: #define U0THR (*((volatile unsigned char *) 0xE000C000))
template <typename T, unsigned int len> class Queue { public: /** Constructor, create a new queue. */ Queue() { put_pos=get_pos=num_elem=0; } bool IRQget(T& elem) { if((put_pos==get_pos)&&(num_elem==0))//If queue empty { return false; } num_elem--; elem=buffer[get_pos]; if(++get_pos==len) get_pos=0; return true; } bool IRQput(T elem) { if((put_pos==get_pos)&&(num_elem!=0))//If queue full { return false; } num_elem++; buffer[put_pos]=elem; if(++put_pos==len) put_pos=0; return true; } private: //Queue data T buffer[len]; volatile unsigned int num_elem; volatile unsigned int put_pos; volatile unsigned int get_pos; }; Queue<char,32> tx_queue; void serial_IRQ_Routine() __attribute__ ((interrupt("IRQ"))); void serial_IRQ_Routine() { char c; int i; for(i=0;i<16;i++) { //If software queue empty, stop if(tx_queue.IRQget(c)==false) break; U0THR=c; } } with gcc 4.2.4, command line "arm-elf-g++ -mcpu=arm7tdmi -fno-exceptions -fno-rtti -Os -Wall -S bug.cpp" corrupts the program counter when returning from the ISR. It happens only with -Os optimization flag. -O0 -O1 -O2 -O3 optimization flags cause no bug. Here's a piece of assembler code: _Z18serial_IRQ_Routinev: @ Interrupt Service Routine. @ args = 0, pretend = 0, frame = 4 @ frame_needed = 0, uses_anonymous_args = 0 sub lr, lr, #4 stmfd sp!, {r0, r1, r2, r3, r4, r5, r6, r7, ip, lr} ldr r7, .L15 sub sp, sp, #4 ldr r6, .L15+4 mov r4, #0 add r5, sp, #3 .L10: ldr r0, .L15+8 mov r1, r5 mov lr, pc bx r7 cmp r0, #0 add r4, r4, #1 beq .L13 ldrb r3, [sp, #3] @ zero_extendqisi2 cmp r4, #16 strb r3, [r6, #0] bne .L10 .L13: add sp, sp, #4 ldmfd sp!, {r0, r1, r2, r3, r4, r5, r6, r7, ip, lr} subs pc, lr, #4 at the beginning there's " sub lr, lr, #4" and at the end " subs pc, lr, #4" so the program counter is decremented by 8 instead of 4. Here's the output of arm-elf-gcc -v: arm-elf-g++ -v Using built-in specs. Target: arm-elf Configured with: ../gcc-4.2.4/configure --target=arm-elf --prefix=/usr/local/arm-elf --enable-interwork --enable-multilib --with-float=soft --enable-languages=c,c++ --with-newlib --with-headers=../newlib-1.16.0/newlib/libc/include Thread model: single gcc version 4.2.4 -- Summary: Interrupt service routine for arm target corrupts program counter Product: gcc Version: 4.2.4 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: fede dot tft at hotmail dot it http://gcc.gnu.org/bugzilla/show_bug.cgi?id=37386