Virgil Reichert

Sticky BugList for CW 5.1 code generator? (MC9S08QG8)

Discussion created by Virgil Reichert on Jul 20, 2008
Latest reply on Jul 25, 2008 by Jim Donelson
Maybe this has been done before, but since I'm new...
Now that I earned my scars from my first CodeWarrior project, I was wondering if anyone has a list of bugs for the code that comes out of the code generator from CodeWarrior 5.1.
Now before all of you say, "It's fixed in the next release", let me say that if so, then CW should support the code in their Special Edition they ship with new DEMO boards, or they should start shipping 6.x with their DEMO boards now.  As a minimum, they could include an errata sheet with the CD that says "the following beans don't work for beans".  I understand that their marketing model does not supply all of the possible code generator beans, and that's fine.  They need to eat too.  But the code they do generate should be supported.
So after that, here's what I learned the hard way (from the code I generated for MC9S08QG8):
1.  Serial Port code:  (AsynchroSerial bean).  At least for the baud rate I wanted (4800), the code generator calculated the wrong value to load into SCIBD (the actual baud rate).  With a bus divider of 1, the PE GUI calculated that SCIBD = 0x6D.  This is incorrect.  The actual value should be 0x68, and it is off enough that the communication doesn't work.  I lost a lot of time because I thought it was my bug.  I found it by studying the DEMO_MC9S08QG8 source code that sets it to 0x68, and then it all worked fine.  I also found it a bit strange that the DEMO apps apparently don't use the code generators at all, but were coded from scratch just to show off the possible applications.
2.  IIC (or I2C) code:  (EI2C1_SW_I2C bean). I found that it had most of the routines I thought I needed to implement the protocol.  I realized that to use it, I would need to do the STOP manually, which is fine.  After studying the code, I immediately realized that they were missing the mark on the IIC protocol.  I've written C for IIC and SPI devices before and after studying the code, I was sure nobody tested this code on a real device.
The first problem is that there is no provision for the Address in the routines.  Now what can be confusing is that there are two addresses.  The first address is the Device Address (which device you want to talk to).  This is sometimes called the Slave Address.  This is the first address after the START bit.  The next byte is normally the Memory Address WITHIN the device.  If it is an EEPROM, then the Device Address is 0xA0 for a write to the device, and the Memory Address is the memory location you wish to access.  The routine "SendChar" only sends the Start bit and two bytes.  They are missing the data.  So my way around this was to edit the PE code to elevate the Write() and GetAck() routines to be accessible outside the module, and I used it after the EI2C1_SendChar routine to send the data.
      MyAddr = (byte)j;
      Err = EI2C1_SendChar(MyAddr);     // Send the Write address to EEPROM
      if(Err) WriteFailed = TRUE;
      Write(*ReadPtr++);                          // Send the data
      Acknowledge = GetAck();
      if(Acknowledge == NOACK) AckFailed++;
      EI2C1_SendStop();                         // Send the stop bit
There was one more problem, and that is the code is missing one clock in the entire protocol.  I only found it when using an oscilloscope to watch the lines.  Mind you, I'm working as a contractor out of my home ever since my job went to China, so I only have an old analog (not a storage) scope.
At the end of the GetAck() routine, the clock is left high after sampling the ACK on the data line.  Then the SendStop() routine drives the data low and then the clock high (which it already was), and finally the data high, which is the Stop bit.  The problem is that there is no clock at the end of GetAck() to clock the reception of the ACK from the slave.  So even though the software read the ACK, the device does not release the ACk because it did not get a clock from the controller.  So in my case, the writes kept failing.  I added a routine called ClkDown() and the device driver started working.
void ClkDown(void) {
  Inhr2_SetDir((bool)OUTPUT);       /* CLOCK LOW PULSE */
I suspect that this clock may also be missing from the reads as well, but I didn't want to change the GetAck() routine because it is used in other places, and my code is now working.  Notice that the above routine uses byte writes in a for loop rather than one block write.  I just wanted to keep things simple to get it working.

So the only devices I used on this part so far have been the IIC, the Serial Port and the GPIO pins.  I was thinking about using the analog comparator, but since 2 of the 3 PE beans have had bugs, I'm a bit nervous.  So I'm hoping we can help each other with a list of known bugs in the code generators.