Using CW 4.7 (with patch 4.7.1), target: 9S12XDT512
Application is TCP-IP stack implemented as a ROM library installed in processor memory, prior to installing an application program. ROM library is located in a far code segment and banked model is being used to construct the library as a project in its own right. Customised application programs will be built as separate projects that can call functions from the common firmware library.
I have written most functions for a module called UDPIP, based loosely on Freescale AN2304. This module covers Layer 3 of the OSI protocol stack: Ethernet driver below it, a TCP module above it, and an HTTP module above that. The 'middle layer' primarily implements IP, but with UDP and ICMP thrown in.
So far I have written and (mostly) tested and debugged the following functions:
UDP_Write() : invoked by higher layer when UDP protocol req'd - mainly for DHCP client
IP_Write() : invoked by UDP_Write() and - when I get to it - TCP_Write()
IP_Receive() : invoked as a callback from lower layer
ICMP_Receive() : invoked by IP_Receive() if protocol is ICMP - generates Echo Reply to a Ping
UDP_Handler() : invoked by IP_Receive() if protocol is ICMP
- others to follow
The compiler INSISTS on treating UDP_Write() as the subject of a near function call - assembly code shows RTS at the end, whereas all others show RTC. I've tried the following:
- naming the code segment with and without the __FAR qualifier
- including and not including the __far prefix with the UDP_Write() prototype (and with the function name in the source code)
- messing about with linker segments and placements
- looking through past 12 months of posts on this board
- tearing hair out
The only difference between UDP_Write() and other functions in this module is that it has a dependency (IP_Write()) in the same module; this situation may change in due course, as more of the module and other modules are written.
UDP_Write() calls IP_Write() using a far call, as you'd expect with the banked model and without pragmas to override. But UDP_Write() in general would be called from another module, and possibly from another page of code memory. It is essential that, in general, this function be called using a far call. But the compiler insists it is a near function, while all the others are allowed to be far functions.
What could be special about a function in a far segment that makes the compiler treat it as a near 'callee', and put an RTS at the end instead of RTC?