USB host (was Re: What's the real problem with wireless on the Ben?)
Rafael Ignacio Zurita
rafaelignacio.zurita at gmail.com
Wed Oct 5 18:58:42 EDT 2011
Thanks a lot Werner for all the explanations!!!. And for the hardware
I will write a test program to set the registers like you
explained below (and I will use as base the ubb-vga code). Then, my idea,
after to talk with you, is to use some timer to control the time
between values. Then I would be ready to start to check the
pins with the scope, in order to know if the D+ D- values are correct.
Those are my first items in my TODO list.
On Wed, Oct 05, 2011 at 09:41:40AM -0300, Werner Almesberger wrote:
> One more item: the Ingenic SoCs have the somewhat unusual feature
> that many registers are implemented as set/reset flip-flops, and
> to change a bit you have to write a 1 to the corresponding set or
> clear register.
> For example, to set pin PD09 to "1", you would write the value
> 1 << 9 to PDDATS. To set it back to "0", you would write 1 << 9
> to PDDATC instead.
> To set pins PD08 and PD09, you would write 1 << 8 | 1 << 9 to
> PDDATS, etc.
> USB uses differential signaling. This means that if D+ is 0, D-
> must be 1, and vice versa. The exception to this rule are some
> special conditions, like the end-of-packet indication, where
> both are set to 0. This is called a "single-ended 0", abbreviated
> as "SE0". All this is summarized in table 7-2 on page 145 of the
> USB 2.0 specification.
> Changing a pair of pins where one goes 0 -> 1 and the other goes
> 1 -> 0 requires two writes - one to PxDATS to set the pin that
> should become "1", and another one to PxDATC to clear the pin
> that should become "0".
> This has two undesirable properties: 1) port register accesses
> are slow and this therefore burns quite a few CPU cycles,
> 2) there will be a small delay between the pin changes.
> For USB, this means that during this short delay, the bus will
> be in an invalid configuration. I don't know if this will cause
> trouble for low-speed USB, but I wouldn't be surprised if it did.
> Here's an idea for how one could perhaps avoid this problem:
> - configure the GPIO to output D+ = 1, D- = 0 (or the opposite)
> - configure the MMC controller to output, on the same pins,
> D+ = 0, D- = 1.
> - to send a differential "1" (D+ = 1, D- = 0), let the GPIOs
> have the pins
> - to send a differential "0" (D+ = 0, D- = 1), let the MMC
> controller have the pins
> A pin is switched between GPIO and a funcion, e.g., MMC, through
> the "function" register. Again, this register is not set
> directly, but its bits are set or cleared through a set and a
> clear register, respectively.
> With the above approach, the bits in the function register
> both change in the same direction with switching between
> differential 0 and differential 1, so only a single write is
> To send a single-ended "0" (SE0) (D+ = 0, D- = 0), one would
> clear the GPIO data bit for D+ and switch to GPIOs. To return
> from SE0 to differential "1", one would simply set the D+ data
> bit again.
> I've illustrated this here:
> The two flip-flops on top are for the GPIO data. In the middle
> is the MMC controller. The two flip-flops at the bottom are
> for selecting whether a pin is used as GPIO or for a function.
> The pair of multiplexers right of the MMC controller switch to
> GPIO if the corresponding PDFUN bit is 0 and to MMC if the bit
> is 1.
> A few detail remarks and clarifications:
> - the naming convention for the port registers is
> P<port><purpose><access> where
> <port> is A, B, ...
> <purpose> is DAT for the value output on the GPIO, FUN is the
> GPIO/function selection, and so on (see the section on
> "General-Purpose I/O Ports" in the JZ4720 or JZ4740
> Programming Manual)
> <access> is S for set, C for clean, or nothing for reading
> the register's current value.
> - all the MMC pins are on port D. The register names and bit
> numbers shown in the drawing are the ones that actually
> correspond to CLK and CMD.
> - in the Ingenic CPU, whether a function block has access to a
> given pin is controlled on that pin. Enabling or disabling the
> function block per se is independent from its access to pins.
> This is different from the way some microcontrollers handle
> this, where enabling a function block automatically assigns a
> set of I/O pins to it.
> - it should be relatively easy to make the MMC controller
> output a constant bit pattern by setting it to a low clock
> frequency and making it begin sending an MMC command. Then,
> when CMD and CLK have the desired value, stop the clock.
> All the necessary ingredients for selecting the clock and,
> erm, controlling the controller can be found in ubb-vga.c
> Note that the MMC bus clock is the 336 MHZ main clock divided
> first by 1...32 according to register MSCCDR and then by
> 2^0...2^7 according to register MSC_CLKRT.
> - I haven't thought this through enough to be sure whether it's
> more convenient to configure the GPIOs for a differential "1"
> and MMC for a differential "0", or the other way around. I
> think the best choice - if it makes a difference at all - will
> automatically emerge during development.
> - I don't know whether switching a pin between function and GPIO
> is "smooth" or whether there can be glitches. And I also don't
> know if such a switch is, as I assume here, as fast as
> setting/clearing the port's data bit would be.
> All this would have to be verified by measurement.
> - Werner
More information about the discussion