Tuesday, September 3, 2013

unsupported timers and usb connect

Discovered that timers 5 ,6  and 7 arent supported on low density stm32 devices like the one I have - stm32f103. So now I am using timer 2 for implementing uS and mS Delays. The stm32_timer_uS_delay() routine is posted below.





/*
 **********************************************************************
 *description:  delay wdUs ticks
 *input:        unsigned int wdUs = number of uS ticks to delay for
 *note:         use timer2. its tied to a 36Mhz reference (PCLK1)
 **********************************************************************
 */
void    stm32_timer_uS_delay(unsigned int wdUs)
{
volatile unsigned int wdTemp, wdPr;

if(wdUs > 1000000)
        wdUs = 1000000;


/*adjust preload counter if greater than 1000*/
if(wdUs > 1000)
        {
        wdUs /= 1000;
        wdPr  = 36000;
        }
else
        wdPr  = 36;



/*
 **********************************************************************
 *disable timer
 *clear status
 *clear interrupt enable reg
 *clear control reg 2
 *then
 *setup prescaler value
 *setup autoreload (for count up)
 *clear the status register' UIF bit
 *then set control reg 1 OPM + CEN
 *finally
 *loop on status register checking UIF
 **********************************************************************
 */
(*PTR_STM32_TIM2_CR1) = 0;
(*PTR_STM32_TIM2_SR)  = 0;
(*PTR_STM32_TIM2_DIER)= 0;
(*PTR_STM32_TIM2_CR2) = 0;

(*PTR_STM32_TIM2_PSC) = wdPr;
(*PTR_STM32_TIM2_ARR) = wdUs;
(*PTR_STM32_TIM2_SR)  = STM32_TIM_SR_UIF;

wdTemp  = STM32_TIM_CR1_OPM;
wdTemp |= STM32_TIM_CR1_CEN;
(*PTR_STM32_TIM2_CR1) = wdTemp;

do
        {
        wdTemp  = (*PTR_STM32_TIM2_SR);
        wdTemp &= STM32_TIM_SR_UIF;
        }while(wdTemp != STM32_TIM_SR_UIF);
}






So the issue of bus enumeration (beginning with RESET) became an issue this weekend. On the stm32f103 board D+ is tied to vcc via jumper J6. This is optional. I dont like this setup because during debugging I like the freedom to connect and disconnect the usb device. This necessitates pulling D+ high to connect and pulling it low later to disconnect.

I wanted a means to do this in software and the stm32 core doesnt appear to have the software CONNECT feature I found on the nxp lpc2378. So I decided to tack a jumper wire between PA0 (user headers) and D+. This allows me to setup PortA and pin 0 as an output and drive it high when I am ready to initiate the host to usb enumeration process.

Clever right?
I thought so too ... routine for me

I wrote stm32_usb_connect_pullup() and stm32_usb_disconnect_pullup() to realize this. They are meanth to be called in usb_test.c/main() after stm32_init() and stm32_usb_init()




/*
 **********************************************************************
 *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_connect_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);
wdMask  = ((STM32_GPIO_CNF_OUT_GEN_PUSH_PULL << 2) | \
            STM32_GPIO_MODE_OUTPUT_10MHZ) << (wdPin << 2);

(*PTR_STM32_GPIO_A_CRL)  = (wdMask | wdTemp);

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





/*
 **********************************************************************
 *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
 **********************************************************************
 */
void    stm32_usb_disconnect_pullup(unsigned int wdPin)
{
volatile unsigned int wdTemp, wdMask;


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

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















No comments:

Post a Comment