At this time when the two of you are active here, can I get an answer to the following which I have sougtht an answer to for some time both through support and this forum. Is there - or will there be - a means of allowing a struct to cross a 64k boundary. The code generated by the compiler does 16 bit math so members in the second page are erroneously accessed. This is for address calculation, not actual access since my system has a "flash page" port and a "read flash" function that set that port. Note" I am NOT talking of "placing in any 64k page", I AM talking about accessing a member of a struct that happen to be in the following 64k page. PLEASE no words about banks, I am not using it since 99.99% of the run time my program is happy in 64k code and data. Erik
Jon said, "my implementation of your example does work across 64K boundaries." Jon's implementation:
char_here = *(from_here + 7L);
char_here = *(from_here + 7);
Did you spot the difference? I did when you showed me; however, that requirement does not make sense. adding a constant to anything should not change the nature of the thing. Such a requirement (the 'L') is almost guaranteed to create data dependent errors. Erik
A lot of old Unix habits, plus the by now long tenure of 32-bit processors, has habitued people to doing pointer arithmetic in ints. But there's no assurance by the language that an int is large enough to contain a pointer. C99 introduced intptr_t for just this purpose. It's the smallest integer big enough to hold a pointer. C51 ints are 16 bits. If you are dealing with far or generic pointers, you need to use a long to hold all three bytes. If you know that you only need cope with memory-specific pointer types, then an int will suffice. Anyone up for adding U24 support to the compiler?
C51 ints are 16 bits. If you are dealing with far or generic pointers, you need to use a long to hold all three bytes. If you know that you only need cope with memory-specific pointer types, then an int will suffice. The issue is NOT what type to "hold" the pointer (far = 3 bytes, fine) but that when something is added to a far pointer the addition should be 24 bit to maintain the far nature of the pointer. Erik
Erik, I think you're missing the point, too, though in a different way than Drew did. You quite right that this is not about pointers cast to integers and back to pointers. But I suspect you were wrong when you rather strongly stressed earlier in the thread that banking had nothing to do with this. Because, unless you were using some extended 8051 variant like the Dallas/Maxim '390 which has true, binary-incompatible, contiguous 23-bit addressing modes, then you must be using some kind of banking to have any memory accessible beyond the first 64K. This might be different if you had used the "huge" memory models (ROM(D512K) or ROM(D16M)). Here's what I would do to workaround this limitation (which I don't really see as a bug): define a hole in address space, in the last byte of every 64K bank. This will prevent any object from ever straddling the boundary, and thus avoid the problem.
Here's what I would do to workaround this limitation (which I don't really see as a bug): define a hole in address space, in the last byte of every 64K bank. This will prevent any object from ever straddling the boundary, and thus avoid the problem. Hans-Bernhard, If you had read the whole thread, you would have seen that I receive the whole shebang in a file created on a PC and thus have NO ABILITY to create "holes" or whatnot. Erik PS Ifnore all references to C51, of course this will have to be done with CX51.
far means that variables can be anywhere in the address space, however the object size is limited to 64KB (see: http://www.keil.com/support/man/docs/c51/c51_le_far.htm) The problem on 8051 based devices: the address space is extended, but the MUL/ADD instructions required to calculate true 24-bit addresses are missing. If CX51 would always calculate 24-bit addresses the code would be huge and very slow. On the Intel 251 architecture there are MUL+ADD instructions that generate 32-bit results. On the extended 8051 variants they are missing. Since some customers need 'linear' 16MB addressing, we change the behaviour of far when the index is a long type (see: http://www.keil.com/support/docs/2800.htm). We think that this is an acceptable solution. Reinhard
It seems to be summed-up in http://www.keil.com/support/docs/2269.htm "The Keil CX51 C Compiler limits individual objects to 64K in size. So, pointer accesses using normal data objects are restricted to a single segment (64K) and 16-bit math is used. "By forcing long pointer arithmetic, you signal the compiler that you want 24-bit address calculations to be performed."
Since some customers need 'linear' 16MB addressing, we change the behaviour of far when the index is a long type We think that this is an acceptable solution. OK, in english: Long or not as type of the index is used by CX51 as a switch between 16 and 24 bit arithmetic for calculating the address. Correct? also: is that the case for C51? Erik PS I can accept the argument (code size) for a switch; however I think the switch chosen is "dangerous" as to potential lurking bugs (you can have a product where the data is, say, 48k day 100 and 67k day 1000 - CRASH). The product is yours, you do what you see best; however since the base is always the same i.e. ONE declaration and the index can be 55 different entities, I would much rather have had a "farx" or such as the switch.