Hi, I'm running a small testapp to see if my 80c32 uP is running fine. Therefore, I toggle P1_0 and next to this, I'm writing a value to a var defined in external RAM. The RAM starts at address 0x0 and is 2kB long, so the end is at 0x7FF. I define those ranges via 'Options - Options for Target 'Target 1' - Target' - Off-chip Xdata memory. However, I see something very strange: when I declare my variable (for fun) at a fixed location outside the given range (e.g. unsigned char xdata testvar _at_ 0x850;), then I don't get a warning, even if I'm working outside the range. Most strange of all, the variable is written and read correctly too (I'm toggling another pin if comparison is failing and I'm observing this pin with a scope, but I don't see any toggling => value exchange seems to be correct...)! Can't understand this... Anyone any idea? --Geert
When you create hardware you'll typically have your CODE space (ROM or FLASH) external RAM (for program variables and buffers) and maybe some memory-mapped peripherals (like an LCD or UART or A/D). You basically want the compiler and linker to locate your program code and variable data in ROM and RAM and you really don't need to know where it is, just that it's there. So, you must specify (to the linker) the code space and the xdata space. You don't want the linker to locate variables at the addresses occupied by memory-mapped peripherals, so these addresses are not specified to the linker. In any case, the memory space used by memory-mapped peripherals should NEVER be specified to the linker. In your program, you'll need to access the memory-mapped peripherals using C pointers, the ?BYTE and ?WORD macros (which are effectively pointers), or by physically locating a variable using the _at_ keyword. These things are all done at the compiler level and the assumption is that if you are messing around with physical addresses you must know what you're doing. For projects with a lot of memory-mapped peripherals (that are accessed using _at_) it does not make sense to warn the develop that they are accessing memory that wasn't specified to the linker for variables. That's one of the major reasons to use _at_. Jon
Hi Geert and John, If we have a system with 2k of ram and do somthing like 'xdata char array[0x1000];' I beleive the the compiler/linker will complain that the system has insufficent memory where as Geerts fun question breaks down into two parts:- 1. Why does addressing something above 0x7ff work in his sytem - this is because of partial address decoding and 2. The poiter is an invalid address - why is there no warning?. So, I was wondering if (possibly) the only way the compiler/linker can know that 'unsigned char xdata testvar _at 0x850;' should cause a problem because there is nothing there! (ram or uart etc) would be if the compiler/linker had some way to be told where everything was? I would be interested in seeing if there is a simple solution that could easily pick up on typo's where a pointer is defined pointing to an address outside the system's xram address and is automatically picked up by the compiler. Thanks, Mark :-)
"For projects with a lot of memory-mapped peripherals (that are accessed using _at_) it does not make sense to warn the develop that they are accessing memory that wasn't specified to the linker for variables. That's one of the major reasons to use _at_." Very true. The Triscend E5 (may it rest in peace), had a lot of system registers mapped into the top 256 bytes if XDATA space - beyond the physical memory actually implemented in the silicon. One would set up the tools with the "XDATA memory size" set to the size of the physical RAM actually present - so that the tools would not try to automatically locate variables where no RAM existed. The extra system registers would be accessed via "_at_" variables - obviously one would not want the tools to give warnings for these, and one would also not want to have to "lie" about the RAM size just to be able to access them! I seem to remember that Keil "broke" this a few versions ago, which meant that we did start getting warnings for the system registers! :-( It's all fixed again now. :-)
"I would be interested in seeing if there is a simple solution that could easily pick up on typo's where a pointer is defined pointing to an address outside the system's xram address and is automatically picked up by the compiler." First, you need to distinguish a pointer from a variable defined with Keil's _at_ keyword extension. A pointer is a standard 'C' mechanism for accessing memory addresses by indirection at run-time; The _at_ keyword extension is merely a way to "manually" fix the location of a variable at compile time. I think the assumption is that if you specify a variable's location using _at_, then you know what you're doing and take full responsibility for it. For other variables, you are letting the Linker/Locator do the placement in memory - therefore you want to be able to tell it how much RAM you have, and for it to be able to tell you if it can't fit everything into the space you've told it. You might well have some "special" memory addresses (eg, memory-mapped preipherals) that you'd want to access via _at_, but would not want to give the Linker/Locator the chance to go putting any old variables there!
Thanks all of you, guys. I have the picture now... It's indeed my responsibility the moment I'm starting to use the _at_ keyword. If something would go wrong, I can't blame the compiler/linker. Keil is doing it correctly: if I do another test, for instance defining an array with size 0x801, it will complain (error L 107: Space Overflow) because that doesn't fit in the available external RAM. That is, 1 byte too much in my example, knowing that RAM is located between 0x000 and 0x7FF. Should I stop having fun now??? ;-) --Geert
"Should I stop having fun now??? ;-)" Maybe you should just get out a little more... ;-)
Should I stop having fun now??? ;-) There are many fine hobbies you may find to pass away the hours between learning esoteric compiler trivia. My first suggestion would be beer tasting! It's relatively inexpensive and there are many fun games you can play with other beer drinkers. For example: who can drink the most, who can drink the most before a bathroom break, who can drink the most and still write a comprehensible and working program, and so on. Jon
"Should I stop having fun now??? ;-)" May I suggest "bar rowing" You line up 2 teams at the bar, each member with a beer. At the start signal member 1 of both teams drains his beer and hold it upside down over member 2s head, then member 2 drain his beer and hold it .... and so on. This get to be real fun if a team insist on winning (try to be member 1) Erik