hwinit: @ initialize the Memory Accelerator Module (MAM) for 60MHZ operation ------------------------------------- @ according to the Errata published online, disabling MAM can cause @ problems with SRAM reading while running a program from Flash @ recommended settings are: MAMCR = 0x2 and MAMTIM = 0x1 (<20MHZ) @ 0x2 (<40MHZ) 0x3 (>40MHZ) or MAMCR = 0x0 and MAMTIM = 0x1. @ To set MAMTIM first set MAMCR to 0 then back to non-zero value @ pre-set common values set fre, #0 set sv1, #1 set sv2, #2 set sv3, #3 set sv4, #4 set sv5, #5 @ set MAMTIM ldr rva, =sys_ctrl str fre, [rva] @ MAMCR <- 0 .ifndef LPC2478_STK str sv3, [rva, #0x04] @ MAMTIM <- 3 for PLL at 60 MHZ str sv2, [rva] @ MAMCR <- 2 to enable MAMTIM str sv1, [rva, #0x0100] @ VPBDIV <- peripheral clock divisor .else str sv4, [rva, #0x04] @ MAMTIM <- 4 for PLL at 72 MHZ str sv2, [rva] @ MAMCR <- 2 to enable MAMTIM add rvb, rva, #0x0100 @ enable the main oscillator set rvc, #0x20 str rvc, [rvb, #0xa0] moswt0: @ wait for main oscillator to be ready ldr rvc, [rvb, #0xa0] tst rvc, #0x40 beq moswt0 @ select clocks and dividers set sv4, #0xaa set sv5, #0x55 str sv1, [rva, #0x80] @ PLLCON <- 1 == enable but disconnect PLL str sv4, [rva, #0x8c] @ PLLFEED <- 0xaa == feed PLL str sv5, [rva, #0x8c] @ PLLFEED <- 0x55 == feed PLL str fre, [rva, #0x80] @ PLLCON <- 0 == disable the disconnected PLL str sv4, [rva, #0x8c] @ PLLFEED <- 0xaa == feed PLL str sv5, [rva, #0x8c] @ PLLFEED <- 0x55 == feed PLL str sv1, [rvb, #0x0c] @ CLKSRCSEL <- 1, select Main Osc str sv3, [rvb, #0x04] @ CCLKCFG <- 3, CPU = 288 MHz/4 = 72 MHz set rvc, #0x05 str rvc, [rvb, #0x08] @ USBCLKCFG <- 5, USB = 288 MHz/6 = 48 MHz ldr rvc, =0x55555555 str rvc, [rvb, #0xa8] @ PCLKSEL1 <- peripherals operate at 72 MHz str rvc, [rvb, #0xac] @ PCLKSEL2 <- peripherals operate at 72 MHz .endif @ configure the PLL ldr rvb, =PLL_PM_parms str rvb, [rva, #0x84] @ PLLCFG <- PLL_PM_parms str sv1, [rva, #0x80] @ PLLCON <- 1 == enable PLL set sv4, #0xaa set sv5, #0x55 str sv4, [rva, #0x8c] @ PLLFEED <- 0xaa == feed PLL str sv5, [rva, #0x8c] @ PLLFEED <- 0x55 == feed PLL pllwt0: ldr rvb, [rva, #0x88] @ rvb <- PLL status tst rvb, #PLOCK_bit @ is PLL locked? beq pllwt0 @ if not, jump to keep waiting str sv3, [rva, #0x80] @ PLLCON <- 3 == connect PLL str sv4, [rva, #0x8c] @ PLLFEED <- 0xaa == feed PLL str sv5, [rva, #0x8c] @ PLLFEED <- 0x55 == feed PLL @ re-set modified common values set sv4, #4 set sv5, #5 .ifdef LPC_H2214 @ initialization of external memory parameters (LPC2214) ldr rva, =0xE002C014 @ rva <- PINSEL2 ldr rvb, =0x0F000924 str rvb, [rva] @ PINSEL2 <- @ F = A23:1 are address lines (not A0) @ 9 = P3.27:26->WE,CS1 @ 2 = P2.31:0->D31:0, P3.31:28->BLS0:3, P1.1:0->OE,CS0 @ 4 = P1.31:26->debug, P1.25:16->gpio (not trace) ldr rva, =0xFFE00000 ldr rvb, =0x1000348F str rvb, [rva] @ BCG0 <- @ off-chip bank 0,FLASH,MX26LV800BTC,R55ns/W55ns,0x80000000->0x80FFFFFF @ 01/b29:28->MW=16bit,110/b15:11->WST2=6(write=9cycles),1/b10->RBLE=1, @ 100/b9:5 ->WST1=4 (read=7cycles), 1111/b3:0 ->IDCY=F (R/W bus wait) @ note: RW55ns chip should have WST1=3, WST2=3 ldr rvb, =0x2000040F str rvb, [rva, #0x04] @ BCFG1 <- @ off-chip bank 1, SRAM, 71V416, R12ns/W12ns, 0x81000000 -> 0x81FFFFFF @ 10/b29:28->MW=32bit,000/b15:11->WST2=0 (write=3cycles),1/b10->RBLE=1, @ 000/b9:5 ->WST1=0 (read=3 cycles), 1111/b3:0->IDCY=F (R/W bus wait) .endif .ifdef LPC2478_STK @ configuration of external memory control pins ldr rva, =PINSEL0 ldr rvc, =0x55555555 ldr rvb, =0x00fcfcc0 bic rvb, rvc, rvb str rvb, [rva, #0x14] @ pinsel5 <- memory bus alternate function str rvc, [rva, #0x18] @ pinsel6 <- memory bus alternate function str rvc, [rva, #0x1c] @ pinsel7 <- memory bus alternate function bic rvb, rvc, #0xC0000000 str rvb, [rva, #0x20] @ pinsel8 <- memory bus alternate function set rvb, #0x040000 str rvb, [rva, #0x24] @ pinsel9 <- memory bus alternate function lsl rvc, rvc, #0x01 ldr rvb, =0x00fcfcc0 bic rvb, rvc, rvb str rvb, [rva, #0x54] @ pinmode5 <- disable pull-up/down resistor str rvc, [rva, #0x58] @ pinmode6 <- disable pull-up/down resistor str rvc, [rva, #0x5c] @ pinmode7 <- disable pull-up/down resistor bic rvb, rvc, #0xC0000000 str rvb, [rva, #0x60] @ pinmode8 <- disable pull-up/down resistor set rvb, #0x080000 str rvb, [rva, #0x64] @ pinmode9 <- disable pull-up/down resistor @ initialization of external memory (LPC2478) ldr rva, =0xFFE08000 @ rva <- EMC Control str sv1, [rva] @ EMCCONTROL <- 1 -- Enable EMC str sv1, [rva, #0x28] @ EMCDYNAMICREADCONFIG <- 1, Cmd delayed, using EMCCLKDELAY str sv1, [rva, #0x30] @ EMCDYNAMICRP <- 20 / 16.6 + 1 = 2 str sv3, [rva, #0x34] @ EMCDYNAMICRAS <- 45 / 16.6 + 1 = 3 str sv4, [rva, #0x38] @ EMCDYNAMICSREX <- 67 / 16.6 + 1 = 5 str sv1, [rva, #0x3C] @ EMCDYNAMICAPR <- SDRAM_TAPR = 1 str sv4, [rva, #0x40] @ EMCDYNAMICDAL <- 2 + 20/16.6 + 1 = 4 str sv3, [rva, #0x44] @ EMCDYNAMICWR <- SDRAM_TWR str sv4, [rva, #0x48] @ EMCDYNAMICRC <- 65 / 16.6 + 1 = 4 str sv4, [rva, #0x4C] @ EMCDYNAMICRFC <- 66 / 16.6 + 1 = 4 str sv4, [rva, #0x50] @ EMCDYNAMICXSR <- 67 / 16.6 + 1 = 5 str sv1, [rva, #0x54] @ EMCDYNAMICRRD <- 15 / 16.6 + 1 str sv3, [rva, #0x58] @ EMCDYNAMICMRD <- SDRAM_TMRD ldr rvb, =0x4680 str rvb, [rva, #0x100] @ EMCDYNAMICCONFIG <- 0x0004680, 13 row, 9 col, 32-bit, SDRAM ldr rvb, [rva, #0x0104] orr rvb, rvb, #0x0300 orr rvb, rvb, #0x0003 str rvb, [rva, #0x0104] @ EMCDYNAMICRASCAS <- 3, 3, bit 9:8, 1:0<-10 -- 3 AHB HCLK cycles lat @ Initialize SDRAM chip (JEDEC) ldr rvb, =0x0183 str rvb, [rva, #0x20] @ EMCDYNAMICCONTROL <- 0x0183, 8:7<-11=NOP, clk-clkout run, rfrsh nrml @ wait countdown set rvc, #0x080000 subs rvc, rvc, #1 subne pc, pc, #12 @ keep going ldr rvb, [rva, #0x20] bic rvb, rvb, #0x0080 str rvb, [rva, #0x20] @ EMCDYNAMICCONTROL, SDRAMINI <- 2, bits 8:7<-10, PALL (prchrge all) str sv1, [rva, #0x24] @ EMCDYNAMICREFRESH <- 1 (refresh every 16 clocks during precharge) @ wait countdown set rvc, #0x080000 subs rvc, rvc, #1 subne pc, pc, #12 @ keep going ldr rvb, =35 str rvb, [rva, #0x24] @ EMCDYNAMICREFRESH <- (15625 / 2 / 13.89 + 1) >> 4 ldr rvb, [rva, #0x20] eor rvb, rvb, #0x0180 str rvb, [rva, #0x20] @ EMCDYNAMICCONTROL, SDRAMINI <- 1, bits 8:7<-01, MODE command ldr rvb, =0xA0064000 @ rvb <- RAM Code for sequential burst of 4 words, CAS-3 ldr rvb, [rvb] @ set mode into RAM mode register ldr rvb, =0x0000 str rvb, [rva, #0x20] @ EMCDYNAMICCONTROL <- 0x0000, NORMAL mode command ldr rvb, [rva, #0x100] orr rvb, rvb, #0x080000 str rvb, [rva, #0x100] @ EMCDYNAMICCONFIG, BUF_EN <- 1, bit 19, enable r/w buffers @ wait countdown set rvc, #0x080000 subs rvc, rvc, #1 subne pc, pc, #12 @ keep going .endif @ initialization of mcu-id for variables (normally I2c address if slave enabled) ldr rva, =i2c0_base @ rva <- I2C0 base address set rvb, #mcu_id str rvb, [rva, #i2c_address] @ I2C0ADR <- set mcu address @ initialization of gpio pins ldr rva, =LEDPINSEL str fre, [rva] @ LEDs are on P1.21-23 (213X) or P0.23-25 (2106) GPIO function ldr rva, =LEDIO ldr rvb, =ALLLED str rvb, [rva, #io_dir] @ make all LED pins an output @ initialization of interrupts ldr rva, =int_base @ rva <- Vectored Interrupt Controller (VIC) base address str fre, [rva, #0x0c] @ VICIntSelect <- all interrupts are IRQ ldr rvb, =genisr .ifndef LPC2478_STK str rvb, [rva, #0x34] @ VICDefVectAddr <- Default IRQ handler .else add rvc, rva, #0x100 str rvb, [rvc, #0x10] @ VICVectAddr4 <- TIMER0 IRQ handler = genisr str rvb, [rvc, #0x14] @ VICVectAddr5 <- TIMER1 IRQ handler = genisr str rvb, [rvc, #0x18] @ VICVectAddr6 <- UART0 IRQ handler = genisr str rvb, [rvc, #0x1c] @ VICVectAddr7 <- UART1 IRQ handler = genisr str rvb, [rvc, #0x24] @ VICVectAddr9 <- I2C0 IRQ handler = genisr str rvb, [rvc, #0x4c] @ VICVectAddr19 <- I2C1 IRQ handler = genisr .endif @ initialization of UART0 for 9600 8N1 operation ldr rva, =PINSEL0 @ rva <- PINSEL0 .ifndef LPC2478_STK ldr rvb, [rva] bic rvb, rvb, #0x0F orr rvb, rvb, #0x05 str rvb, [rva] @ PINSEL0 <- Enable UART0 pins (P0.0 and P0.1) .else ldr rvb, [rva, #0x40] bic rvb, rvb, #0xF0 orr rvb, rvb, #0xA0 str rvb, [rva, #0x40] @ PINMODE0 <- disable pull-up/down resistors on uart0 pins ldr rvb, [rva] bic rvb, rvb, #0xF0 orr rvb, rvb, #0x50 str rvb, [rva] @ PINSEL0 <- Enable UART0 pins (P0.2 and P0.3) .endif ldr rva, =uart0_base str sv1, [rva, #0x08] @ U0FCR <- Enable UART0, Rx trigger-level = 1 char set rvb, #0x80 str rvb, [rva, #0x0c] @ U0LCR <- Enable UART0 divisor latch ldr rvb, =UART0_DIV_L str rvb, [rva] @ U0DLL <- UART0 lower byte of divisor for 9600 baud ldr rvb, =UART0_DIV_H str rvb, [rva, #0x04] @ U0DLM <- UART0 upper byte of divisor for 9600 baud str sv3, [rva, #0x0c] @ U0LCR <- Disable UART0 divisor latch and set 8N1 transmission str sv1, [rva, #0x04] @ U0IER <- Enable UART0 RDA interrupt @ initialization of interrupts ldr rva, =int_base @ rva <- Vectored Interrupt Controller (VIC) base address set rvb, #uart0_int str rvb, [rva, #0x10] @ VicIntEnable <- Enable UART0 Interrupt (IRQ#6 -> bit 6) @ USB ldr rva, =USB_CONF str fre, [rva] @ USB_CONF <- USB device is not yet configured .ifdef SFE_Logomatic2 @ Turn on USB PCLK in PCONP register (to power up USB RAM) ldr rva, =0xE01FC0C4 @ rva <- PCONP = power ctrl for peripherals ldr rvb, [rva] orr rvb, rvb, #0x80000000 str rvb, [rva] @ PCONP <- power the USB RAM and clock, etc... .endif @ SFE_Logomatic2 .ifdef LPC_H2148 @ Turn on USB PCLK in PCONP register (to power up USB RAM) ldr rva, =0xE01FC0C4 @ rva <- PCONP = power ctrl for peripherals ldr rvb, [rva] orr rvb, rvb, #0x80000000 str rvb, [rva] @ PCONP <- power the USB RAM and clock, etc... .endif @ LPC_H2148 .ifdef LCDDemo_2158 @ Turn on USB PCLK in PCONP register (to power up USB RAM) ldr rva, =0xE01FC0C4 @ rva <- PCONP = power ctrl for peripherals ldr rvb, [rva] orr rvb, rvb, #0x80000000 str rvb, [rva] @ PCONP <- power the USB RAM and clock, etc... .endif @ LCDDemo_2158 .ifdef LPC2478_STK @ Turn on USB PCLK in PCONP register (to power up USB subsystem) ldr rva, =0xE01FC0C4 @ rva <- PCONP = power ctrl for peripherals ldr rvb, [rva] orr rvb, rvb, #0x80000000 str rvb, [rva] @ PCONP <- power the USB RAM and clock, etc... .endif @ LPC2478_STK .ifdef native_usb @ 10. initialization of USB device controller -- for LPC2148, LPC2158 -- **** MUST BE LAST **** --------- @ 1.5 now that USB RAM is ON, initialize it ldr rva, =USB_LineCoding ldr rvb, =115200 str rvb, [rva] @ 115200 bauds set rvb, #0x00080000 str rvb, [rva, #0x04] @ 8 data bits, no parity, 1 stop bit ldr rva, =USB_CHUNK str fre, [rva] @ zero bytes remaining to send at startup ldr rva, =USB_ZERO str fre, [rva] @ alternate interface and device/interface status = 0 ldr rva, =USB_CONF str fre, [rva] @ USB device is not yet configured @ see if USB is plugged in (if not, exit USB setup) .ifndef LPC2478_STK ldr rva, =PINSEL1 ldr rvb, [rva] bic rvb, rvb, #0x00C000 str rvb, [rva] @ set P0.23 (VBUS) as GPIO ldr rva, =io0_base ldr rvb, [rva] tst rvb, #0x00800000 @ branch to resetC if tst IO0PIN, 0x800000 gives eq seteq pc, lnk @ i.e. exit hardare initialization if VBUS is not on .else ldr rva, =PINSEL0 ldr rvb, [rva, #0x40] bic rvb, rvb, #0x30000000 orr rvb, rvb, #0x20000000 str rvb, [rva, #0x40] @ PINMODE0 <- disable pull-up/down resistor on P0.14/VBUS ldr rvb, [rva] bic rvb, rvb, #0x30000000 str rvb, [rva] @ set P0.14 (VBUS) as GPIO ldr rva, =io0_base ldr rvb, [rva] tst rvb, #0x00004000 @ branch to resetC if P0.14 (VBUS) is not high seteq pc, lnk @ i.e. exit hardare initialization if VBUS is not on .endif @ disable UART0 interrupts if USB is plugged in (they can cause noise on the shared READBUFFER) ldr rva, =int_base set rvb, #uart0_int str rvb, [rva, #0x14] @ VicIntEnClear <- Disable UART0 Interrupt (IRQ#6 -> bit 6) ldr rva, =uart0_base str fre, [rva, #0x04] @ U0IER <- Disable UART0 RDA interrupt .ifndef LPC2478_STK @ 3. Turn on PLL1 at 48 MHz for USB clock (see 4-8) ldr rva, =0xE01FC000 ldr rvb, =PLL1_PM_parms str rvb, [rva, #0xa4] @ PLL1CFG <- dividor and multiplier for 48 MHZ (USB) / configure PLL1 str sv1, [rva, #0xa0] @ PLL1CON <- enable PLL1 set sv4, #0xaa set sv5, #0x55 str sv4, [rva, #0xac] @ PLL1FEED <- feed PLL1 str sv5, [rva, #0xac] @ PLL1FEED <- feed PLL1 usbwt0: ldr rvb, [rva, #0xa8] @ rvb <- PLL status tst rvb, #0x0400 @ is PLL locked? beq usbwt0 @ if not, jump to keep waiting str sv3, [rva, #0xa0] @ PLL1CON <- connect PLL1 str sv4, [rva, #0xac] @ PLL1FEED <- feed PLL1 str sv5, [rva, #0xac] @ PLL1FEED <- feed PLL1 .else @ 3. Turn on USB device clock (see 9-2-1) (4. we're using port1 for device = default) ldr rva, =0xFFE0CFF4 @ rva <- USBClkCtrl set rvb, #0x12 @ rvb <- DEV_CLK_EN, AHB_CLK_EN str rvb, [rva] @ enable USB clock and AHB clock usbwt0: ldr rvb, [rva] and rvb, rvb, #0x12 eq rvb, #0x12 bne usbwt0 .endif @ 4. Disable all USB interrupts. ldr rva, =USBIntSt str fre, [rva] ldr rva, =usb_base str fre, [rva, #0x04] @ USBDevIntEn str fre, [rva, #0x34] @ USBEpIntEn @ 5. Configure pins .ifndef LPC2478_STK @ Set PINSEL1 to enable USB VBUS and the soft connect/good link LED function. @ VBUS = 15:14 (P0.23) -> 01, UP_LED = 31:30 (P0.31) -> 01, CONNECT = 31:30 -> 10 ldr rva, =PINSEL1 ldr rvb, [rva] bic rvb, rvb, #0xC0000000 bic rvb, rvb, #0x0000C000 orr rvb, rvb, #0x00004000 str rvb, [rva] @ VBUS: unplug => CON_CH DEV_STAT intrpt ldr rva, =io0_base ldr rvb, [rva, #io_dir] orr rvb, rvb, #0xE0000000 str rvb, [rva, #io_dir] @ config P0.29-31 as outpt gpio (for USB pseudo-connect fnctin on P0.31) .else @ enable USB D-, D+, USB_UP_LED1, USB-Connect (GPIO) ldr rva, =PINSEL1 ldr rvb, [rva] bic rvb, rvb, #0x3C000000 orr rvb, rvb, #0x14000000 str rvb, [rva] @ set P0.29, P0.30 to USB1(device) D-, D+ ldr rva, =PINSEL3 ldr rvb, [rva] bic rvb, rvb, #0xF0 orr rvb, rvb, #0x10 str rvb, [rva] @ set P1.18 to USB_UP_LED, P1.19 GPIO (USB_CONNECT) ldr rvb, [rva, #0x40] bic rvb, rvb, #0xF0 orr rvb, rvb, #0xA0 str rvb, [rva, #0x40] @ PINMODE0 <- disable pull-up/down resistors on pins ldr rva, =io1_base ldr rvb, [rva, #io_dir] orr rvb, rvb, #0x00080000 str rvb, [rva, #io_dir] @ config P1.19 as output gpio (for USB pseudo-connect function) .endif @ 6. Set Endpoint index and MaxPacketSize registers for EP0 and EP1, and wait until the @ EP_RLZED bit in the Device interrupt status register is set so that EP0/1 are realized. ldr rva, =usb_base str fre, [rva, #0x48] @ USBEpInd -- USBEpIndEP_INDEX <- 0 set sv4, #0x08 str sv4, [rva, #0x4c] @ USBMaxPSize -- MAXPACKET_SIZE <- 8 set sv5, #0x0100 usbwt1: ldr rvb, [rva] @ USBDevIntSt -- wait for dev_int_stat to have EP_RLZED_INT (= 0x100) tst rvb, sv5 beq usbwt1 str sv5, [rva, #0x08] @ USBDevIntClr -- clear EP_RLZD_INT str sv1, [rva, #0x48] @ USBEpInd -- EP_INDEX <- 1 str sv4, [rva, #0x4c] @ USBMaxPSize -- MAXPACKET_SIZE <-8 usbwt2: ldr rvb, [rva] @ USBDevIntSt -- wait for dev_int_stat to have EP_RLZED_INT (= 0x100) tst rvb, sv5 beq usbwt2 str sv5, [rva, #0x08] @ USBDevIntClr -- clear EP_RLZD_INT @ 7. Clear, then Enable, all Endpoint interrupts ldr sv4, =0xFFFFFFFF str sv4, [rva, #0x38] @ USBEpIntClr -- EP_INT_CLR = 0xFFFFFFFF; str sv4, [rva, #0x34] @ USBEpIntEn -- EP_INT_EN = 0xFFFFFFFF; @ 8. Clear Device Interrupts, then Enable DEV_STAT, EP_SLOW, EP_FAST, FRAME str sv4, [rva, #0x08] @ USBDevIntClr -- DEV_INT_CLR = 0xFFFFFFFF; set rvb, #0x0c str rvb, [rva, #0x04] @ USBDevIntEn -- rvb <- 0x08 (DEV_STAT_INT) + 0x04 (EP_SLOW_INT) @ 9. Install USB interrupt handler in the VIC table and enable USB interrut in VIC. .ifndef LPC2478_STK ldr rva, =int_base+8 ldr rvb, =usbisr str rvb, [rva, #0x0100] @ VICVectAddr2 <- specify IRQ ISR address, pos 2 set rvb, #0x36 str rvb, [rva, #0x0200] @ VICVectCntl2 <- vec pos 2 enbld (0x20), IRQ#=22 USB (0x16) (tbl 47) set rvb, #0x00400000 str rvb, [rva, #0x08] @ VicIntEnable <- Enable USB Interrupt (IRQ#22 -> bit 22) .else ldr rva, =int_base @ rva <- Vectored Interrupt Controller (VIC) base address @ add rvc, rva, #0x100 ldr rvb, =usbisr @ str rvb, [rvc, #0x58] @ VICVectAddr22 <- USB IRQ handler = usbisr str rvb, [rva, #0x0158] @ VICVectAddr22 <- USB IRQ handler = usbisr set rvb, #0x00400000 str rvb, [rva, #0x10] @ VicIntEnable <- Enable USB Interrupt (IRQ#22 -> bit 22) .endif @ 10. Set default USB address to 0x0 and send Set Address cmd to the protoc engin (twice, see manual). set rvc, lnk @ r12 <- lnk, saved against wrtcmd ldr rvb, =0xD00500 bl wrtcmd @ execute set-address command (0x0500 = write command) ldr rvb, =0x800100 bl wrtcmd @ execute device enable on address zero (0x80) (0x0100 = write data) ldr rvb, =0xD00500 bl wrtcmd @ execute set-address command (0x0500 = write command) ldr rvb, =0x800100 bl wrtcmd @ execute device enable on address zero (0x80) (0x0100 = write data) @ 11. Set CON bit to 1 to make SoftConnect_N active (send Set Device Status cmd to protocol engine) ldr rvb, =0xFE0500 bl wrtcmd @ execute get/set device status command ldr rvb, =0x010100 bl wrtcmd @ execute set device status to connected (0x01) @ 12. Set AP_Clk high so that USB clock does not disconnect on suspend ldr rvb, =0xF30500 bl wrtcmd @ execute get/set mode command ldr rvb, =0x010100 bl wrtcmd @ execute set mode to "no suspend" (0x01) (around p. 197, 225) @ exit once connected ldr rva, =USBIntSt set rvb, #0x80000000 str rvb, [rva] @ activate USB interupts (connect to VIC) ldr rva, =USB_CONF usbwt3: ldr rvb, [rva] @ wait until configured before going on to scheme tst rvb, sv4 beq usbwt3 set lnk, rvc @ lnk <- restored .endif @ native_usb @ end of the hardware initialization set pc, lnk @------------------------------------------------------------------------------------------------ @ @ 1- Initialization from FLASH, writing to and erasing FLASH @ 2- I2C Interrupt routine @ @------------------------------------------------------------------------------------------------ @ @ 1- Initialization from FLASH, writing to and erasing FLASH @ .ifndef LCDDemo_2158 .ifndef LPC2478_STK FlashInitCheck: @ return status of flash init enable/override gpio pin (P0.3) in rva ldr rvb, =PINSEL0 @ set P0.3 to gpio ldr sv1, [rvb] bic rva, sv1, #0x00C0 str rva, [rvb] ldr rvb, =io0_base @ set P0.3 as input ldr sv2, [rvb, #io_dir] bic rva, sv2, #0x08 str rva, [rvb, #io_dir] ldr rva, [rvb] @ rva <- values of all P0.X and rva, rva, #8 @ rva <- status of P0.3 only (return value) str sv2, [rvb, #io_dir] ldr rvb, =PINSEL0 @ reset P0.3 to its initialized setting str sv1, [rvb] set sv1, #null @ sv1 <- '() (cleared for exit) set sv2, sv1 @ sv2 <- '() (cleared for exit) set pc, lnk .endif .endif .ifdef LCDDemo_2158 FlashInitCheck: @ return status of flash init enable/override gpio pin (P2.19 - button 1) in rva @ ldr rvb, =io0_base @ rvb <- address of gpio 0 base register ldr rvb, =0x3fffc054 @ rvb <- address of fio2pin ldr rva, [rvb] @ rva <- values of all P2.X and rva, rva, #0x080000 @ rva <- status of P2.19 only (return value) set pc, lnk .endif .ifdef LPC2478_STK FlashInitCheck: @ return status of flash init enable/override gpio pin (P0.16 - Mode switch) in rva ldr rvb, =io0_base @ rvb <- address of gpio 0 base register ldr rva, [rvb] @ rva <- values of all P0.X and rva, rva, #0x010000 @ rva <- status of P0.16 only (Mode switch) (return value) set pc, lnk .endif .ifdef SMALL_MEMORY wrtfla: @ write to flash, r2 = page address, r4 = file descriptor swi run_no_irq @ disable interrupts (user mode) stmfd sp!, {rva, rvb, rvc, lnk} @ store scheme registers onto stack set rvb, #20 @ rvb <- 20 = space for 5 IAP arguments (words) bl zmaloc @ rva <- address of free memory bic fre, fre, #0x03 @ fre <- address of free cell for IAP arguments stmfd sp!, {fre, cnt, sv1-sv5, env, dts, glv} @ store scheme registers onto stack set r2, #50 @ r2 <- IAP command 50 -- prepare sector for write bl iap000 @ prepare sector for write ldmfd sp, {r0-r5} @ restore r0 = iap addr, r3 <- sv2=page addr, r5 <- sv4=file descriptor bl iap001 @ write data to flash ldmfd sp!, {fre, cnt, sv1-sv5, env, dts, glv} @ restore scheme registers from stack ldmfd sp!, {rva, rvb, rvc, lnk} @ restore scheme registers from stack orr fre, fre, #0x02 @ fre <- fre-ptr de-reserved swi run_normal @ enable interrupts (user mode) set pc, lnk @ return ersfla: @ erase flash sector that contains page address in sv2 (has to be sector 7) fleras: @ erase flash sector 7 (ie. erase all file flash on LPC2131) swi run_no_irq @ disable interrupts (user mode) stmfd sp!, {rva, rvb, rvc, lnk} @ store scheme registers onto stack set rvb, #16 @ rvb <- 16 = space for 4 IAP arguments (words) bl zmaloc @ rva <- address of free memory bic fre, fre, #0x03 @ fre <- address of free cell for IAP arguments stmfd sp!, {fre, cnt, sv1-sv5, env, dts, glv} @ store scheme registers onto stack set r2, #50 @ r2 <- IAP command 50 -- prepare sector for write bl iap000 @ prepare sector for write ldmfd sp, {r0} @ restore IAP arguments address from stack set r2, #52 @ r2 <- IAP command 52 -- erase FLASH sector(s) bl iap000 @ erase sector ldmfd sp!, {fre, cnt, sv1-sv5, env, dts, glv} @ restore scheme registers from stack ldmfd sp!, {rva, rvb, rvc, lnk} @ restore scheme registers from stack orr fre, fre, #0x02 @ fre <- fre-ptr de-reserved swi run_normal @ enable interrupts (user mode) set pc, lnk @ return iap000: @ prepare FLASH sector 7 for write, or erase it @ on entry: r0 <- address for IAP input and output arguments @ on entry: r2 <- IAP command to execute set r1, r0 @ r1 <- IAP results table (same as arguments) set r3, #7 @ r3 <- start sector set r4, #7 @ r4 <- end sector ldr r5, =CLOCK_FREQ @ r5 <- clock frequency stmia r0, {r2-r5} @ store IAP arguments ldr r12, =IAP_ENTRY @ r12 <- address of IAP routine bx r12 @ jump to perform IAP iap001: @ write to FLASH @ on entry: r0 <- address for IAP input and output arguments @ on entry: r3 <- target FLASH page address @ on entry: r5 <- file descriptor set r1, r0 @ r1 <- IAP results table (same as arguments) set r2, #51 @ r2 <- IAP command 51 -- copy RAM to FLASH vcrfi r4, r5, 3 @ r4 <- buffer add r4, r4, #4 @ r4 <- RAM start address (data in buffer r3) set r5, #F_PAGE_SIZE @ r5 <- number of bytes to write ldr r6, =CLOCK_FREQ @ r6 <- clock frequency stmia r0, {r2-r6} @ store IAP arguments ldr r12, =IAP_ENTRY @ r12 <- address of IAP routine bx r12 @ jump to perform IAP .ifdef TINY_2131 flashsectors: @ 8 x 4KB FLASH sectors of LPC2131 .word 0x00000, 0x01000, 0x02000, 0x03000, 0x04000, 0x05000, 0x06000, 0x07000, 0x08000 .endif @ .ifdef TINY_2131 .ifdef LPC_H2103 flashsectors: @ 8 x 4KB FLASH sectors of LPC2103 .word 0x00000, 0x01000, 0x02000, 0x03000, 0x04000, 0x05000, 0x06000, 0x07000, 0x08000 .endif @ .ifdef LPC_H2103 .else @ CASE WHERE MCU IS NOT SMALL_MEMORY .ifndef LPC_H2214 @ if not a LPC-H2214 which has external FLASH wrtfla: @ write to flash, sv2 = page address and sv4 = file descriptor swi run_no_irq @ disable interrupts (user mode) stmfd sp!, {rva, rvb, rvc, lnk} @ store scheme registers onto stack set rvb, #20 @ rvb <- 20 = space for 5 IAP arguments (words) bl zmaloc @ rva <- address of free memory bic fre, fre, #0x03 @ fre <- address of free cell for IAP arguments stmfd sp!, {fre, cnt, sv1-sv5, env, dts, glv} @ store scheme registers onto stack .ifdef LPC2478_STK ldr fre, =0x4000F000 @ fre <- address for IAP arguments (63KB into on-chip RAM) .endif @ prepare flash sector for write bl pgsctr @ r2 <- sector number (raw int), from page address in r5 {sv2} set r1, r0 @ r1 <- IAP results table (same as arguments) set r3, #50 @ r3 <- IAP command 50 -- prepare sector for write set r4, r2 @ r4 <- start sector set r5, r2 @ r5 <- end sector stmia r0, {r3-r5} @ write IAP arguments bl go_iap @ run IAP @ copy RAM flash to FLASH ldmfd sp, {r0, r1, r4-r7} @ restore r5 {sv2} = page address and r7 {sv4} = file dscrptr from stack .ifdef LPC2478_STK ldr r0, =0x4000F000 @ r0 <- address for IAP arguments (63KB into on-chip RAM) .endif set r1, r0 @ r1 <- IAP results table (same as arguments) set r2, #51 @ r2 <- IAP command 51 -- copy RAM to FLASH set r3, r5 @ r3 <- page address vcrfi r4, r7, 3 @ r4 <- address of buffer add r4, r4, #4 @ r4 <- RAM start address for data in buffer .ifdef LPC2478_STK add r5, r0, #24 set r6, #F_PAGE_SIZE wrtflp: subs r6, r6, #4 ldr r7, [r4, r6] str r7, [r5, r6] bne wrtflp set r4, r5 .endif set r5, #F_PAGE_SIZE @ r5 <- number of bytes to write ldr r6, =CLOCK_FREQ @ r6 <- clock frequency stmia r0, {r2-r6} @ store IAP arguments (command, page, source, numbytes, freq) bl go_iap @ run IAP @ finish up ldmfd sp!, {fre, cnt, sv1-sv5, env, dts, glv} @ restore scheme registers from stack ldmfd sp!, {rva, rvb, rvc, lnk} @ restore scheme registers from stack orr fre, fre, #0x02 @ fre <- fre-ptr de-reserved swi run_normal @ enable interrupts (user mode) set pc, lnk @ return ersfla: @ erase flash sector that contains page address in sv2 swi run_no_irq @ disable interrupts (user mode) stmfd sp!, {rva, rvb, rvc, lnk} @ store scheme registers onto stack set rvb, #16 @ rvb <- 16 = space for 4 IAP arguments (words) bl zmaloc @ rva <- address of free memory bic fre, fre, #0x03 @ fre <- address of free cell for IAP arguments stmfd sp!, {fre, cnt, sv1-sv5, env, dts, glv} @ store scheme registers onto stack .ifdef LPC2478_STK ldr fre, =0x4000F000 @ fre <- address for IAP arguments (63KB into on-chip RAM) .endif @ prepare flash sector for write bl pgsctr @ r2 <- sector number (raw int), from page address in sv2 set r1, fre @ r1 <- IAP results table (same as arguments) set r3, #50 @ r3 <- IAP command 50 -- prepare sector for write set r4, r2 @ r4 <- start sector set r5, r2 @ r5 <- end sector stmia fre, {r3-r5} @ write IAP arguments bl go_iap @ run IAP @ erase flash sector ldmfd sp, {fre, cnt, sv1-sv2} @ restore page address in sv2 {r5} from stack .ifdef LPC2478_STK ldr r0, =0x4000F000 @ r0 <- address for IAP arguments (63KB into on-chip RAM) .endif bl pgsctr @ r2 <- sector number (raw int), from page address in sv2 set r1, fre @ r1 <- IAP results table (same as arguments) set r3, #52 @ r3 <- IAP command 52 -- erase FLASH sector(s) set r4, r2 @ r4 <- start sector set r5, r2 @ r5 <- end sector ldr r6, =CLOCK_FREQ @ r6 <- clock frequency stmia fre, {r3-r6} @ write IAP arguments bl go_iap @ run IAP @ finish up ldmfd sp!, {fre, cnt, sv1-sv5, env, dts, glv} @ restore scheme registers from stack ldmfd sp!, {rva, rvb, rvc, lnk} @ restore scheme registers from stack orr fre, fre, #0x02 @ fre <- fre-ptr de-reserved swi run_normal @ enable interrupts (user mode) set pc, lnk @ return go_iap: ldr r12, =IAP_ENTRY @ r12 <- address of IAP routine bx r12 @ jump to perform IAP .ifdef TINY_2106 flashsectors: @ 16 x 8KB FLASH sectors of LPC2106 .word 0x00000, 0x02000, 0x04000, 0x06000, 0x08000, 0x0A000, 0x0C000, 0x0E000 .word 0x10000, 0x12000, 0x14000, 0x16000, 0x18000, 0x1A000, 0x1C000, 0x1E000, 0x0FFFFFFC .endif @ .ifdef TINY_2106 .ifdef TINY_2138 flashsectors: @ 8 x 4KB, 14 x 32KB, 5 x 4KB FLASH sectors of LPC2138 .word 0x00000, 0x01000, 0x02000, 0x03000, 0x04000, 0x05000, 0x06000, 0x07000 .word 0x08000, 0x10000, 0x18000, 0x20000, 0x28000, 0x30000, 0x38000, 0x40000 .word 0x48000, 0x50000, 0x58000, 0x60000, 0x68000, 0x70000 .word 0x78000, 0x79000, 0x7A000, 0x7B000, 0x7C000, 0x0FFFFFFC .endif @ .ifdef TINY_2138 .ifdef SFE_Logomatic1 flashsectors: @ 8 x 4KB, 14 x 32KB, 5 x 4KB FLASH sectors of LPC2138 .word 0x00000, 0x01000, 0x02000, 0x03000, 0x04000, 0x05000, 0x06000, 0x07000 .word 0x08000, 0x10000, 0x18000, 0x20000, 0x28000, 0x30000, 0x38000, 0x40000 .word 0x48000, 0x50000, 0x58000, 0x60000, 0x68000, 0x70000 .word 0x78000, 0x79000, 0x7A000, 0x7B000, 0x7C000, 0x0FFFFFFC .endif @ .ifdef SFE_Logomatic1 .ifdef SFE_Logomatic2 flashsectors: @ 8 x 4KB, 14 x 32KB, 5 x 4KB FLASH sectors of LPC2148 .word 0x00000, 0x01000, 0x02000, 0x03000, 0x04000, 0x05000, 0x06000, 0x07000 .word 0x08000, 0x10000, 0x18000, 0x20000, 0x28000, 0x30000, 0x38000 .word 0x40000, 0x48000, 0x50000, 0x58000, 0x60000, 0x68000, 0x70000 .word 0x78000, 0x79000, 0x7A000, 0x7B000, 0x7C000, 0x0FFFFFFC .endif @ .ifdef SFE_Logomatic2 .ifdef LPC_H2148 flashsectors: @ 8 x 4KB, 14 x 32KB, 5 x 4KB FLASH sectors of LPC2148 .word 0x00000, 0x01000, 0x02000, 0x03000, 0x04000, 0x05000, 0x06000, 0x07000 .word 0x08000, 0x10000, 0x18000, 0x20000, 0x28000, 0x30000, 0x38000 .word 0x40000, 0x48000, 0x50000, 0x58000, 0x60000, 0x68000, 0x70000 .word 0x78000, 0x79000, 0x7A000, 0x7B000, 0x7C000, 0x0FFFFFFC .endif @ .ifdef LPC_H2148 .ifdef LCDDemo_2158 flashsectors: @ 8 x 4KB, 14 x 32KB, 5 x 4KB FLASH sectors of LPC2158 .word 0x00000, 0x01000, 0x02000, 0x03000, 0x04000, 0x05000, 0x06000, 0x07000 .word 0x08000, 0x10000, 0x18000, 0x20000, 0x28000, 0x30000, 0x38000 .word 0x40000, 0x48000, 0x50000, 0x58000, 0x60000, 0x68000, 0x70000 .word 0x78000, 0x79000, 0x7A000, 0x7B000, 0x7C000, 0x0FFFFFFC .endif @ .ifdef LCDDemo_2158 .ifdef LPC2478_STK flashsectors: @ 8 x 4KB, 14 x 32KB, 5 x 4KB FLASH sectors of LPC2478 .word 0x00000, 0x01000, 0x02000, 0x03000, 0x04000, 0x05000, 0x06000, 0x07000 .word 0x08000, 0x10000, 0x18000, 0x20000, 0x28000, 0x30000, 0x38000 .word 0x40000, 0x48000, 0x50000, 0x58000, 0x60000, 0x68000, 0x70000 .word 0x78000, 0x79000, 0x7A000, 0x7B000, 0x7C000, 0x0FFFFFFC .endif @ .ifdef LPC2478_STK .else @ code to use external FLASH on LPC-H2214 wrtfla: @ write to flash, sv2 = target page address, sv4 = file descriptor @ uses 56 bytes of user-stack space swi run_no_irq @ disable interrupts (user mode) stmfd sp!, {rva, rvb, rvc, lnk} @ store scheme registers onto stack stmfd sp!, {fre, cnt, sv1-sv5, env, dts, glv} @ store scheme registers onto stack @ copy buffer data from file descriptor {sv4=r7} (RAM) to FLASH {sv2=r5} vcrfi sv3, sv4, 3 @ sv3 <- buffer address (source start, minus one word) add rva, sv2, #F_PAGE_SIZE @ rva <- end target address @ perform write, 2 half-words at a time ldr sv1, =0x80000aaa @ sv1 <- flash command address 1 ldr sv5, =0x80000554 @ sv5 <- flash command address 2 wrtfl0: add sv3, sv3, #4 @ sv3 <- source word address ldrh rvb, [sv2] @ rvb <- prior contents of FLASH cell, half-word 1 set rvc, #0xaa @ rvc <- flash command 1 strh rvc, [sv1] @ write command to flash set rvc, #0x55 @ rvc <- flash command 2 strh rvc, [sv5] @ write command to flash set rvc, #0xa0 @ rvc <- flash command 3 strh rvc, [sv1] @ write command to flash ldrh rvc, [sv3] @ rvc <- first half-word from buffer and rvc, rvc, rvb @ rvc <- new data ANDed with original FLASH contents strh rvc, [sv2] @ write ANDed data to FLASH cell wrtfw0: ldrh rvb, [sv2] @ rvb <- contents of FLASH cell, half-word 1 eq rvc, rvb @ has flash content been updated? bne wrtfw0 @ if not, jump to keep waiting ldrh rvb, [sv2, #2] @ rvb <- prior contents of FLASH cell, half-word 2 set rvc, #0xaa @ rvc <- flash command 1 strh rvc, [sv1] @ write command to flash set rvc, #0x55 @ rvc <- flash command 2 strh rvc, [sv5] @ write command to flash set rvc, #0xa0 @ rvc <- flash command 3 strh rvc, [sv1] @ write command to flash ldrh rvc, [sv3, #2] @ rvc <- second half-word from buffer and rvc, rvc, rvb @ rvc <- new data ANDed with original FLASH contents strh rvc, [sv2, #2] @ write ANDed data to FLASH cell wrtfw1: ldrh rvb, [sv2, #2] @ rvb <- contents of FLASH cell, half-word 2 eq rvc, rvb @ has flash content been updated? bne wrtfw1 @ if not, jump to keep waiting add sv2, sv2, #4 @ sv2 <- next destination address cmp sv2, rva @ done writing? bmi wrtfl0 @ if not, jump to keep writing to flash @ finish up ldmfd sp!, {fre, cnt, sv1-sv5, env, dts, glv} @ restore scheme registers from stack ldmfd sp!, {rva, rvb, rvc, lnk} @ restore scheme registers from stack swi run_normal @ enable interrupts (user mode) set pc, lnk @ return ersfla: @ erase flash sector that contains page address in sv2 @ uses 56 bytes of user-stack space swi run_no_irq @ disable interrupts (user mode) stmfd sp!, {rva, rvb, rvc, lnk} @ store scheme registers onto stack stmfd sp!, {fre, cnt, sv1-sv5, env, dts, glv} @ store scheme registers onto stack @ prepare flash sector for write bl pgsctr @ rva <- sector number (raw int), from page address in sv2 adr rvb, flashsectors @ rvb <- address of flash sector table ldr rvb, [rvb, rva, LSL #2] @ rvb <- start address of flash block to be erased ldr sv1, =0x80000aaa @ sv1 <- flash command address 1 ldr sv5, =0x80000554 @ sv5 <- flash command address 2 set rvc, #0xaa @ rvc <- flash command 1 strh rvc, [sv1] @ write command to flash set rvc, #0x55 @ rvc <- flash command 2 strh rvc, [sv5] @ write command to flash set rvc, #0x80 @ rvc <- flash command 3 strh rvc, [sv1] @ write command to flash set rvc, #0xaa @ rvc <- flash command 1 strh rvc, [sv1] @ write command to flash set rvc, #0x55 @ rvc <- flash command 2 strh rvc, [sv5] @ write command to flash set rvc, #0x30 @ rvc <- flash command 4 -- erase block strh rvc, [rvb] @ write command to flash -- erase block rvb ldr rvc, =0xffff @ rvc <- #xffff = erased half-word mask erswt0: ldrh rva, [rvb] @ rva <- 1st half-wrod of erased flash block eq rva, rvc @ is it erased? bne erswt0 @ if not, jump to keep waiting @ finish up ldmfd sp!, {fre, cnt, sv1-sv5, env, dts, glv} @ restore scheme registers from stack ldmfd sp!, {rva, rvb, rvc, lnk} @ restore scheme registers from stack swi run_normal @ enable interrupts (user mode) set pc, lnk @ return flashsectors: @ 1 x 16KB, 2 x 8KB, 1 x 32KB, 15 x 64KB FLASH sectors of MX26LV800BTC on LPC-H2214 .word 0x80000000, 0x80004000, 0x80006000, 0x80008000 .word 0x80010000, 0x80020000, 0x80030000, 0x80040000, 0x80050000, 0x80060000, 0x80070000, 0x80080000 .word 0x80090000, 0x800A0000, 0x800B0000, 0x800C0000, 0x800D0000, 0x800E0000, 0x800F0000, 0x80100000 .endif @ ifndef LPC_H2214 .endif @ ifdef SMALL_MEMORY TINY_2131 .ltorg @ dump literal constants here => up to 4K of code before and after this point @ @ 2- I2C Interrupt routine @ .ifndef SMALL_MEMORY hwi2cr: @ write-out additional address registers, if needed @ modify interupts, as needed @ on entry: sv5 <- i2c[0/1]buffer @ on entry: rva <- i2c[0/1] base address (also I2CONSET) @ interrupts are disabled throughout set rvb, #0 @ rvb <- 0 bytes to send (scheme int) tbsti rvb, sv5, 3 @ store number of bytes to send in i2c buffer[12] @ initiate i2c read/write, as master swi run_normal @ re-enable interrupts set rvb, #0x20 @ rvb <- i2c START command strb rvb, [rva, #i2c_cset] @ initiate bus mastering (write start to i2c[0/1]conset) hwi2r0: @ wait for mcu address and registers to have been transmitted swi run_no_irq @ disable interrupts tbrfi rvb, sv5, 1 @ rvb <- data ready status from i2cbuffer[4] eq rvb, #f @ is i2c data ready = #f (i.e. addresses have been transmitted) seteq pc, lnk @ if so, jump to continue swi run_normal @ re-enable interrupts b hwi2r0 @ jump to keep waiting hwi2ni: @ initiate i2c read/write, as master @ on entry: rva <- i2c[0/1] base address (also I2CONSET) set rvb, #0x20 @ rvb <- i2c START command strb rvb, [rva, #i2c_cset] @ initiate bus mastering (write start to i2c[0/1]conset) set pc, lnk hwi2st: @ get i2c interrupt status and base address @ on exit: rva <- i2c[0/1] base address @ on exit: rvb <- i2c interrupt status ldrb rvb, [rva, #i2c_status] @ r7 <- I2C Status set pc, lnk i2c_hw_branch: @ process interrupt eq rvb, #0x08 @ Master Read/Write -- bus now mastered (I2STAT = 0x08) beq i2c_hw_mst_bus eq rvb, #0x18 @ Master Write -- slave has acknowledged address (I2STAT = 0x18) beq i2c_wm_ini eq rvb, #0x28 @ Master Write -- slave ok to receive data (I2STAT = 0x28) beq i2c_wm_put eq rvb, #0x40 @ Master Read -- slave ackn. address - (set nak?) (I2STAT = 0x40) beq i2c_rm_ini eq rvb, #i2c_irm_rcv @ Master Read -- new byte received - (set nak?) (I2STAT = 0x50) beq i2c_rm_get eq rvb, #0x58 @ Master Read -- last byte received (I2STAT = 0x58) beq i2c_rm_end eq rvb, #0x60 @ Slave Read -- address recognized as mine (I2STAT = 0x60) beq i2c_rs_ini eq rvb, #i2c_irs_rcv @ Slave Read -- new data received (I2STAT = 0x80) beq i2c_rs_get eq rvb, #0xA0 @ Slave Read -- STOP or re-START received (I2STAT = 0xA0) beq i2c_rs_end eq rvb, #0xA8 @ Slave Write -- address recognized as mine (I2STAT = 0xA8) beq i2c_ws_ini eq rvb, #0xB8 @ Slave Write -- master requests byte (I2STAT = 0xB8) beq i2c_ws_put eq rvb, #0xC0 @ Slave Write -- NAK received from master/done (I2STAT = 0xC0) beq i2c_ws_end set pc, lnk i2c_hw_mst_bus: @ Reading or Writing as Master -- bus now mastered (I2STAT = 0x08) tbrfi rva, sv2, 0 @ rva <- address of mcu to send data to (scheme int) lsr rva, rva, #1 @ rva <- mcu-id as int -- note: ends with 0 (i.e. divide by 2) strb rva, [sv3, #i2c_thr] @ set address of mcu to send data to set rva, #0x20 @ rva <- bit 5 strb rva, [sv3, #i2c_cclear] @ clear START bit to enable Tx of target address b i2cxit hwi2we: @ set busy status/stop bit at end of write as master @ on entry: sv2 <- i2c[0/1] buffer address @ on entry: sv3 <- i2c[0/1] base address @ on entry: rvb <- #f tbrfi rva, sv2, 3 @ rva <- number of data bytes to send (raw int) eq rva, #0 @ were we sending 0 bytes (i.e. reading as master, done writing address bytes)? tbstine rvb, sv2, 0 @ if not, set busy status to #f (transfer done) setne rva, #0x10 @ if not, rva <- STOP bit used to stop i2c transfer strbne rva, [sv3, #i2c_cset] @ if not, set STOP bit to stop i2c transfer set pc, lnk hwi2re: @ set stop bit if needed at end of read-as-master set rva, #0x014 @ rva <- bit4 | bit 2 strb rva, [sv3, #i2c_cset] @ set STOP bit and reset AA to AK set pc, lnk hwi2cs: @ clear SI set rva, #0x08 @ clear SI strb rva, [sv3, #i2c_cclear] set pc, lnk i2cstp: @ prepare to end Read as Master transfer set rva, #0x04 @ rva <- bit 2 strb rva, [sv3, #i2c_cclear] @ set AA to NAK set pc, lnk i2putp: @ Prologue: write additional address bytes to i2c, from buffer or r12 (prologue) tbrfi rva, sv2, 1 @ rva <- number of additional address bytes to send (scheme int) eq rva, #i0 @ no more address bytes to send? tbrfieq rva, sv2, 3 @ if so, rva <- number of data bytes to send (raw int) tbrfieq rvb, sv2, 4 @ if so, rvb <- number of data bytes sent (raw int) eqeq rva, rvb @ if so, are we done sending data? beq i2c_wm_end @ if so, jump to stop or restart x-fer and exit tbrfi rvb, sv2, 1 @ r7 <- number of address bytes remaining to send (scheme int) eq rvb, #i0 @ done sending address bytes? subne rvb, rvb, #4 @ if not, rvb <- updated number of address bytes to send (scheme int) tbstine rvb, sv2, 1 @ if not, store updated number of address bytes to send in i2cbuffer[4] addne rva, sv2, #8 @ if not, rva <- address of additional address bytes in i2cbuffer ldrbne rva, [rva, rvb, LSR #2] @ if not, rva <- next address byte to send strbne rva, [sv3, #i2c_thr] @ put next data byte in I2C data register bne i2cxit set pc, lnk i2pute: @ Epilogue: set completion status if needed (epilogue) set pc, lnk .endif .ltorg @ dump literal constants here => up to 4K of code before and after this point