Friday, October 4, 2013

modification to using external pin to control the USB D+ line/pin

So I decided to abandon using the jumper switch. It suffers from mechanical bounce and that is a major problem going forward debugging wize. Cant have the usb host mis-interpreting connects and disconnects. Besides I wanted a purely software solution since that will allow me to debug this remotely without having to stand in front of the board pushing and holding the pushbutton switch-hack I used previous to this.

My solution?
The realization that the external pin ALONE does not produce enough current to drive the USB D+ pin high. So my work around was to take a 3 position jumper and tie all three leads together - and plug it into J6 effectively driving D+ to vcc by DEFAULT.

Then connect one of the jumper positions to pin PA0. Now when the software loads it calls stm32_usb_disconnect_pullup() which sets PA0 as an output and pulls it down to ground (0). then later when the user presses "c" on the terminal I call stm32_usb_connect_pullup() which sets PA0 as in input and floating - which drives D+ back up to VCC. This results seen on my Total Phase USB Sniffer is as I expected!!!

Clever?
Yeah ... thats me


/*
 **********************************************************************
 *description:  setup particular portA pin to an input, so its no
 *              longer driving the pin
 *input:        unsigned int wdPin = PAx pin number to use. it must be
 *              portA block pins ONLY
 *note:         this should be called inside the usb isr on RESET flag
 *implemented:  using three position jumper pin with all three wire
 *              wrapped linked - and a jumper from PAx to one of the
 *              positions
 **********************************************************************
 */
void    stm32_usb_connect_pullup(unsigned int wdPin)
{
volatile unsigned int wdTemp, wdMask;


wdTemp  = (*PTR_STM32_GPIO_A_CRL);
wdTemp &= ~(0x0f << (wdPin << 2));
wdMask  = ((STM32_GPIO_CNF_IN_FLOATING << 2) | \
            STM32_GPIO_MODE_INPUT_MODE) << (wdPin << 2);

(*PTR_STM32_GPIO_A_CRL)  = (wdMask | wdTemp);
}





/*
 **********************************************************************
 *description:  I am using PAX (external wire to Dplus pin on J6 facing
 *              the USB connector) to pull up the line to trigger the
 *              USB HOST enumeration. 
 *              setup PAX to generic output. pull it high 
 *input:        unsigned int wdPin = PAx pin number to use. it must be
 *              portA block pins ONLY
 **********************************************************************
 */
void    stm32_usb_disconnect_pullup(unsigned int wdPin)
{
volatile unsigned int wdTemp, wdMask;


(*PTR_STM32_GPIO_A_BSRR) = ((1 << wdPin) << 16);

wdTemp  = (*PTR_STM32_GPIO_A_CRL);
wdTemp &= ~(0x0f << (wdPin << 2));
wdMask  = ((STM32_GPIO_CNF_OUT_GEN_PUSH_PULL << 2) | \
            STM32_GPIO_MODE_OUTPUT_2MHZ) << (wdPin << 2);

(*PTR_STM32_GPIO_A_CRL)  = (wdMask | wdTemp);
} 
 
 
 
 
 
 
 

No comments:

Post a Comment