Embedded Systems Programming Serial port programming 2 Example
Embedded Systems Programming Serial port programming 2
Example assembler program • Simple program with putchar and getchar routines – Initialises UART port 3 – Oversimplified test on transmit – but works – Use of word – 32 bit writes to ARM peripheral bus – Requires linkage with boot. s file
@ -----------------------------------@ Constant values used in this program. set SP 1, 0 x 80030000 @ Base of the Microcontroller I/O space . set UTCR 0, UTCR 1, UTCR 2, UTCR 3, UTDR, 0 x 00 0 x 04 0 x 08 0 x 0 C 0 x 14 @ Offset to the Serial Status port @ Offset to the Serial Data Register . set UTSR 0, UTSR 1, 0 x 1 c 0 x 20 @ Offset to SP status reg 0 @ Offset to the Serial Status port . set UTSR 1_TNF, 0 b 00000100 UTSR 1_RNE, 0 b 00000010 UTSR 1_TBY, 0 b 00000001 @ Mask to check Tx FIFO Not Full @ Mask to check Rx FIFO Not Empty @ Mask to check Tx Busy . set Wait. Delay, 0 x 100000 @ abitrary delay count @ -----------------------------------@ Assembly-language preamble. text. global _start main b main _start: @ Executable code follows @ "_start" is required by the linker @ "main" is our main program
main: 1: 2: ldr ands bne mov str mov str ldr subs bne mov bl mov bl bl b r 1, =SP 1 r 3, [r 1, #UTSR 1] r 0, r 3, #1 1 b r 0, #0 r 0, [r 1, #UTCR 3] r 0, #0 x. FF r 0, [r 1, #UTSR 0] r 0, #0 x 8 r 0, [r 1, #UTCR 0] r 0, #0 x 0 r 0, [r 1, #UTCR 1] r 0, #0 x 1 r 0, [r 1, #UTCR 2] r 0, #0 x 3 r 0, [r 1, #UTCR 3] r 0, =Wait. Delay r 0, #1 2 b r 0, #'n' r 0, #'h' wb r 0, #'e' wb r 0, #'l' wb r 0, #'o' wb rb wb wb halt @ Use R 1 as a base register for uart @ read out pending transmissions @ disable rx/tx @ clear SR 9 to reset @ clear bottom 3 bit 1 st 2 r/o? @ 8 bits no parity, 1 sstop @ set top bit of BRD to 0 @ set baud to 115200 @ write to bottom bits of BRD @ set RXE & TXE no ints @ delay loop
@ Send the character to the internal serial port – character in register r 0 @ no return value wb: ldr tst beq r 2, [r 1, #UTSR 1] r 2, #UTSR 1_TNF wb @ Check the Serial Status port @ Can a character be sent out? @ No: wait until port is ready str mov r 0, [r 1, #UTDR] pc, lr @ Send the actual character out @ go back @read a character from the port - return it in r 0 @ returns character in r 0 rb: ldr tst beq ldr mov r 2, [r 1, #UTSR 1] r 2, #UTSR 1_RNE rb r 0, [r 1, #UTDR] pc, lr @ Check the Serial Status port @ Can a character be sent out? @ no check again @ yes read the char @ go back @ halt function – to end program @ doesn't return! halt: b halt @ -----------------------------------. end @ Do this forever (or until stopped)
Data transfer instructions 3 types of data transfer instructions: – single register loads and stores • byte or word (or possibly half-word) transfers – multiple register loads and stores • less flexible, multiple words, higher transfer rate – single register-memory swap • mainly for system use
Single register load / store • 32 bit – LDR r 0, [r 1] ; r 0 : = mem [r 1] – STR r 0, [r 1] ; mem [r 1] : = r 0 • 8 bit – LDRB r 0, [r 1] ; r 0 : = mem [r 1] [7: 0] – STRB r 0, [r 1] ; mem [r 1] [7: 0] : = r 0
Address Specification • Register – indirect with displacement – LDR r 0, [r 1, #4] ; r 0 : = mem[r 1+4] – The offset must be within +/- 4 k. Bytes • Special case : register indirect – LDR r 0, [r 1] ; r 0 : = mem[r 1] • Required: a register initialized with an address close to the target – Immediate values are restricted to (0… 255)*22 n – Assembler: pseudo instruction ADR is replaced automatically by appropriate processor instructions • ADR r 1, TABLE 1 ; r 1 points to TABLE 1 • . . . • TABLE 1. . . ; LABEL
Updating the address register • Auto - indexing – LDR r 0, [r 1, #4] ! ; r 0 : = mem[r 1+4] • ; r 1 : = r 1 + 4 – Write effective address back to base register • Post - indexing – LDR r 0, [r 1], #4 ; r 0 : = mem[r 1] • ; r 1 : = r 1 + 4
Example C program • Use of macros – speed up execution • Use of base addresses and offsets – Only need to change one base address • Use of delay – Should use clock/timer
Calculating baud rates So to get the BRD for 115200 we need to work out BRD = ( ( 3. 6864 * 1000000) / (16 * 115200) ) -1 BRD = (3686400/1843200) -1 BRD = 2;
FIFO TX Character delays Writing A character A A A A A SA 1110 side External Side
Waiting for transmissions • Requires 2 level poll of TBY bit in Status Register 1 • This requires a wait on a transition from 0 to 1 then a wait on a transition from 1 to 0. • This is only required on programmed (polled) IO, not necessary with interrupts or DMA.
/*--------------------------includes--------*/ #include "include/bios/stdio. h" /*--------------------------defines--------*/ /******************* * * Basic type definitions. * ******************/ typedef char S 08; typedef unsigned char U 08; typedef short S 16; typedef unsigned short U 16; typedef int S 32; typedef unsigned int U 32; typedef long S 64; typedef unsigned long U 64; typedef float F 32; typedef U 32 Terr; typedef U 08 BOOL; #define NULL ((void *) 0)
/* UART defines */ #define SA 1100_UART 1_BASE 0 x 80010000 #define SA 1100_UART 3_BASE 0 x 80030000 #define SA 1100_UTCR 0 0 x 00 #define SA 1100_UTCR 1 0 x 04 #define SA 1100_UTCR 2 0 x 08 #define SA 1100_UTCR 3 0 x 0 C #define SA 1100_UTCR 4 0 x 10 #define SA 1100_UTDR 0 x 14 #define SA 1100_UTSR 0 0 x 1 C #define SA 1100_UTSR 1 0 x 20 /* ** UART status definitions */ #define SA 1100_UTSR 1_TBY 0 x 1 /* transmitter busy flag */ #define SA 1100_UTSR 1_RNE 0 x 2 /* receiver not empty (LSR_DR) */ #define SA 1100_UTSR 1_TNF 0 x 4 /* transmit fifo non full */ #define SA 1100_UTSR 1_PRE 0 x 8 /* parity read error (LSR_PE) */ #define SA 1100_UTSR 1_FRE 0 x 10 /* framing error (LSR_FE) */ #define SA 1100_UTSR 1_ROR 0 x 20 / * receive fifo overrun (LSR_OE) */ /* ** UART Macros */ #define UART_PUT_CHAR(p, c) ((*(volatile U 32 *)(p + SA 1100_UTDR)) = c) #define UART_GET_STATUS(p) (*(volatile U 32 *)(p + SA 1100_UTSR 1)) #define UART_GET_CHAR(p) (*(volatile U 32 *)(p + SA 1100_UTDR)) #define UART_RX_READY(s) ((s & UTSR 1_RNE) == 1) #define UART_TX_READY(s) ((s & 4) != 0) #define UART_TBY_READY(s) ((s & 1) != 0) #define Uart. Base SA 1100_UART 3_BASE
void Serial. Write. Byte(U 32, const U 08); U 32 Serial. Read. Byte(U 32); void delay(void); /********************************** * * Test - C - entry point. * **********************************/ int main(int argc, char** argv) { volatile U 32* p. U 32 CR 0 = (U 32 *)((U 08 *)(Uart. Base) + SA 1100_UTCR 0); volatile U 32* p. U 32 CR 1 = (U 32 *)((U 08 *)(Uart. Base) + SA 1100_UTCR 1); volatile U 32* p. U 32 CR 2 = (U 32 *)((U 08 *)(Uart. Base) + SA 1100_UTCR 2); volatile U 32* p. U 32 CR 3 = (U 32 *)((U 08 *)(Uart. Base) + SA 1100_UTCR 3); volatile U 32* p. U 32 SR 0 = (U 32 *)((U 08 *)(Uart. Base) + SA 1100_UTSR 0); volatile U 32* p. U 32 SR 1 = (U 32 *)((U 08 *)(Uart. Base) + SA 1100_UTSR 1); int i; U 32 ch;
/* Wait for any pending transmissions to complete */ while(*p. U 32 SR 1 & 0 x 01) /* do nothing */; /* Disable rx, tx and interrupts - to reset line speed */ *p. U 32 CR 3 = 0 x 0; /* Clear status by writing 1's overkill doesn't hurt*/ *p. U 32 SR 0 = 0 x. FF; /* 8 bit, no parity, 1 stop */ *p. U 32 CR 0 = 0 x 08; /* Set default baud rate, high byte & low byte */ *p. U 32 CR 1 = 0 x 00; /* upper baud rate select */ *p. U 32 CR 2 = 1; /* 1 == 115200 baud. 23 == 9600 baud */ /* Enable rx and tx, NOT interrupts */ *p. U 32 CR 3 = 0 x 03 ; delay(); /* wait a while */ Serial. Write. Byte(SA 1100_UART 3_BASE, 'h'); Serial. Write. Byte(SA 1100_UART 3_BASE, 'e'); Serial. Write. Byte(SA 1100_UART 3_BASE, 'l'); Serial. Write. Byte(SA 1100_UART 3_BASE, 'o'); Serial. Write. Byte(SA 1100_UART 3_BASE, 'n');
for ( i = 0; i != 9; i++ ) { ch = Serial. Read. Byte(SA 1100_UART 3_BASE); Serial. Write. Byte(SA 1100_UART 3_BASE, (U 08)ch); Serial. Write. Byte(SA 1100_UART 1_BASE, (U 08)ch); } Serial. Write. Byte(SA 1100_UART 1_BASE, 'B'); Serial. Write. Byte(SA 1100_UART 1_BASE, 'Y'); Serial. Write. Byte(SA 1100_UART 1_BASE, 'E'); Serial. Write. Byte(SA 1100_UART 1_BASE, 'n'); Halt(); } /* Boot. Loader - halt */ /* read a byte from the serial port */ U 32 Serial. Read. Byte(U 32 UB) { U 08 Char; volatile S 32 U 32 Status; do { U 32 Status = UART_GET_STATUS(UB) ; } while (!(U 32 Status & SA 1100_UTSR 1_RNE)); /* wait until ready */ U 08 Char = UART_GET_CHAR(UB); return (U 32)U 08 Char; } /* Serial. Read. Byte */ /* short delay */ void delay(void) { volatile int i; for (i=0; i != 100000; i++) ; }
void Serial. Write. Byte(U 32 UB, const U 08 Char) { volatile S 32 Status ; /* wait until we can transmit */ do { S 32 Status = UART_GET_STATUS(UB) ; } while (!UART_TX_READY(S 32 Status)) ; UART_PUT_CHAR(UB, U 08 Char) ; /* wait for the data to flush through the FIFO wait for TBY to go 0 - 1 then 1 - 0 */ do /* 0 to 1 */ { S 32 Status = UART_GET_STATUS(UB) ; } while (!UART_TBY_READY(S 32 Status)) ; do /* 1 to 0 */ { S 32 Status = UART_GET_STATUS(UB) ; } while (UART_TBY_READY(S 32 Status)) ;
- Slides: 19