Additionally just below the call to msleep() linked to above you have
nested loops two deep so . . .
http://stackoverflow.com/questions/24643432/big-o-nested-while-loop

On Mon, Mar 21, 2016 at 1:44 PM, William Hermans <[email protected]> wrote:

> So, I'm just now getting back to you, and I see you all have been
> discussing things I have not fully read about yet. Anyway I will say that I
> have zero hands on with LKM's, but I do have a decent amount of hands on
> with C in userspace. One thing that sticks out to me . . .
> https://github.com/davidgood1/ledmsgchar/blob/master/ledmsgchar.c#L359
>
> msleep(n) where n is a value in microseconds. I honestly do not know how
> responsive timers are in kernel space, but in userspace high resolution
> timers do not work. It does not matter if one uses an RT kernel or not. So
> system API calls such as usleep() really do not work, as there is some
> system call overhead involved. In kernel space . . . again I have no hands
> on personally, but I'd be leery of any sleep() type call until I actually
> tested it on the specific platform I planned using it on.
>
> On Mon, Mar 21, 2016 at 1:23 PM, Harvey White <[email protected]>
> wrote:
>
>> On Mon, 21 Mar 2016 14:31:56 -0500, you wrote:
>>
>> >So, let me see if I understand your idea:
>> >My display looks like this:
>> >R0 <Common data outputs: 144 pixels (18 bytes)>
>> >...
>> >R7 <Common data outputs>
>>
>> Ah, ok, dot matrix then.
>> >
>> >Data is written to the LED drivers while power is applied to one row.
>> >Then, new data is written and power is applied to the next row, etc.
>> >
>> >"I'd be tempted to do the following approach:  Divide the scan time
>> >into one slot per digit plus one.  Use that time to allow synchronized
>> >refresh to the display itself."
>> >
>> >When you say "digit", I assume you are thinking in terms of a multiplexed
>> >7-segment readout style display, which in my case would be the same thing
>> >as a row.  My driver operates on one row at a time before going to sleep.
>> >Are you suggesting that I scan through all 8 rows and then have a special
>> >9th "row" time where I do things like the memcpy?  This would be pretty
>> >close to a VSYNC idea, right?  I suppose that this 9th "row" wouldn't
>> have
>> >to wait a full row time, but could schedule the next row sooner.  Hmm....
>> >
>>
>> Exactly, VSync or Hsync depending on what analogy you want.  In this
>> case, Vsync would be right.
>>
>> If you're doing an operating system, then your timing is really
>> generated by interrupts, so I'd be using a relatively high priority
>> hardware interrupt from a timer here, or if you want to do an
>> operating system, then just give the remaining time back to the OS so
>> it can pick the next task.  No need to chew up one tick period.
>>
>> In my OS, tasks suspended or delayed check the time (or semaphore) or
>> yield back the time, then the OS simply looks for the next active
>> task.
>>
>>
>>
>> >You are totally right about MCUs and burning the LEDs.  This particular
>> >display is safe because the LEDs are not being over-driven.  Your idea
>> >about a CPLD is a good one.  I've never used them, but have know about
>> >them.  I found this XC2C32A for $1.8USD.  I will probably try this out at
>> >some point just for educational purposes :)
>>
>> You would want the Xilinx free version of their web support (ISE),
>> which works fine those chips.  You'll need to find the USB programming
>> cable as well, I got mine from Amazon.
>>
>> There are times when it's nice to be able to throw hardware at a
>> problem.  You have the driver done well enough, but IIRC, there are
>> some subsystems out there that do this.  A simple Atmel Mega processor
>> would work well for this, if you wanted.
>>
>> The nice thing about the XC2C32A and the Xc2C64A is that they have
>> exactly the same footprint.  Once you get to 128 or 256 cells, you go
>> to a TQFP-100 package.
>>
>> I'd recommend VHDL (simply because I like it) for the design language.
>> Remember that in VHDL you do not have to design components like chips,
>> but you can tell the chip "I want a divide by 37 counter" by
>> explaining how it counts, and then let the program built it.  This
>> makes it an easier design process than designing the counter with
>> logic by itself.
>>
>> Harvey
>>
>>
>> >
>> >
>> http://www.digikey.com/product-detail/en/xilinx-inc/XC2C32A-6VQG44I/122-1704-ND/1952030
>> >
>> >--David
>> >
>> >
>> >On Mon, Mar 21, 2016 at 12:28 PM, Harvey White <[email protected]>
>> >wrote:
>> >
>> >> On Mon, 21 Mar 2016 11:16:49 -0500, you wrote:
>> >>
>> >> >Hmm... I'm using UCN5821 driver chips from Allegro.  They do indeed
>> have a
>> >> >hardware latch (strobe) which latches the received serial data from
>> the
>> >> >internal shift register to the outputs.
>> >> >
>> >> >My write algorithm is (per row):
>> >> >1> set_current_state(TASK_RUNNING)
>> >>
>> >> For state 2, I'd be tempted to do a non-interruptible write to the
>> >> display memory (or protect it by a semaphore).  You want to interlock
>> >> the process so that you have a safe zone to write new data to the
>> >> memory.
>> >> >2> If new data is ready in RAM, memcpy it to the real display buffer
>> in
>> >> RAM.
>> >>
>> >> This should not cause a problem unless the data changes somehow.
>> >> >3> Serially shift out next row data in the background, but do not
>> latch
>> >> yet
>> >> >(background)
>> >>
>> >> This may be too fast for you to see, and you don't want it slow.
>> >>
>> >> >4> Blank the display - This is not actually working right now.  I
>> never
>> >> see
>> >> >the blank line move. Hmm....
>> >>
>> >> I'm assuming you have the data for the new row in the buffer, of
>> >> course,
>> >>
>> >> >5> Adjust the multiplexed row select pins to the next row (A2...A0)
>> >> >6> Latch the data already in the serial buffers
>> >>
>> >> Problem with blanking and unblanking the whole display could cause
>> >> flicker.
>> >> >7> Unblank the display
>> >> >8> set_current_state(TASK_INTERRUPTIBLE)
>> >> >9> usleep until time to update next row
>> >> >
>> >> >I wanted to spend a little time as possible with the LEDs off, which
>> is
>> >> why
>> >> >I'm shifting data while the LEDs are still showing the current row
>> data.
>> >>
>> >> That shouldn't be a problem at all, the chip is designed for it.
>> >>
>> >> >Using this technique, I've seen ghosting issues when a mcu is very
>> fast as
>> >> >the drivers themselves need a little time to switch the state of their
>> >> >outputs, and also the high-side switching power transistors sometimes
>> need
>> >> >some time to fully turn off.  I don't think that's what I'm seeing
>> here
>> >> >though.
>> >>
>> >> Let's assume that it is a problem, so you can fix that.
>> >> >
>> >> >The display artifacts that I see look like stuttering on the display
>> when
>> >> >the processor gets busy.  I suspect that this is due to inconsistent
>> >> usleep
>> >> >times (Linux isn't an RTOS) but I'm still trying to catch it with my
>> logic
>> >> >analyzer.
>> >> >
>> >>
>> >> I've had similar task interlocking problems with an RTOS, but I'd
>> >> suggest a slightly different approach.
>> >>
>> >> >My basic question is this: Does the Linux kernel "usually" do this
>> kind of
>> >> >bit-banged driver for other things (I2C, video, framebuffers, audio,
>> etc.)
>> >> >or does it "usually" pass these tasks off to hardware peripherals?
>> The
>> >> >question behind the question is: Am I doing this the "usual" way or
>> am I
>> >> >trying something very specialized.
>> >>
>> >> Not an expert on Linux at all, but it depends on the data rates, and
>> >> whether or not there's hardware available to do it.
>> >>
>> >> >
>> >> >My goal is to look into the framebuffer devices and see if I can learn
>> >> >anything there, but kernel programming is very new to me.
>> >>
>> >> Kernel programming (for microprocessors) is not all that bad, but
>> >> there are things you probably don't think of when writing kernel level
>> >> drivers and code.
>> >>
>> >> 1) everything is asynchronous
>> >> 2) this can be inconvenient
>> >> 3) lots of mechanisms exist to keep this from happening
>> >>
>> >> I'd be tempted to do the following approach:  Divide the scan time
>> >> into one slot per digit plus one.  Use that time to allow synchronized
>> >> refresh to the display itself.  You may need to limit the on time
>> >> depending on your sink current (per driver's data sheet).
>> >>
>> >> Assuming you use a semaphore, then while actively scanning digits, the
>> >> scanning process "owns" it.  During the update time, the scanning
>> >> process gives it back.  The update process can grab that, then can
>> >> update all the ram buffers that the scanning process uses.  The update
>> >> process then gives back the semaphore and the scanning process can
>> >> grab it again during the next scan time.  Result: display does all RAM
>> >> updates while blanked.
>> >>
>> >> Now for the scan itself.  Assuming the scan time has just happened,
>> >> you may want to disable task switching.  shift in the new data, switch
>> >> the row drivers off, then latch the column data, then enable the new
>> >> row drivers.  Since darlingtons are slow, I'd be looking at the
>> >> driving waveforms for the darlington outputs to the display for any
>> >> overlap.  Shouldn't be much, though, if any.  Some software delays of
>> >> a few microseconds may be needed.  At this point, enable task
>> >> switching for the OS and you're in good shape.
>> >>
>> >> The problem with multiplexed displays run directly by a microprocessor
>> >> is debugging during the scan cycle, where the average display current
>> >> can exceed the steady state limits for the display.  I'd have been
>> >> tempted to put in a small CPLD which appears as external registers to
>> >> the processor, and then allow the hardware to do all the work.  Xilinx
>> >> coolrunner II 32 or 64 cell chips are cheap, 3.3 volt I/O, and need
>> >> (IIRC) 1.5 volts.  Not too bad and the display stays happy.
>> >>
>> >> Harvey
>> >>
>> >> >
>> >> >Thanks for your feedback!
>> >> >
>> >> >--David
>> >> >
>> >> >
>> >> >On Mon, Mar 21, 2016 at 9:40 AM, Harvey White <[email protected]
>> >
>> >> >wrote:
>> >> >
>> >> >> On Mon, 21 Mar 2016 01:20:34 -0500, you wrote:
>> >> >>
>> >> >> I've often seen artifacts in LED displays where the write to the
>> >> >> display process (which should be amazingly short for each digit) is
>> >> >> interrupted.  You might be seeing some differences in digit
>> brightness
>> >> >> as well.
>> >> >>
>> >> >> Once you have the pattern in Ram, ready to be written, you would
>> >> >> ideally update right at the beginning of each scan for each digit.
>> You
>> >> >> want to make sure that the pattern is not updated during the active
>> >> >> strobe to display process as well.  (I'm assuming that there's a
>> >> >> hardware latch in there that you write, and you're not depending on
>> >> >> the output pins to be constant, that strobe to activate the display
>> is
>> >> >> also a latch).  This approach would minimize the critical time where
>> >> >> the display data cannot be interfered with.  This would ideally be
>> in
>> >> >> the microsecond range (i.e. turn off previous strobe, load next
>> data,
>> >> >> turn on this strobe).  That part of the code cannot be interrupted
>> and
>> >> >> should ideally protected by turning interrupts off during those few
>> >> >> instructions.
>> >> >>
>> >> >> So the first question to ask is "what's going on with the strobes
>> and
>> >> >> data?"
>> >> >>
>> >> >> Harvey
>> >> >>
>> >> >>
>> >> >>
>> >> >> >Ok, I posted the full source code here:
>> >> >> >https://github.com/davidgood1/ledmsgchar
>> >> >> >
>> >> >> >I'm not sure that userspace has much to do with what I'm seeing
>> right
>> >> now.
>> >> >> >I'm using a kthread that runs until a flag is set indicating that
>> >> there is
>> >> >> >a new buffer of data ready from user space and my task (update_row)
>> >> copies
>> >> >> >the buffer, so no one should be waiting on slow user space
>> operations,
>> >> but
>> >> >> >maybe there's something I don't see.
>> >> >> >
>> >> >> >I didn't know if I was getting interrupted in the memcpy call in
>> >> >> >update_row, so I am going to try to copy the buffer by rows one
>> call
>> >> at a
>> >> >> >time rather than copy the whole buffer at once.
>> >> >> >
>> >> >> >Also, I notice that I see visual artifacts whenever anything else
>> is
>> >> going
>> >> >> >on, such as ssh, typing on the terminal, etc.  The CPU usage is ~3%
>> >> using
>> >> >> >the timing in the file right now.  BTW, the update_row task
>> regulates
>> >> its
>> >> >> >timing by calling usleep_range() which is supposed to be backed by
>> high
>> >> >> >resolution timers.  I am using the same number on the upper and
>> lower
>> >> >> >bounds to try and force stricter timing and because when I did +/-
>> 10%
>> >> you
>> >> >> >could definitely see more visual artifacts.
>> >> >> >
>> >> >> >Also, you will notice that the strobe pin is toggled high and then
>> >> >> >immediately low, which I've measured to be about 2us.  So, that
>> seems
>> >> to
>> >> >> be
>> >> >> >the best the gpio interface can do.
>> >> >> >
>> >> >> >Thanks!
>> >> >> >
>> >> >> >--David
>> >> >> >
>> >> >> >On Sun, Mar 20, 2016 at 11:03 PM, William Hermans <
>> [email protected]>
>> >> >> wrote:
>> >> >> >
>> >> >> >> OK so yes, seeing your code would help us understand what you're
>> >> >> >> bottleneck but I've a pretty good idea why you're LCD matrix
>> refresh
>> >> is
>> >> >> so
>> >> >> >> slow. It has to do with userspace communicating with kernel
>> space,
>> >> and
>> >> >> >> you're either invoking some system API calls ( which are
>> notoriously
>> >> >> slow
>> >> >> >> ), or you're copying data from userspace to kernel space, which
>> >> again is
>> >> >> >> slow.
>> >> >> >>
>> >> >> >> The reason I said to show us some code above however is that I
>> think
>> >> it
>> >> >> >> *should* be possible to use /dev/mem/ + mmap() to access whatever
>> >> you're
>> >> >> >> controlling. Using mmap() in this manner gives you no userspace
>> to
>> >> >> kernel
>> >> >> >> overheard . . . but again I need to see some relevant code to
>> give
>> >> you a
>> >> >> >> better idea how that might work.
>> >> >> >>
>> >> >> >> On Sun, Mar 20, 2016 at 8:58 PM, William Hermans <
>> [email protected]>
>> >> >> >> wrote:
>> >> >> >>
>> >> >> >>> Show us some code.
>> >> >> >>>
>> >> >> >>> On Sun, Mar 20, 2016 at 6:28 PM, David Good <
>> [email protected]>
>> >> >> >>> wrote:
>> >> >> >>>
>> >> >> >>>> Hi All,
>> >> >> >>>>
>> >> >> >>>> I've been experimenting with embedded linux and matrixed LED
>> >> displays.
>> >> >> >>>> I started on a Raspberry pi user space program, but could see
>> >> visual
>> >> >> >>>> artifacts on the display due to inconsistent timing of my sleep
>> >> >> command.
>> >> >> >>>> So, I figured that moving the basic row scanning into the
>> kernel
>> >> >> would help
>> >> >> >>>> out.  After failing to get the right kernel headers for the
>> pi, I
>> >> >> switched
>> >> >> >>>> to a BeagleBone White.  I've now got a working character
>> device LKM
>> >> >> which
>> >> >> >>>> takes new images by writing ASCII formatted hex strings to the
>> >> device
>> >> >> in
>> >> >> >>>> /dev.  The performance is pretty good, but not great.  I still
>> see
>> >> >> visible
>> >> >> >>>> artifacts, but am playing with things.
>> >> >> >>>>
>> >> >> >>>> My basic question is this: I know that Linux is not a RTOS, so
>> >> timing
>> >> >> >>>> will never be guaranteed, yet linux does a lot of things very
>> >> quickly
>> >> >> >>>> (video, audio, i2c, etc).  My driver is bit-banging a spi like
>> >> stream
>> >> >> over
>> >> >> >>>> 8 rows at a rate of ~3ms per row (333Hz row scanning or ~41Hz
>> per
>> >> >> complete
>> >> >> >>>> frame) and is really struggling.  How does linux usually get
>> large
>> >> >> smooth
>> >> >> >>>> video at over 60FPS while doing other things???  Is it simply
>> >> taking
>> >> >> >>>> advantage of special hardware resources?
>> >> >> >>>>
>> >> >> >>>> The obvious solution for this display is to use a little 8051
>> or M0
>> >> >> >>>> microcontroller (or PRU!) and let the Bone feed it over uart or
>> >> >> something,
>> >> >> >>>> but I really thought I could do better with the LKM.
>> >> >> >>>>
>> >> >> >>>> Am I just doing something totally wrong?  Any other ideas?
>> >> >> >>>>
>> >> >> >>>> Thanks!
>> >> >> >>>>
>> >> >> >>>> --David
>> >> >> >>>>
>> >> >> >>>> --
>> >> >> >>>> For more options, visit http://beagleboard.org/discuss
>> >> >> >>>> ---
>> >> >> >>>> You received this message because you are subscribed to the
>> Google
>> >> >> >>>> Groups "BeagleBoard" group.
>> >> >> >>>> To unsubscribe from this group and stop receiving emails from
>> it,
>> >> send
>> >> >> >>>> an email to [email protected].
>> >> >> >>>> For more options, visit https://groups.google.com/d/optout.
>> >> >> >>>>
>> >> >> >>>
>> >> >> >>>
>> >> >> >> --
>> >> >> >> For more options, visit http://beagleboard.org/discuss
>> >> >> >> ---
>> >> >> >> You received this message because you are subscribed to the
>> Google
>> >> >> Groups
>> >> >> >> "BeagleBoard" group.
>> >> >> >> To unsubscribe from this group and stop receiving emails from it,
>> >> send
>> >> >> an
>> >> >> >> email to [email protected].
>> >> >> >> For more options, visit https://groups.google.com/d/optout.
>> >> >> >>
>> >> >>
>> >> >> --
>> >> >> For more options, visit http://beagleboard.org/discuss
>> >> >> ---
>> >> >> You received this message because you are subscribed to the Google
>> >> Groups
>> >> >> "BeagleBoard" group.
>> >> >> To unsubscribe from this group and stop receiving emails from it,
>> send
>> >> an
>> >> >> email to [email protected].
>> >> >> For more options, visit https://groups.google.com/d/optout.
>> >> >>
>> >>
>> >> --
>> >> For more options, visit http://beagleboard.org/discuss
>> >> ---
>> >> You received this message because you are subscribed to the Google
>> Groups
>> >> "BeagleBoard" group.
>> >> To unsubscribe from this group and stop receiving emails from it, send
>> an
>> >> email to [email protected].
>> >> For more options, visit https://groups.google.com/d/optout.
>> >>
>>
>> --
>> For more options, visit http://beagleboard.org/discuss
>> ---
>> You received this message because you are subscribed to the Google Groups
>> "BeagleBoard" group.
>> To unsubscribe from this group and stop receiving emails from it, send an
>> email to [email protected].
>> For more options, visit https://groups.google.com/d/optout.
>>
>
>

-- 
For more options, visit http://beagleboard.org/discuss
--- 
You received this message because you are subscribed to the Google Groups 
"BeagleBoard" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to