I am debugging an application using CCS 4.2.4, an MSP430-FET, on an MSP430F5418 and attempting to find a problem with SPI reads. My trouble seems to be reading the SPI RX buffer. I can single step through and my variable appears to 'read' the correct value out of the buffer however if I run without single stepping I don't get a proper reading of the variable. Below is some code to illustrate what I am observing ...
unsigned char mytestdatabyte=0; // for tests and comparison only (TODO: remove later)
void SPIRead(unsigned char address, unsigned char *buffer, unsigned char len){ if (len > 0x80 || len == 0) return; ENTER_TASK; // presently just disables interrupts ENABLE_CS_PIN(); UCB0TXBUF = (len & 0x7F); while (!(UCB0IFG&UCRXIFG)); // USCI_B0 RX buffer ready? mytestdatabyte = UCB0RXBUF; // clears flag UCB0TXBUF = address; while (!(UCB0IFG&UCRXIFG)); // USCI_B0 RX buffer ready? mytestdatabyte = UCB0RXBUF; // clears flag while(len-- > 0) // now read the values { UCB0TXBUF = 0xff; while (!(UCB0IFG&UCRXIFG)); // USCI_B0 RX buffer ready? mytestdatabyte = UCB0RXBUF; *buffer++ = mytestdatabyte; } /* chip select */ DISABLE_CS_PIN(); LEAVE_TASK; // and re-enables interrupts}
If I single step through my variable mytestdatabyte contains the correct value I expect to read. If I 'run' with a breakpoint on LEAVE_TASK my test variable does not contain the correct value.
Can any one help me understand what I am doing wrong? Thank you.
I'll update this by saying that if this is speed related, which it really shouldn't be, I'm running the MSP with the default oscillator values, so, DCOCLKDIV (1048576 hz) with the following setup using MSP Ware
#define SPICLK 500000
unsigned char usciB0_SPI_Init(void){ unsigned char returnValue = 0; //P3.3,2,1 option select GPIO_setAsPeripheralModuleFunctionInputPin(__MSP430_BASEADDRESS_PORT3_R__,GPIO_PORT_P3,GPIO_PIN3 + GPIO_PIN2 + GPIO_PIN1); SET_CS_PIN(); DISABLE_CS_PIN(); returnValue = SPI_masterInit( __MSP430_BASEADDRESS_USCI_B0__, SPI_CLOCKSOURCE_SMCLK, //selects Clock source. Valid values are SPI_CLOCKSOURCE_ACLK SPI_CLOCKSOURCE_SMCLK UCS_getSMCLK(__MSP430_BASEADDRESS_UCS__), //clockSourceFrequency is the frequency of the slected clock source SPICLK, //desiredSpiClock is the desired clock rate for SPI communication SPI_LSB_FIRST, //controls the direction of the receive and transmit shift register. Valid values are SPI_MSB_FIRST SPI_LSB_FIRST [Default Value] SPI_PHASE_DATA_CHANGED_ONFIRST_CAPTURED_ON_NEXT, //clockPhase is clock phase select. Valid values are SPI_PHASE_DATA_CHANGED_ONFIRST_CAPTURED_ON_NEXT [Default Value] SPI_PHASE_DATA_CAPTURED_ONFIRST_CHANGED_ON_NEXT SPI_CLOCKPOLARITY_INACTIVITY_HIGH); //clockPolarity_InactivityHIGH is clock polarity select. Valid values are SPI_CLOCKPOLARITY_INACTIVITY_HIGH SPI_CLOCKPOLARITY_INACTIVITY_LOW if (returnValue != STATUS_FAIL) { SPI_enable(__MSP430_BASEADDRESS_USCI_B0__); } return (returnValue);}
Further info ....
I must be doing something perhaps fundamental here. The bizarre observations below seem to suggest this to me. I set up a call and comparison to the values I was anticipating from the former code and what I observe in the RXBUF. What I've observed is that my 'local' watch on a buffer and a global "Watch" on the debug variable both indicate 0x00 as the value. However, when I set up a compare to defined values, they pass through as 'true' which means what the 'watch' shows must be incorrect. Or, code execution is incorrect.
Somewhere along the way here my observations don't make sense and leaves me questioning the debugger. Since I've haven't seen any threads on that, it must be something I'm doing however I can't explain what at the moment.
Has anyone else had observations like this?
Here is a sample of calling above and the result is that I can trap on the return (true); however my local watch on buff[0] = 0x00 and buff[1]= 0x00
(in this instance, A_Revision_O and A_Version_O are constants that represent an unsigned char Address value passed over the SPI)
#define A_Version_I 0x05 // I can see these values in the RXBUF after having stepped through an SPIRead.
#define A_Revision_I 0x01
/**************************************************************************/
bool CheckVerRev (void)/**************************************************************************/{ unsigned char buff[2]={0,0}; SPIRead(A_Version_O, &buff[0] , 1); SPIRead(A_Revision_O, &buff[1] , 1); // Now compare the version this is compile to run with //if (buff[0] == A_Version_I && buff[1] == A_Revision_I) // commented out for testing individual buffer locations if (buff[0] == A_Version_I) { if (buff[1] == A_Revision_I){ return TRUE; } else{ return FALSE; } } else { return FALSE; }}
Hi Kevin,
it might be that you ran into a typical copy and paste error. I can only see
KevinFwhile (!(UCB0IFG&UCRXIFG)); // USCI_B0 RX buffer ready?
even when you write the address - I would expect something like this
UCB0TXBUF = address ; while(!(UCB0IFG & UCTXIFG)); while (!(UCB0IFG & UCRXIFG)); receiveChar = UCB0RXBUF; UCB0TXBUF = 0; while(!(UCB0IFG & UCTXIFG)); while (!(UCB0IFG & UCRXIFG)); receiveChar = UCB0RXBUF;
--Regards,JanOxfam Trailwalker 2012 - Runner
Found any horribly english mistakes? - Drop me a note as private conversation via my profile if you like ;-)
Thank Jan,
It wasn't a copy and paste error and my thoughts behind it were; I'm getting data in at the same time as I'm sending out and therefore waiting for the UCRXBUF to fill up (ie: not a blind send). The UCTXIFG flag would indicate it's ready to TX again, which it should be once I've finished receiving the byte. Now, I supposed that perhaps the more correct way would be to check the TX flag initially, TX,check the TX flag, check the RX flag plus any possible error flags, check for TX Flag before sending the next byte....
I don't think that's indicative of what I'm seeing since I actually do see my expected return value sitting in the RXBUF when I set a break point at the end of the call, what I don't seem to be seeing is the actual value sitting in the value you point to above as 'receiveChar' (as a watch) unless I single step. I thought perhaps my issue might be refreshing the watch list but that didn't seem to work either.
Next, I looked to see if optimizations might be an issue. That doesn't seem to be a problem, I don't have any turned on at the moment.
There something odd in the behaviour but oddly, when I try to trap for the behaviour in a return value (the latest update I think I mentioned above) - all seems fine. Since it'll be an easy change to make, I'll try your suggestion above and report back. Just seems odd to me to have the debugger break on a break point but indicate incorrect values.
K
KevinFhe UCTXIFG flag would indicate it's ready to TX again, which it should be once I've finished receiving the byte.
If you single-step, time passes and the transfer completes. (the world doesn't stop turning just because you are single-stepping the CPU code execution). Likely this is why it works in single-stepping
_____________________________________Before posting bug reports or ask for help, do at least quick scan over this article. It applies to any kind of problem reporting. On any forum. And/or look here.If you cannot discuss your problem in the public, feel free to start a private conversation: click on my name and then 'start conversation'. But please do so only if you really cannot do it in a public thread, as I usually read all threads. And I prefer to answer where others can profit from it (or contribute to it) too.
KevinFThe UCTXIFG flag would indicate it's ready to TX again, which it should be once I've finished receiving the byte.
This might not be true. Since SPI may run at a different clock than MCLK. The edges of SPI signals differ from MCLK then and this could cause a problem - as is works then you single step your code line by line and not when running through I would bet at beer it's a timing issue :-)
Hi Jens,
While I hear what your saying. In my case the read phase is 1/2 cycle later and my clock is SMCLK. Why would the buffer (RXBUF) hold the correct value in both cases, or at least appear to be, and yet only when I single step does my variable in the watch window contain the same information? I disable other interrupts with ENTER_TASK and re-store through LEAVE_TASK, which was another source of potential error.
PS: I made the change to check for TXFG however it appeared to make no difference in my watch window.
PPS: One thing I have not done in a while is power everything off which I'll attempt to do now and see if that resolves it.
Hi Jan,
Yeah, my gut says this too but so far I must be having a brain fart. Since both you and Jen's pointed my out my logic fault, I may be assuming too much here although my initial changes to your suggestion didn't appear to resolve the issue. I'l going to compare my captures with my data and restart the whole environment to see if I can see what the differences may be.
Thanks to both you and Jen's for passing along your thoughts. I'll report back if/when I've got this figured but I do appreciate the suggested hints.
So, for now, I'm going to chalk this one up to a strange environment issue. After a complete shutdown (target, FET and CCS - plus comptuer), it seems I am able to observe changes in my variables now in a watch window. The SPI data buffers are now equal to the variables I am using to read too. For some safety, I'm going to add in the above suggestions for alignment of interrupts, reads and writes ... I get what people have been suggesting (thanks Jan and Jen's) . I made some assumptions based on my app and the devices the SPI was talking too but I also get why both of you would suggest the 'correctness' . Thanks to all who took time to either read or write. K
KevinFAfter a complete shutdown (target, FET and CCS - plus comptuer), it seems I am able to observe changes in my variables now in a watch window.