We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
hello everyone, I am reading some code on a system that connect the 8051 with an external ram chip but I have no idea what is going on with the code, I have been struggling on this for quite some time now, just want to see if anyone can point me to the right direction.
the first part i dun understand is how the ram is use
void k6x8008_writebyte (unsigned char hadd,unsigned char madd,unsigned char ladd,unsigned char indat) { RD = 1; WR = 1; k6x8008_laddress(ladd); k6x8008_maddress(madd); k6x8008_din(indat); k6x8008_din(indat); k6x8008_haddress(hadd); WR = 0; WR = 0; WR = 1; k6x8008_haddress(0x00); P0 = 0; WR = 1; }
i don't understand what those ladd, madd or hadd means at all
on the main code this is the part that requires writing data to the ram...
iphadd=((subaddress&HADDBITS)/0x00010000); ipmadd=((subaddress&MADDBITS)/0x00000100); ipladd=((subaddress&LADDBITS)/0x00000001); k6x8008_writebyte(iphadd,ipmadd,ipladd+0x00,0xff); k6x8008_writebyte(iphadd,ipmadd,ipladd+0x01,0xff); k6x8008_writebyte(iphadd,ipmadd,ipladd+0x02,0xff);
why does the coder uses binary division?? and this might be abstract but im also not sure why he is writing 0xff to the ram in the part above
Please read the instructions on how to post source code:
www.danlhenry.com/.../keil_code.png
l = low. m = medium h = high
A single byte can only address 256 bytes. Exactly how large address space can your chip address? It seems like it can address more than 2^16 bytes. Possibly all the way to 2^24 bytes, which means you need three bytes to specify the address.
The code could have used shift instead of division. Normally, the compiler will look for this case and replace the division with a shift.
I think you will have to ask the previous developer why he is written 0xff to the RAM. Source code supports comments just to allow a developer to describe the reasons why things are done - reading the code can't normally answer the "why" - only the "what".
Strange how you sometimes see animals in the clouds:
k6x8008_laddress(ladd); // Lad Dress k6x8008_maddress(madd); // Mad Dress k6x8008_haddress(hadd); // Had Dress
Does the code have some association with cross dressing?
void k6x8008_writebyte ( unsigned char hadd, unsigned char madd, unsigned char ladd, unsigned char indat) { RD = 1; WR = 1; k6x8008_laddress(ladd); k6x8008_maddress(madd); k6x8008_din(indat); k6x8008_din(indat); k6x8008_haddress(hadd); WR = 0; WR = 0; WR = 1; k6x8008_haddress(0x00); P0 = 0; WR = 1; }
phadd=((subaddress&HADDBITS)/0x00010000); ipmadd=((subaddress&MADDBITS)/0x00000100); ipladd=((subaddress&LADDBITS)/0x00000001); k6x8008_writebyte(iphadd,ipmadd,ipladd+0x00,0xff); k6x8008_writebyte(iphadd,ipmadd,ipladd+0x01,0xff); k6x8008_writebyte(iphadd,ipmadd,ipladd+0x02,0xff);
Do you have documentation on the hardware this person is accessing? I believe the answers would be more obvious if you had the hardware documentation and started commenting the could. It might be good to change the code to be less abstract. For example ipladd is probably ip_low_address which is also wrong it should be ip_LSB <standard for least significant byte> or ip_least_significant_byte. It doesn't seem space efficient but it's big and obvious.
k6x8008_writebyte is nasty naming, it at least gives you an idea what it does however, you may wish to give it a new and more descriptive function name. Refactoring of the original code might be a good idea before you get into it. One of the most important aspects of embedded code is it MUST be maintainable.
You should document the method and reason for each function too, that way if someone else has to deal with the code they can extol your wisdom and make changes much more easily.
According to the internet the k6x8008 is "1Mx8 bit Low Power full CMOS Static RAM". I suggest you get the documentation on the hardware interface to make better sense of that. In fact you probably should have notes on what version of your hardware that code is for, if it is not in there that is yet another major faux pas in programming. Always keep in the comments for IO interfacing what version of the hardware that code is for. That way people can look at the correct schematic to see what is going on (and hope the schematics are kept in proper revisions). Also if the hardware changes you know what part of the code needs changed.
Stephen
Thank you for the replies, I do have the documentation for the K6X8008 Ram and the 8051 which is a Winbond W77E58. I have tried reading the datasheet of the Ram chip and is still having difficulty understanding it. The previous developer did not leave anything behind except for the code and I have not been able to reach him. From what I read from the replies, when accessing a ram is it necessary to have the low, medium and high address? Also about the division or the shifting, whats the purpose in that? I am sorry if the question is naive but I have to admit that I am very new to hardware programming. Thanks for the patients.
P.S. in the k6x8008_writebyte function, why did the previous developer set WR = 0 for two lines then set it back to 1?
"when accessing a ram is it necessary to have the low, medium and high address?"
A RAM chip - any RAM chip - requires a complete address. In your case, it appears that it takes 24 bits to make a complete address.
Now, an 8051 is an 8-bit processor, isn't it? That means that it can only handle 8 bits at a time.
Therefore, to handle anything bigger that 8 bits, it is going to have to do it one byte (8 bits) at a time.
Obviously, a 24-bit address takes 3 bytes - which can conveniently be called "low", "medium" (or "middle"), and "high".
"why did the previous developer set WR = 0 for two lines then set it back to 1?"
In the RAM Datasheet, you should find some Timing Diagrams; these show how the various signals need to behave with respect to time - there you should be able to see how the various lines are required to go up & down...
As an aside, I hope you will learn from this experience just how much grief that causes - and be sure to comment your code diligently so that your successors don't end up in the same position!
And, of course, it's not just your successors - it may well be you in six months' time when you've forgotten why you did things the way you did...
If you have a 24-bit number and wants to split it into three individual bytes, you can do that in a number of ways.
To extract an 8-bit group of bits from the larger integer, you may use either % or & (modulo or bit-and).
To move bits down to the least significant part of the integer, before extracting them, you may use >> or / (right-shift or division).
There is nothing magic about your RAM chip - it just needs an address of the required width, and the hardware interface of your processor don't have any magic function that can directly accept a 24-bit wide address.
We don't know the contents of the helper functions (or macros) used, so maybe the code is using three 8-bit ports to send out the address. Or maybe it is using one 8-bit port and a couple of signals on another 8-bit port, and then sending out the three bytes of the address to three external 8-bit latches.
The duplication of some of the source lines, is - as Andy notes - a way to slow down your processor, to make sure that the written data has enough time to settle before the RAM latches it, and to make sure that the write pulse is long enough. You should make yourself familiar with the settle and hold times specified in the RAM datasheet. When writing this kind of code, it is also required to verify the timing by using an oscilloscope and measure on the actual signals.
Of course, all code like this should be properly documented. There should be information about the maximum speed you may run the processor in, to still fulfill the timing. Note that both clock frequency and the processors required clock count/instruction will affect the timing. And in some situations, a change of compiler or change of compiler settings may change the timing. C can't guarantee exact timing, but in this case you don't need exact timing. It doesn't matter if the timing is a bit too slow, but it may not be too fast.
P.S. in the k6x8008_writebyte function, why did the previous developer set WR = 0 for two lines then set it back to 1? The real thing to consider, is "why do you have to even ask this question?" as it should be well documented. I suggest you get the project SCHEMATIC <you MUST have this or your project is DOOMED> and see if pertinent information is on it, such as how the SRAM you are using is interfaced into it (see http://www.keil.com/dd/docs/datashts/winbond/w77e58.pdf for your processor data sheet also) ALL of this data should be with your project data already. IE the data sheet the schematic etc should be packaged with the source code. The source code is abysmally useless without it.
Most importantly LOOK at the schematic, LOOK at the data sheet for the RAM, that should indicate how they were addressing the SRAM. If not you should ask someone who has an idea, or find the project files and see if anything was documented. ALL of these things need to be carefully documented. You should be sure to add this data and note that it had to be searched for (you should account for the time you are using to do all this in case someone asks).
A bit of documentation (IE 5 minutes) will save you DAYS worth of discovery by trial and error. It's VERY expensive to not document things properly.
as it should be well documented I guess that, of what I have 'inherited' over the years the status has been: 5% "well documented" and reasonably commented 20% documented and reasonably commented 30% reasonably commented 45% no documentation whatsoever
Erik
Managers sees function, not the source code or all the documentation around the code.
And they pay for a fast delivery of working code.
The consultant who skips the documentation can offer the lowest price and fastest delivery. (And make the most money by delivering code that no other company is interested in maintaining.)
In a world where you write your budget based on the initial costs, and ignores the total life-time costs, the buyer tends to get exactly what they are willing to pay for. And the customers does the same - buys the cheapest product. Then they get surprised/frustrated/angry when it doesn't work as well as they hoped.