[En-Nut-Discussion] problem using fflush() (Klaus Kloos)
Harald Kipp
harald.kipp at egnite.de
Tue Oct 25 10:26:52 CEST 2011
Hello Klaus,
On 24.10.2011 20:00, Klaus Kloos wrote:
> There is new understanding on my side. The delay is coming from the fwrite(buffer, 1, 512, dmxOut).
> If I write all the bytes one by one there is no delay. Using fflush() after each byte or after the block, does no change this.
When you call fwrite, the data is first moved to a ring buffer. If the
number of bytes in the buffer reach the high water mark, the transmitter
is triggered and the data is sent out in the background, using interrupts.
As far as I can see, the default size of the buffer is 64 and the high
water mark is at 56.
> #define blockgroesse 1 // 2^n, works up to 4, 8 generates delays
> for(lauf=0; lauf<512/blockgroesse; lauf++){
> gesendet = fwrite(&buffer[lauf*blockgroesse], 1, blockgroesse, dmxOut);
> }
> fflush(dmxOut);
This is highly ineffective. Better decrease the high water mark. You may
also increase the total buffer size to 512, so fwrite will return
immediately.
http://www.ethernut.de/nutwiki/Advanced_UART_Functions
> This is a solution for my needs, but there seems to be a problem.
Could be. I remember, that we extensively tested hardware handshake to
make sure that no characters get lost. But your requirement is different
and there may be a yet undiscovered bug.
>> So you might better want to implement the break function directly into
>> the UART driver.
>>
> I think thats beyond my possibilities at the moment. Ethernut and even ARM is new for me. Where to start? Is there an example somewhere?
I agree, that the UART driver is a bit complicated. That's because we
tried to move as much as possible to a hardware independent part and
still make use of hardware specific features as much as possible.
Although I do have many years of experience with UARTs, I can't remember
ever having used the break function. May be we can first define the
requirements to see, what's possible. The datasheet tells, that you have
to set STTBRK in US_CR to start, and then set STPBRK to stop it. The
break signal will last for at least a full character length. DMX512
requires a minimum time of 92us. If I understood it right, this have to
be followed by 12us "inverted break". Hummmm! AFAIK, the UART can't to
this. Thus we have to use GPIO. Furthermore, if we really want the right
timing for the break and MAB, we need to use a hardware timer.
Considering hardware timer, GPIO and UART, I think that it would be a
bad idea to integrate this into the existing UART driver.
I'd do it with native code. You'll probably find an interrupt driven
UART example in the Internet, which is more easy to follow than the
Nut/OS driver. Same is true for the timer, Nut/OS doesn't provide any
except the system timer, which is special.
If you think, that a Nut/OS driver is an advantage (because you want
stdio), then create a dedicated DMX driver. In fact, this is quite easy.
Fortunately I just created a new document, which may be helpful:
http://www.ethernut.de/en/firmware/porting.html
It explains, how to port Nut/OS to a new platform, but also contains
informations about Nut/OS drivers. Note, that it refers to Nut/OS 5.0.
I'd recommend to stick with 4.10. You can get the new sources, which the
document refers to, at
http://ethernut.svn.sourceforge.net/viewvc/ethernut/trunk/
If you need help, please asks here.
Regards,
Harald
P.S.: Many thanks for you work on the IR receiver. I haven't got time,
to look to it, but recently played around with IR remote myself. So I'm
still interested.
More information about the En-Nut-Discussion
mailing list