This is the mail archive of the ecos-discuss@sourceware.org mailing list for the eCos project.
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
Other format: | [Raw text] |
Thanks for your advice Andrew. >Yes. Some devices have a FIFO and the interrupt is triggered >when a low water mark is reached. You can then write multiple >bytes to fill the FIFO. Hence the loop. This processor has a 16 byte queue for one of it serial lines, but this is not implemented yet in the driver. >Maybe an interrupt problem. Is the TX interrupt getting >cleared properly when the DSR exists? If not the interrupt >will fire again once interrupts are reenabled. See how many >bytes get send out on average. It should be 1, but if there >are lots of 0s, you have a problem. > > Andrew I've tried to see how the interrupt gets cleared in the code and it doesn't seem to get explicitely cleared. The are two transmit interrput types, one when the single byte buffer is empty and another when the last transmition is complete. The driver as it stands uses the buffer empty interupt which asserts the TDRE (Transmit data register empty) bit in the SCxSR SCI status register. After consulting the processor's manual it say in two places: "The TDRE flag in the status register is readonly." And seemingly contradictory: "New data is not transmitted if TDRx is written without first clearing TDRE." Attempting to write to TDRE causes an exception so I can only assume that the former is true. I've conducted an number of tests at 57600 baud. I have tried putting counters in the following code: static bool mpc555_serial_putc(serial_channel * chan, unsigned char c) { mpc555_serial_info * mpc555_chan = (mpc555_serial_info *)chan->dev_priv; cyg_addrword_t port = mpc555_chan->base; cyg_uint16 scsr; cyg_uint16 scdr; HAL_READ_UINT16(port + MPC555_SERIAL_SCxSR, scsr); if(scsr & MPC555_SERIAL_SCxSR_TDRE) { // Ok, we have space, write the character and return success scdr = (cyg_uint16)c; HAL_WRITE_UINT16(port + MPC555_SERIAL_SCxDR, scdr); return true; } else // We cannot write to the transmitter, return failure return false; } I've put separate counters in both sections that return either true or false. For a 64 byte packet there seems to be a time averaged fixed ratio of about 2.06 times successful sends to no room in buffer sends. Next I've tried to scope out what's going on by toggling some I/O lines. In scope1.tif the cyan trace is my app toggling the state of a pin each time it runs around a loop with cyg_thread_delay(1) and when the orange trace goes low it is entering serial_xmt_char() in serial.c. It brings the line high again only when it leaves the while loop after a sucessful send and nothing else to send, but not if the buffer is still full. It seems to confirm that my app thread's execution is blocked, or at least the timer event is blocked until all of the serial data has been sent. Scope2.tif shows this closer up and that the selayed timer event occurs imediately after serial transmission has finished. For scope3.tif I've added to serial_xmt_char()that it will bring the line high even if it returns because the buffer is full. This should show the interrupt activity. Scope4.tif is the same but zoomed in on the timebase. So 300us are spent idle and only 100us by the DSR attempting to transfer more data for each buffer empty interrupt. Using the same I/O line technique I've checked that the realtime clock ISR and DSR are still being called on a regular basis even during serial transmission. I've also tried reducing the number of clock ticks between time slices to one in cdl, but this semms to make no diffence to the problem. I don't know enough about how the kernel uses the RTC, but is it unrealistic for me to expect the kernel to context switch in 300us, or 12000 cpu cycles @ 40MHz ? For lower baud rates the problem seems to reduce, at 9600 baud there's a tiny amount of jitter in the timer period, at 19200 baud there's noticable jitter, at 38400 there's very heavy jitter and at 57600 baud the timer event just doesn't every occur when serial transmission is in progress. Looks like I'll have to fall back to using the driver interupt-less mode or investigate implementing the 16-byte queue to reduce the magnetude or frequency of the delay problem. Any insight into this is appreciated. Steven
Attachment:
scope4.tif
Description: scope4.tif
Attachment:
scope1.tif
Description: scope1.tif
Attachment:
scope2.tif
Description: scope2.tif
Attachment:
scope3.tif
Description: scope3.tif
-- Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |