/****************************************************************************** * gpio.s * by Alex Chadwick * * A sample assembly code implementation of the ok05 operating system. * See main.s for details. * * gpio.s contains the rountines for manipulation of the GPIO ports. ******************************************************************************/ /* NEW * According to the EABI, all method calls should use r0-r3 for passing * parameters, should preserve registers r4-r8,r10-r11,sp between calls, and * should return values in r0 (and r1 if needed). * It does also stipulate many things about how methods should use the registers * and stack during calls, but we're using hand coded assembly. All we need to * do is obey the start and end conditions, and if all our methods do this, they * would all work from C. */ /* NEW * GetGpioAddress returns the base address of the GPIO region as a physical address * in register r0. * C++ Signature: void* GetGpioAddress() */ .globl GetGpioAddress GetGpioAddress: gpioAddr .req r0 ldr gpioAddr,=0x20200000 mov pc,lr .unreq gpioAddr /* NEW * SetGpioFunction sets the function of the GPIO register addressed by r0 to the * low 3 bits of r1. * C++ Signature: void SetGpioFunction(u32 gpioRegister, u32 function) */ .globl SetGpioFunction SetGpioFunction: pinNum .req r0 pinFunc .req r1 cmp pinNum,#53 cmpls pinFunc,#7 movhi pc,lr push {lr} mov r2,pinNum .unreq pinNum pinNum .req r2 bl GetGpioAddress gpioAddr .req r0 functionLoop$: cmp pinNum,#9 subhi pinNum,#10 addhi gpioAddr,#4 bhi functionLoop$ add pinNum, pinNum,lsl #1 lsl pinFunc,pinNum mask .req r3 mov mask,#7 /* r3 = 111 in binary */ lsl mask,pinNum /* r3 = 11100..00 where the 111 is in the same position as the function in r1 */ .unreq pinNum mvn mask,mask /* r3 = 11..1100011..11 where the 000 is in the same poisiont as the function in r1 */ oldFunc .req r2 ldr oldFunc,[gpioAddr] /* r2 = existing code */ and oldFunc,mask /* r2 = existing code with bits for this pin all 0 */ .unreq mask orr pinFunc,oldFunc /* r1 = existing code with correct bits set */ .unreq oldFunc str pinFunc,[gpioAddr] .unreq pinFunc .unreq gpioAddr pop {pc} /* NEW * SetGpio sets the GPIO pin addressed by register r0 high if r1 != 0 and low * otherwise. * C++ Signature: void SetGpio(u32 gpioRegister, u32 value) */ .globl SetGpio SetGpio: pinNum .req r0 pinVal .req r1 cmp pinNum,#53 movhi pc,lr push {lr} mov r2,pinNum .unreq pinNum pinNum .req r2 bl GetGpioAddress gpioAddr .req r0 pinBank .req r3 lsr pinBank,pinNum,#5 lsl pinBank,#2 add gpioAddr,pinBank .unreq pinBank and pinNum,#31 setBit .req r3 mov setBit,#1 lsl setBit,pinNum .unreq pinNum teq pinVal,#0 .unreq pinVal streq setBit,[gpioAddr,#40] strne setBit,[gpioAddr,#28] .unreq setBit .unreq gpioAddr pop {pc}