Good afternoon,
I'm trying to register a serial (com-0) interrupt using uVision 3 on the Cypress FX2LP. The code compiles fine, but the linker warns:
WARNING L16: UNCALLED SEGMENT, IGNORED OVERLAY PROCESS SEGMENT: ?PR?COM_ISR?MAIN
My ISR looks like this:
static void com_isr (void) interrupt 4 { char c; if (RI) { c = SBUF0; // read character RI = 0; // clear interrupt request flag if (istart + ILEN != iend) { inbuf[iend++ & (ILEN-1)] = c; } } if (TI != 0) { TI = 0; // clear interrupt request flag if (ostart != oend) { // if characters in buffer and SBUF0 = outbuf[ostart++ & (OLEN-1)]; // transmit character sendfull = 0; } else { // if all characters transmitted sendactive = 0; // clear 'sendactive' } } }
This code is pretty much copy and pasted from the Keil Help section on Serial Transmission.
This ISR is not being called, even with IE=0x80 (to enable global interrupts) and ES0 = 1 (to enable serial 0 interrupts). Does anyone have any suggestions?
Thanks,
Montana
static void com_isr (void) interrupt 4 {
void com_isr (void) interrupt 4 {
I'm sure I have seen it done with 'static' !
It kinda makes sense, as you're not allowed to call an ISR - so you might as well "hide" it...?
I belive this might apply to this situation:
"Normally, when several relocatable object files are processed, the linker disallows multiple definitions of global symbols with the same name. However, the linker allows a weak definition in the presence of a global symbol with the same name; the weak definition is ignored. Another difference between a global and a weak symbol lies in whether the linker searches archive libraries. To resolve undefined global symbols, the linker searches archive libraries and extracts members that contain definitions; it does not do this to resolve undefined weak symbols.
The following restrictions and limitations apply to weak symbols:
Weak symbols may not have static storage duration. Multiple definitions for a weak symbol cannot be provided in the same translation unit.
When multiple definitions are present, the linker uses the first weak definition encountered."
I tried static on an ISR within a Cortex device and received a warning that the ISR was not being referenced.
WARNING L16: UNCALLED SEGMENT, IGNORED OVERLAY PROCESS SEGMENT: ?PR?COM_ISR?MAIN if this is not the only warning/error you get it could be due to you prototyping the ISR (which SDCC needs and Keil abhors)
Erik
That's not relevant here, as interrupts work entirely differently in C51.
In C51, it's the interrupt keyword that tells the compiler 1. to generate the ISR entry & exit code, and 2. to insert an entry at the specified location in the vector table.
This does, however, make it stange that there should be an "uncalled function" warning - since the interrupt keyword should be telling the compiler to create the "call" itself!
You haven't set the option to disable vector table generation, have you...?
I don't think Keil cares - but it certainly doesn't need it!
I tried removing static - that didn't work. I also tried adding a method prototype - with no result.
I've changed the method header to
void com_isr(void)
and I have changed my putchar and getchar methods to run com_isr() until the buffers are empty. I also have
while (TI == 1 || RI == 1) com_isr();
I've disabled interrupts for the time being. This works for my application, but is a dirty trick to use (and is a bit concerning, since I could miss some received data if my processor is off doing something and doesn't call com_isr() as often as it should). Luckily sending the data is much more important than receiving (receive is just an ACK, and I haven't lost one yet since the processor doesn't do much else).
I'll post back here if I ever resolve the issue ... unfortunately I must move on.
Thanks for the suggestions,
every Keil user has such working did you retype and 'skip' an error in the code?
I think you got it, noiv will definetely do it if the vector is not set in assembler (I guess that would be the only way to do it manually)
I have used noiv for bootloader/app switch, but see no other use - any takers?
If there are no other publics in the file, it will not be linked. Just put a global variable (used elsewhere) in this file, or put an initialisation routine in THIS file, of which you are sure it is been called from another place. Or just include the interrupt routine within another sourcefile.
Are you sure?
In C51, an ISR cannot be called directly - so it is never "linked".
Or, looking at it another way, the interrupt keyword tells the compiler to enter the function's address in the vector table, thus creating an "implicit" call which - which should ensure that it gets "linked" (otherwise the warning would be "unresolved external" rather than "uncalled function"...?)
If there are no other publics in the file, it will not be linked.
True, but only when the ISR is in a library file. If the module is in the linker command line it DOES get linked.