2010-08-15 05:07 PM
USART not working
2011-05-17 05:02 AM
I've done USART1 polled from assembler, which worked fine with minimal initialization. I also cleared the prescaler.
While I can't micro analyze your code fragment, and can offer the following quick suggestions. Make sure you have all you clocks and clock sources set correctly. USART2 runs off the 36 MHZ PCLK1 (APB1), for 9600 baud the divider is surely 0x0EA6 not 0x1D4C Make sure you have set up the GPIO pins correctly to match the peripheral setting, pin directions, etc. Have your code stream out a byte or pattern of bytes on USART2, check that you can see this data on HyperTerminal or RealTerm (better). Confirm you can see data, and baud rate is correct. Check also on scope if you get junk. Have your code do polled input, verify it receives the correct data, or echo back the data so you can see it in your terminal. Make sure you have initialized the NVIC correctly, you have priorities/groups and interrupt set up correctly, and enabled. Check also the vector address, and the servicing subroutines.2011-05-17 05:02 AM
My assembler for USART1 running straight out of the reset time HSI (8MHz) looks like this. Admittedly somewhat cruder in implementation, it was designed to get the job done and allow for bus fault analysis very early in the boot prior to a working C platform.
408 0000017C InitUART PROC 409 0000017C 410 0000017C 484E ldr r0, =0x40021000 ; RCC 411 0000017E 412 0000017E ; ldr r1, =0x00000000 ; HSI as clock 413 0000017E ; str r1, [r0, #4] ; RCC_CFGR 414 0000017E 415 0000017E F244 0104 ldr r1, =0x00004004 ; USART1EN | IOPAEN (GPIOA) 416 00000182 6181 str r1, [r0, #24] ; +24 RCC_APB2ENR 417 00000184 418 00000184 484D ldr r0, =0x40010800 ; GPIOA 419 00000186 420 00000186 494E ldr r1, =0x444444B4 ; PA.9 USART1_TX 50MHz AF_PP 421 00000188 6041 str r1, [r0, #4] ; +4 GPIOx_CRH 422 0000018A 423 0000018A 4843 ldr r0, =0x40013800 ; UART1 424 0000018C 425 0000018C 2100 movs r1, #0 426 0000018E 8081 strh r1, [r0, #4] ; +4 USART_DR 427 00000190 428 00000190 2145 movs r1, #69 ; 8MHz / 69 == 115200 429 00000192 8101 strh r1, [r0, #8] ; +8 USART_BR 430 00000194 431 00000194 F45F 61C0 movs r1, #0x0600 432 00000198 8201 strh r1, [r0, #16] ; +16 USART_CR2 = 0x600 433 0000019A 434 0000019A 2100 movs r1, #0 435 0000019C 8201 strh r1, [r0, #16] ; +16 USART_CR2 = 0 436 0000019E 437 0000019E 2100 movs r1, #0 438 000001A0 8301 strh r1, [r0, #24] ; +24 USART_GTPR = 0 - Prescaler 439 000001A2 440 000001A2 F242 010C movw r1, #0x200C ; 8-bit, no parity, enable TX,RX 441 000001A6 8181 strh r1, [r0, #12] ; +12 USART_CR1 442 000001A8 443 000001A8 F04F 020A ldr r2, =10 ; Send 10 pounds 444 000001AC F8D0 1000 iu1 ldr.w r1, [r0, #0] ; USART->SR 445 000001B0 F011 0180 ands r1, #0x80 ; TXE 446 000001B4 D0FA beq iu1 447 000001B6 F04F 0123 mov r1, #'#' 448 000001BA F8C0 1004 str.w r1, [r0, #4] ; USART->DR 449 000001BE F1B2 0201 subs.w r2, r2, #1 ; $1 450 000001C2 D1F3 bne.n iu1 451 000001C4 452 000001C4 4770 bx lr 453 000001C6 454 000001C6 ENDP2011-05-17 05:02 AM
Hi clive, many thanks for your reply.
Ok, I have fixed the baud rate. I did not know that USART2 did not run at 72mHz. This info is literally buried in tiny italic type in the manual. I am pretty sure that I have all other settings done correctly, although I have nothing to go on except some C code that you posted in answer to another query on the forum. There should be a section in the manual that tells you EVERYTHING you have to set up in order to get usart reception and transmission happening. C programmers are lucky because they have libraries they can use, we assembler programmers have nothing! The only thing I am not sure of is the priorities/groups you mention. I am not using the receive or transmit interrupts at the moment so I don't think priorities are relevant and I don't know what a ''group'' is, there is nothing I can see in the STM32F103 Reference Manual referring to groups in this context. If you can shed some light on this I will know whether I need to do anything with it. Having fixed the baud rate and cleared the prescaler I have tried again. This time with the two USARTS connected to each other with a null modem cable. The TXE flag is being sent on transmission but I am not receiving anything. Anything you can suggest would be greatly appreciated.2011-05-17 05:02 AM
The source clock for the USARTs also manifests in the maximum speeds, USART2 and 3 are limited to 2.25 Mbaud, vs 4.5 Mbaud for USART1. It gets coverage in a couple of places in the STM32 Reference Manual. The C/Library code holds a lot of the details and interplay, so even if you have to code in assembler you should review the library source to see how the device works in practice.
As for debugging the USART, consider sending out a constant stream of characters. Verifying on a scope that the data is correct and has the right rate/form. Stream it to a PC, and/or loopback the TX and RX to confirm. The output of the USART is CMOS 3.x Volts, and is not suitable to direct connection to a PC, you will need a CMOS to RS232 level conversion (MAX232, et al). USART1 is 5V tolerant, not so sure the others. I've mentioned the voltage issues, as I'm not sure if you are using a dev board or some custom hardware. One additional note on the USARTs is to make sure you check for and clear reception errors (by reading the data register). If you just look at RXNE it has the potential to stay low, while other errors are pending. With Keil I can certainly step through all the of C and assembler code, and view the peripheral states/settings. You might want to step your way through the code to make sure nothing is faulting. The NVIC allows you to group together interrupts of similar priority (with a programmable mask), so they won't preempt each other, the configuration is rather flexible. One gotcha in the implementation is not to give any interrupts within a group the same sub-priority, easy to do if you cut-n-paste code. http://www.codextr.com/migrating-arm7-code-to-a-cortex-m3-mcu-1/ In the C portion of my system using all 3 USARTs the NVIC configuration looks like this. The interrupt routines themselves do little more than check the assorted status and move data to/from software buffers. void NVIC_Configuration(void) { NVIC_InitTypeDef NVIC_InitStructure; u8 Priority; NVIC_SetVectorTable((u32)(&__Vectors), 0x0); // Smart Base Location /* Configure the NVIC Preemption Priority Bits */ NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; Priority = 0; /* Enable the USART3 Interrupt */ NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQChannel; NVIC_InitStructure.NVIC_IRQChannelSubPriority = Priority++; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); /* Enable the USART2 Interrupt */ NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQChannel; NVIC_InitStructure.NVIC_IRQChannelSubPriority = Priority++; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); /* Enable the USART1 Interrupt */ NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQChannel; NVIC_InitStructure.NVIC_IRQChannelSubPriority = Priority++; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); /* SysTick is a SubPriority 3 - Handled elsewhere*/ SysTickPriority = Priority++; /* Enable the EXTI Interrupt */ NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQChannel; NVIC_InitStructure.NVIC_IRQChannelSubPriority = Priority++; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); /* Enable the RTC Alarm Interrupt */ NVIC_InitStructure.NVIC_IRQChannel = RTCAlarm_IRQChannel; NVIC_InitStructure.NVIC_IRQChannelSubPriority = Priority++; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); }2011-05-17 05:02 AM
Hi Clive, many thanks for your post.
I am using the STM32F103ZE development board with IAR Embedded Workbench IDE. My project is to receive data over USART2 and USART3 and send data out on USART1. As I am not a C programmer, looking at C code does not help me. I did do this but just got more confused. I cannot even get the Hyperterm Interrupt example that came with the Standard Peripheral Library to work. Below are the register settings I am making. As there is no guidance in the STM32F103 Reference Manual as to exactly what registers you have to deal with when using the USARTS I have had to glean what I know from posts in C on this forum. As I don't know what I don't know there may be other registers I have to set. If you can run your eye over this list and maybe tell me what I am missing it will enable me to move forward I am not using interrupts at this stage, just polling. ;reset_and_clock_control ; clock_control_register ; internal high-speed clock enable HSION on. ; clock_configuration_register ; select HSI as system clock ; apb2_periph_clock_enable_register ; USART1EN - usart1 clock enable ; IO port B clock enable (IOPBEN) ; IO port A clock enable (IOPAEN) ; alternate function IO clock enable (AFIOEN) ; apb1_periph_clock_enable_register ; USART3EN - usart3 clock enable ; USART2EN - usart2 clock enable ;gpio_port_b ; port_configuration_register_high ; configures pins 8 to 15 ; pin 11 configuration - 01 (INPUT MODE: = floating input USART3) ;gpio_port_a ; ort_configuration_register_high ; configures pins 8 to 15 ; pin 09 configuration - 10 (OUTPUT MODE: = alternate function output push-pull, MODE 11 = 50 mHz USART1) ;gpio_port_a ; port_configuration_register_low ; configures pins 0 t0 7 ; pin 03 configuration - 01 (INPUT MODE: = floating input USART2) ;usart1 ; usart_cr1 ; UE - USART enable - on ; TE - transmitter enable - on ;usart2 ; usart_cr1 ; UE - USART enable - on ;usart3 ; usart_cr1 ; UE - USART enable - on ;usart1 ; usart_cr2 ; control register 2 ; STOP = 0 (1 stop bit) ;usart2 ; usart_cr2 ; control register 2 ; STOP = 0 (1 stop bit) ;usart3 ; uart_cr2 ; control register 2 ; STOP = 0 (1 stop bit) ;usart1 ; usart_brr ; 0x1d4c (9600) ; usart_dr ; 0 ; usart_guardtime_prescaler_register ; 0 ;usart2 ; usart_brr ; 0x0ea6 (9600) ; usart_dr ; 0 ; usart_guardtime_prescaler_register ; 0 ;usart3 ; usart_brr ; 0x1d4c (9600) ; usart_dr ; 0 ; usart_guardtime_prescaler_register ; 0 ;usart2 ; usart_cr1 ; control register 1 ; RE - receiver enable - on ;usart3 ; usart_cr1 ; control register 1 ; RE - receiver enable - on2011-05-17 05:02 AM
Ok, if your source clock is HSI, and your AHB, APB1, and APB2 prescalers are 1, then the source frequency to USART1,2,3 is 8 MHz, as is SYSCLK.
The baud rate computation would then be 8000000 / 9600 = 833.333 or 0x0341 or for 115200 baud 8000000 / 115200 = 69 or 0x0045 (see assembler above for how I had USART1 doing this directly out of reset) With an oscilloscope you could measure the bit time of a pattern like 0x55 if you wanted secondary confirmation that the baud rate was set as expected.2011-05-17 05:02 AM
http://www.iar.com/website1/1.0.1.0/658/1/?item=prod_prod-s1%2F255
http://www.iar.com/website1/50.0.1.0/255/IAR_STM32F103ZE_SK.pdf2011-05-17 05:02 AM
Hi Clive, thanks for your reply, but...
Am I wrong, or in your assembler code you refer to are the prescalers not set to zero? I did as you advised in an earlier post and set the prescalers in my code to zero. So I am a bit confused. However, having now set them to 1, and changed the baud rate calculation, for all three usarts the receive is working (using usart2) (yeehaaa) but send is not (using usart1). Is there anything different I have to do for send?2011-05-17 05:02 AM
The prescalers are clock divider chains designed to efficiently reduce the clock speed. To understand how they fit in you need to look at the clock distribution/gating diagram in the STM32 Reference Manual.
http://www.st.com/stonline/products/literature/rm/13902.pdf pg 84 At reset the STM32 starts up running from the 8 MHz HSI clock. And the bus prescalers are set to divide-by-1 as RCC_CFGR is zeroed. So you can assume SYSCLK, HCLK, PCLK1 and PCLK2 are 8 MHz at reset time. Unless you reconfigure them they will stay this way. The programmable divider circuit in the USART derives from PCLK1 or PCLK2, and gets you to the desired baud rate. To know what divider value to use depends on the speed of those clocks, and if you subsequently change to using the PLL and adjust the system and bus clocks you will need to change the baud rate divider to match the new configuration. There is another prescaler within the USART, it resets to zero.