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