Page 1 of 1

Spurious RX character on SD

Posted: Mon Dec 21, 2015 1:23 pm
by avrhack
This should be simple but I can't for the life of me see what I'm doing wrong!

When I enable the SD driver I get a spurious receive character. I've paid attention to the port settings and order i.e. I set as an input with pullup to ensure the RX pin sees a '1', then I start the SD driver, then I set the alternate mode to select the pin into the SD USART.

And a character is generated for no reason.

Any thoughts welcome.

Re: Spurious RX character on SD

Posted: Mon Dec 21, 2015 2:57 pm
by Giovanni
This is strange, no idea but I would think to some HW reason. Try putting a delay before enabling the SD driver.

Giovanni

Re: Spurious RX character on SD

Posted: Mon Dec 21, 2015 8:14 pm
by avrhack
Yeah it is strange. Already tried a delay thanks. And I can't see it's a hardware issue as it happens on two different STM32's that I have, one of which is connected to an RS232 level converter that is dormant i.e. pulled up, the other of which has no connection at all so the RX line should float high with the weak pull up.

This suggests that despite there being a pull up, something is generating a spurious character on SD.

In terms of code, the reading is done in a separate thread with a tight loop:

while(1)
{
ch = chnGetTimeout(d,TIME_INFINITE);
sdPut(d, ch);
}

So again there's nothing clever there. Something is causing ChibiOS to return a character at startup despite all the pull-ups and initialisation sequencing.

I'm sure it's my code / software setup otherwise others would have spotted this in ChibiOS, just can't figure out what it is!

Re: Spurious RX character on SD

Posted: Sat Dec 26, 2015 5:57 pm
by rew
In my experience, when you enable an SPI module it might have a "recieved character" waiting for you.

On SPI, as a master, you have to transmit before a character can be recieved. So <transmit character> <wait for RXNE> would immediately continue, and you don't get the data you expect... I've fixed it by adding a "while (RXNE) discard (spi->DR)" before transmitting.

It could be (and prossibly that's what Giovanni calls "hardware") that the USART hardware is similar, when starting up there might already be a character in the input FIFO.

Would:

Code: Select all

ch = chnGetTimeout(d,SHORT);
while(1) {
  ch = chnGetTimeout(d,TIME_INFINITE);
  sdPut(d, ch);
}
work for you?

Re: Spurious RX character on SD

Posted: Sat Dec 26, 2015 6:11 pm
by avrhack
rew wrote:In my experience, when you enable an SPI module it might have a "recieved character" waiting for you.

On SPI, as a master, you have to transmit before a character can be recieved. So <transmit character> <wait for RXNE> would immediately continue, and you don't get the data you expect... I've fixed it by adding a "while (RXNE) discard (spi->DR)" before transmitting.

It could be (and prossibly that's what Giovanni calls "hardware") that the USART hardware is similar, when starting up there might already be a character in the input FIFO.

Would:

Code: Select all

ch = chnGetTimeout(d,SHORT);
while(1) {
  ch = chnGetTimeout(d,TIME_INFINITE);
  sdPut(d, ch);
}
work for you?


That's probably the quickest and easiest way to do it for sure. I'm just a bit OCD and like to know the cause rather than just the solution, but you're right - I should just change my code like this and move on :)

Re: Spurious RX character on SD

Posted: Sat Jan 02, 2016 12:24 pm
by rew
I have "just fixed it and moved on".

On the other hand, you're right that finding the real cause can help understanding.

I have the impression that when debugging and having the CPU under debugger-control a restart of the processor does not always completely reset the CPU. So, you might be seeing the "last RX" character from BEFORE the start of your application".

Another option is that simply enabling the hardware module is not enough to reset the module. We have the "RCC" module that controls clocks and resets to the IO modules. Possibly the code just enables the clock to the module and "hopes" that the module was "reset" by the reset-pulse that started the CPU. Quite possibly (from a hardware viewpoint) that is not the case: When the CPU is reset, the RCC resets and disables the clock to all IO modules. Applying a reset pulse to a module that doesn't have a clock will probably not clear the registers to their reset values. So maybe the proper way to enable a module is to assert reset, enable the clock and then deassert that module's reset signal.