serSTM32F0xxp.fth (11064B)
1 \ serSTM32F0xxp.fth - STM32F0xx polled serial driver 2 3 (( 4 Copyright (c) 2009, 2011 5 MicroProcessor Engineering 6 133 Hill Lane 7 Southampton SO15 5AF 8 England 9 10 tel: +44 (0)23 8063 1441 11 fax: +44 (0)23 8033 9691 12 email: mpe@mpeforth.com 13 tech-support@mpeforth.com 14 web: http://www.mpeforth.com 15 Skype: mpe_sfp 16 17 From North America, our telephone and fax numbers are: 18 011 44 23 8063 1441 19 011 44 23 8033 9691 20 901 313 4312 (North American access number to UK office) 21 22 23 To do 24 ===== 25 26 Change history 27 ============== 28 20120125 MPE002 Changed to use external pin selection words. 29 20111130 MPE001 Converted from STM32F103 30 )) 31 32 only forth definitions 33 decimal 34 35 \ =========== 36 \ *> drivers 37 \ =========== 38 \ *S STM32F0 polled serial driver 39 \ ******************************* 40 \ *P The serial driver *\i{Cortex/Drivers/serSTM32F0xxp.fth} 41 \ ** provides polled serial drivers for the on-chip USARTs. 42 \ ** The supplied driver implements USART1 on PA9/10 and 43 \ ** USART3 on PD8 (Tx) and PD9 (Rx). 44 45 \ *P When you copy this file for your own hardware do not forget 46 \ ** update the GPIO pin assignments and alternate function 47 \ ** selections. 48 49 50 \ *********************** 51 \ *N Baud rate generation 52 \ *********************** 53 \ *P The baud rate routines use 16 times sampling and the fractional 54 \ ** baud rate generator. 55 56 \ *E pclkx 57 \ ** divisor = ------------- 58 \ ** 16 * baudrate 59 \ *P We then treat the divisor as an integer and four bit fraction, 60 \ ** effectively scaling it by 16 again. 61 \ *E pclkx 62 \ ** BRRval = -------- 63 \ ** baudrate 64 65 interpreter 66 : genBRRval \ baud clock -- divisor 67 \ *G Generate the required BRR value. 68 1 lshift \ for rounding 69 swap / \ brr = clock / baud 70 1+ 1 rshift \ rounding 71 ; 72 target 73 74 75 \ ************** 76 \ *N Shared code 77 \ ************** 78 79 : (serKey?) \ base -- flag 80 usISR + @ bit5 and ; 81 82 : (serkey) \ base -- char 83 begin 84 dup usISR + @ bit5 and 0= 85 while 86 pause 87 repeat 88 usRDR + @ $FF and 89 ; 90 91 : (seremit) \ char base -- 92 begin 93 dup usISR + @ bit7 and 0= 94 while 95 pause 96 repeat 97 usTDR + ! 98 ; 99 100 : (sertype) \ caddr len base -- 101 -rot bounds 102 ?do i c@ over (seremit) loop 103 drop 104 ; 105 106 : (sercr) \ base -- 107 #13 over (seremit) #10 swap (seremit) ; 108 109 : +FaultConsole \ -- 110 \ *G For use in fault exception handlers, the multi-tasker must 111 \ ** be turned off and *\fo{EMIT) and friends must run in polled 112 \ ** mode. 113 ; 114 115 : (init-ser) \ brrval ^usart -- 116 $0000 over usCR1 + ! \ disable UART, 8 bits, no parity 117 $0000 over usCR2 + ! \ 1 stop bit, UART mode 118 $0000 over usCR3 + ! \ no interrupts, no DMA, no LIN, no smartcard 119 tuck usBRR + ! \ set baud rate 120 $000C over usCR1 + ! \ 8 bit, no parity, TE, RE 121 $000D over usCR1 + ! \ 8 bit, no parity, TE, RE, UE 122 drop 123 ; 124 125 126 \ ********* 127 \ *N USART1 128 \ ********* 129 \ *P USART1 is on the APB bus, so the baud rate is calculated 130 \ ** using that bus clock. 131 132 useUSART1? [if] 133 _USART1 CONSTANT UART1 134 console1-speed APB-speed genBRRval equ /us1BRR \ -- u 135 \ *G Baud rate divisor for USART1. 136 137 (( 138 : selio-ser1 \ -- 139 \ *G Example to perform clock and pin selection for USART1 on PA9/10. 140 \ ** Provide your own version, e.g. in the control file. 141 \ Clocks and reset 142 _RCC 143 $0000 $0003 2 pick rccCFGR3 + setMask \ PCLK is UART clock 144 bit17 over rccAHBen + or! \ enable clock to GPIOA 145 bit17 over rccAHBrst + bic! \ take it out of reset 146 bit14 over rccAPB2en + or! \ enable clock to USART1 147 bit14 over rccAPB2rst + bic! \ take it out of reset 148 drop 149 \ Default on PA9/10 150 _GPIOA >r 151 $0028:0000 $003C:0000 r@ gpioMODER + setMask \ alternate function on 9/10 152 $0000:0110 $0000:0FF0 r> gpioAFRH + setMask \ AF1 for both 153 ; 154 )) 155 156 : init-ser1 \ -- 157 \ *G Initialise USART1 for polled operation. Pin selection is 158 \ ** performed by *\fo{selio-ser1}. 159 selio-ser1 160 /us1BRR _USART1 (init-ser) 161 ; 162 163 : serkey?1 \ -- flag 164 \ *G *\fo{KEY?} for USART1. 165 _USART1 (serkey?) ; 166 167 : serkey1 \ -- char 168 \ *G *\fo{KEY} for USART1. 169 _USART1 (serkey) ; 170 171 : seremit1 \ char -- 172 \ *G *\fo{EMIT} for USART1. 173 _USART1 (seremit) ; 174 175 : serType1 \ c-addr len -- 176 \ *G *\fo{TYPE} for USART1. 177 _USART1 (sertype) ; 178 179 : sercr1 \ -- 180 \ *G *\fo{CR} for USART1. 181 _USART1 (sercr) ; 182 183 create Console1 \ -- addr ; OUT managed by upper driver 184 \ *G Device structure for USART1 185 \ *[ 186 ' serkey1 , \ -- char ; receive char 187 ' serkey?1 , \ -- flag ; check receive char 188 ' seremit1 , \ -- char ; display char 189 ' sertype1 , \ caddr len -- ; display string 190 ' sercr1 , \ -- ; display new line 191 \ *] 192 193 console-port 1 = [if] 194 console1 constant console 195 \ *G Device structure for console on USART1. 196 [then] 197 198 [then] \ useUSART1? 199 200 201 useUSART2? [if] 202 _USART2 CONSTANT UART2 203 console2-speed APB-speed genBRRval equ /us2BRR \ -- u 204 \ *G Baud rate divisor for USART1. 205 206 : SER2CLOCKS ( --- ) 207 \ Clocks and reset 208 _RCC 209 $0000 $00030000 2 pick rccCFGR3 + setMask \ PCLK is UART clock 210 bit17 over rccAHBen + or! \ enable clock to GPIOA 211 bit17 over rccAHBrst + bic! \ take it out of reset 212 bit17 over rccAPB1en + or! \ enable clock to USART2 213 bit17 over rccAPB1rst + bic! \ take it out of reset 214 drop ; 215 216 217 PA 2 PIO: TX2 218 PA 3 PIO: RX2 219 220 221 : SER2FUNCTIONS ( --- PA2, PA3) 222 1 TX2 ISFUNCTION 223 1 RX2 ISFUNCTION 224 \ _GPIOA >r 225 \ $0000:00C0 $0000:00F0 r@ gpioMODER + setMask \ alternate function on 2/3 ***** 226 \ $0000:1100 $0000:FF00 r> gpioAFRL + setMask \ AF1 for both 227 ; 228 229 \ : SER2FUNCTIONS ( --- PA2, PA15) 230 \ _GPIOA >r 231 \ $8000:0020 $C000:0030 r@ gpioMODER + setMask \ alternate function on 2/15 ***** 232 \ $0000:0100 $0000:0F00 r@ gpioAFRL + setMask \ AF1 for both 233 \ $1000:0000 $F000:0000 r> gpioAFRH + setMask \ AF1 for both 234 \ ; 235 236 237 : selio-ser2 \ -- 238 \ *G Example to perform clock and pin selection for USART1 on PA9/10. 239 \ ** Provide your own version, e.g. in the control file. 240 SER2CLOCKS SER2FUNCTIONS ; 241 242 : init-ser2 \ -- 243 \ *G Initialise USART2 for polled operation. Pin selection is 244 \ ** performed by *\fo{selio-ser2}. 245 selio-ser2 246 /us2BRR _USART2 (init-ser) 247 ; 248 249 : serkey?2 \ -- flag 250 \ *G *\fo{KEY?} for USART2. 251 _USART2 (serkey?) ; 252 253 : serkey2 \ -- char 254 \ *G *\fo{KEY} for USART2. 255 _USART2 (serkey) ; 256 257 : seremit2 \ char -- 258 \ *G *\fo{EMIT} for USART2. 259 _USART2 (seremit) ; 260 261 : serType2 \ c-addr len -- 262 \ *G *\fo{TYPE} for USART2. 263 _USART2 (sertype) ; 264 265 : sercr2 \ -- 266 \ *G *\fo{CR} for USART2. 267 _USART2 (sercr) ; 268 269 create Console2 \ -- addr ; OUT managed by upper driver 270 \ *G Device structure for USART1 271 \ *[ 272 ' serkey2 , \ -- char ; receive char 273 ' serkey?2 , \ -- flag ; check receive char 274 ' seremit2 , \ -- char ; display char 275 ' sertype2 , \ caddr len -- ; display string 276 ' sercr2 , \ -- ; display new line 277 \ *] 278 279 console-port 2 = [if] 280 console2 constant console 281 \ *G Device structure for console on USART2. 282 [then] 283 284 [then] \ useUSART2? 285 286 287 \ ********* 288 \ *N USART3 289 \ ********* 290 \ *P USART3 is on the APB1 bus, so the baud rate is calculated 291 \ ** using that bus clock. Or not. Use APB instead. 292 293 \ This code is only compiled if the 294 \ ** equate *\fo{useUSART3} is non-zero}. 295 296 useUSART3? [if] 297 _USART3 CONSTANT UART3 298 console3-speed APB-speed genBRRval equ /us3BRR \ -- u 299 \ *G Baud rate divisor for USART3. 300 301 PC 4 PIO: TX3 302 PC 11 PIO: RX3 303 304 305 : selio-ser3 \ -- 306 \ *G Example to perform clock and pin selection for USART3 307 \ ** using GPIO pins PC4, PC11. 308 _RCC 309 $0000 $C0000 2 pick rccCFGR3 + setMask \ PCLK is UART clock 310 bit19 over rccAHBen + or! \ enable clock to GPIOA 311 bit19 over rccAHBrst + bic! \ take it out of reset 312 bit18 over rccAPB1en + or! \ enable clock to USART1 313 bit18 over rccAPB1rst + bic! \ take it out of reset 314 drop 315 316 \ alternate function on 4/11 317 1 TX3 ISFUNCTION 318 1 RX3 ISFUNCTION 319 ; 320 321 : init-ser3 \ -- 322 \ *G Initialise USART3 for polled operation on GPIO pins PD8/9. 323 selio-ser3 324 /us3BRR _USART3 (init-ser) 325 ; 326 327 : serkey?3 \ -- flag 328 \ *G *\fo{KEY?} for USART3. 329 _USART3 (serkey?) ; 330 331 : serkey3 \ -- char 332 \ *G *\fo{KEY} for USART3. 333 _USART3 (serkey) ; 334 335 : seremit3 \ char -- 336 \ *G *\fo{EMIT} for USART3. 337 _USART3 (seremit) ; 338 339 : serType3 \ c-addr len -- 340 \ *G *\fo{TYPE} for USART3. 341 _USART3 (sertype) ; 342 343 : sercr3 \ -- 344 \ *G *\fo{CR} for USART3. 345 _USART3 (sercr) ; 346 347 create Console3 \ -- addr ; OUT managed by upper driver 348 \ *G Device structure for USART3. 349 \ *[ 350 ' serkey3 , \ -- char ; receive char 351 ' serkey?3 , \ -- flag ; check receive char 352 ' seremit3 , \ -- char ; display char 353 ' sertype3 , \ caddr len -- ; display string 354 ' sercr3 , \ -- ; display new line 355 \ *] 356 357 console-port 3 = [if] 358 console3 constant console 359 \ *G Device structure if console is on USART3. 360 [then] 361 362 [then] \ useUSART3? 363 364 \ ********* 365 \ *N USART4 366 \ ********* 367 \ *P USART4 is on the APB1 bus, so the baud rate is calculated 368 \ ** using that bus clock. Or not. Use APB instead. 369 370 \ This code is only compiled if the 371 \ ** equate *\fo{useUSART3} is non-zero}. 372 373 useUSART4? [if] 374 _USART4 CONSTANT UART4 375 console4-speed APB-speed genBRRval equ /us4BRR \ -- u 376 \ *G Baud rate divisor for USART4. 377 378 PA 1 PIO: RX4 379 PC 10 PIO: TX4 380 381 : selio-ser4 \ -- 382 \ *G Example to perform clock and pin selection for USART4 383 \ ** using GPIO pins PA1, PC10. 384 _RCC 385 bit19 over rccAHBEN + or! \ enable clock to GPIOC 386 bit19 over rccAHBRST + bic! \ take it out of reset 387 bit17 over rccAHBen + or! \ enable clock to GPIOA 388 bit17 over rccAHBrst + bic! \ take it out of reset 389 bit19 over rccAPB1EN + or! \ enable clock to USART4 390 bit19 over rccAPB1RST + bic! \ take it out of reset 391 drop 392 393 4 RX4 ISFUNCTION 394 0 TX4 ISFUNCTION 395 ; 396 397 : init-ser4 \ -- 398 \ *G Initialise USART4 for polled operation on GPIO pins PA1,PC10. 399 selio-ser4 400 /us4BRR _USART4 (init-ser) 401 ; 402 403 : serkey?4 \ -- flag 404 \ *G *\fo{KEY?} for USART4. 405 _USART4 (serkey?) ; 406 407 : serkey4 \ -- char 408 \ *G *\fo{KEY} for USART4. 409 _USART4 (serkey) ; 410 411 : seremit4 \ char -- 412 \ *G *\fo{EMIT} for USART4. 413 _USART4 (seremit) ; 414 415 : serType4 \ c-addr len -- 416 \ *G *\fo{TYPE} for USART4. 417 _USART4 (sertype) ; 418 419 : sercr4 \ -- 420 \ *G *\fo{CR} for USART4. 421 _USART4 (sercr) ; 422 423 create Console4 \ -- addr ; OUT managed by upper driver 424 \ *G Device structure for USART4. 425 \ *[ 426 ' serkey4 , \ -- char ; receive char 427 ' serkey?4 , \ -- flag ; check receive char 428 ' seremit4 , \ -- char ; display char 429 ' sertype4 , \ caddr len -- ; display string 430 ' sercr4 , \ -- ; display new line 431 \ *] 432 433 console-port 4 = [if] 434 console4 constant console 435 \ *G Device structure if console is on USART4. 436 [then] 437 438 [then] \ useUSART4? 439 440 441 \ ***************** 442 \ *N Initialisation 443 \ ***************** 444 445 : init-ser \ -- 446 \ *G Initialise primary serial ports. 447 [ useUSART1? ] [if] init-ser1 [then] 448 [ useUSART2? ] [if] init-ser2 [then] 449 [ useUSART3? ] [if] init-ser3 [then] 450 [ useUSART4? ] [if] init-ser4 [then] 451 ; 452 453 454 : SETBAUD ( n uart --- ) 455 SWAP APB-speed 456 \ *G Generate the required BRR value. 457 1 lshift \ for rounding 458 swap / \ brr = clock / baud 459 1+ 1 rshift \ rounding 460 SWAP usBRR + ! ; 461 462 : IS-CONSOLE ( n --- ) 463 DUP OPVEC ! IPVEC ! ; 464 465 466 \ ====== 467 \ *> ### 468 \ ====== 469 470 decimal