Sunday, December 8, 2013

Raspberry Pi :Lesson3 &Lesson4

                                                  Lesson 03
1- Introduction:
       In lesson 3 of Baking PI, we will do similar as we did in lesson 2, which making the ‘ACT’ light to be turning on and off periodically. However, in this lesson we are going to use a different approach, which is using the function in assembly in order to make more an efficient code. The SetGpio function causing the GPIO pin 16 to be off, so the ACT LED will be on. By considering a certain delay, the SetGpio function causing the GPIO pin 16 to be on, so the ACT LED will be off.

2- Materials and Procedures:
In order to carry this assignment out, there are two types of requirements .The first type is the required equipment and the second one is the software and the operating system.
2.1Equipment:
   1-A Raspberry Pi board (it is a single circuit that considered as a computer which, primary runs on a version of Linux).
   2-A computer uses a Microsoft Windows-based Operating System.
   3- A SD card (it is a memory card).
   4- A power supply.

2.2Software:
1-     Using  the GNU compiler toolchain in order to deal with the architecture
2-     The OS Template File
 (It provides a Makefile script, a Linker script and no assembly code would be provided. Since the compiler needs required instructions in order to create Operating System for the Raspberry Pi, those instructions have been provided by the OS Template file )


2.3 Experimental Procedure



The ARM assembly code for Lesson 3:
GPIO's:
globl GetGpioAddress
       GetGpioAddress:
               ldr r0,=0x20200000
               mov pc,lr
  We need to set the function of  a GPIO by  moving the physical  GPIO address which is (0x20200000) into r0 then  return none.

.globl SetGpioFunction
SetGpioFunction:
               cmp r0,#53
               cmpls r1,#7
               movhi pc,lr

               push {lr}
               mov r2,r0
               bl GetGpioAddress

               functionLoop$:
                              cmp r2,#9
                              subhi r2,#10
                              addhi r0,#4
                              bhi functionLoop$

               add r2, r2,lsl #1
               lsl r1,r2
               str r1,[r0]
               pop {pc}
Since there are 54 pins, we set both the pin and the function within the restricted range (0-53).
Chick for r0 if the pin number in (0-53) and for r1 if the pin in (0-7) .
By storing lr, we can make a method call.
In order to make sure  that r0  would not be overwritten by  the value of a return  function of
GetGpioAddress , we move out the pin from r0 to r2.
In order to find out in what a group that the   required pin in, we use a loop.
Now, by comparing the value of r2 to 9, if the value of r2 is not greater than 9 then the GPIO functions are in the group, otherwise it is not.
Moving the GPIO address in r0 by 4 increments and decrementing r2 by 10.
 The loop will be repeated if did match the right group.
The address that needs to be adjusted is stored In r0 and the offset that needs to adjusted is stored in r2
In each group, there exists 3 status bits for each pin. So, in order to find out what is the required bit offset, the value of r2 will be multiplied by 3.
Since the multiplication is a slow process rather than logical –shift –left(lsl), we  use the (lsl by 1) which gives a similar effect of using the  multiplication  by 2 .eventually the value will be added  again.

  r1 contains the 3 bits that are responsible of setting the pin’s status  and because of that, by using the (lsl) ,we shift the value in r1 bt the value of r2 to the right. Then we return back to the stack because it contains lr.

In order to turn  pin on or off  ,we should figure out  the byte that the  pin is in. 

.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}
In order to turn pin on or off, we should figure out the byte that the pin is in. 

By using the logical -shift t- the right(lsr) by 5 bits, we will be able to figure out if the pin is in the first set  , which means that if  the pin is <32,so its value is 0, otherwise the pin is in the second set , which means the pin is> 32 and its value is 1. In order to get the required offset to match the correct bank, we use   logical-shift –left (lsl) by 2 and then add it to the GPIO controller.
Since the first set is  (from0 to 31 of 1st  byte ) ,and  the second set is(from 0 to21 of 2nd   byte),so it is essential  that the  register only contains the bit offset. Beside that we know which byte group that we are looking for.



main's:
.section .init
.globl _start
_start:

b main
.section .init and .globl _start are directives that instructs the assembler in order to put our assembly code in a section its name is ( .init ).  Because of that, we will be able to control the order of the code execution. Also, the GNU toolchain needs a entry point to work properly, so we need to include symbol _start. Then, we need global, which is required by the linker. Then ( _start:) to start the address of the new line.


In order to branch to the actual main code, we use (b main)
mov sp,#0x8000
pinNum .req r0
pinFunc .req r1
mov pinNum,#16
mov pinFunc,#1
bl SetGpioFunction
.unreq pinNum
.unreq pinFunc
Moving the stack pointer to the location (0x8000).

Assined  pinNum to register  r0.
Assined pinFunc to register r1.

On GPIO, set the function (from pin 16 ~1) as output.
call function
delete assigned.
 delete assigned.

loop$:
pinNum .req r0
pinVal .req r1
mov pinNum,#16
mov pinVal,#0
bl SetGpio
.unreq pinNum
.unreq pinVal
By setting pin 16 on a low voltage(off) , the LED will be turn on and this can be done by using  
SetGpio function in order to turn off GPIO pin 16.
Assined  pinNum to register  pin 16.
Assined pinVal to register pin 0.
call function.
delete assigned.
 delete assigned.
decr .req r0
mov decr,#0x3F0000
wait1$:
               sub decr,#1
               teq decr,#0
               bne wait1$
.unreq decr
In order to achieve the delay, we need to have a little trick which is making the processor busy by decrementing the number from 0x3F0000 to 0.
pinNum .req r0
pinVal .req r1
mov pinNum,#16
mov pinVal,#1
bl SetGpio
.unreq pinNum
.unreq pinVal
By setting pin 16 on a high voltage(on) , the LED will be turn off and this can be done by using 
SetGpio function in order to turn on GPIO pin 16.
decr .req r0
mov decr,#0x3F0000
wait2$:
               sub decr,#1
               teq decr,#0
               bne wait2$
.unreq decr
In order to achieve the delay, we need to have a little trick which is making the processor busy by decrementing the number from 0x3F0000 to 0.

b loop$
Loop will keep running to keep the LED turning on and off until disconnecting from a proper power supply. 


3. Results:

http://youtu.be/7aLTezbNTa4





_________________________________________________________________________________
         
                                        Lesson 04

1- Introduction:
        Lesson 4 basically builds on the operating system of lesson 3 and the objective of lesson 4 is to show how we can use the system timer in order to flashing the ‘ACT’ LED at a certain or limited interval. The timer has a base address as well as GPIO controller.We need a new code to deal with the system timer, which acts as a counter that runs at 1MHz, and that system timer is used to count the difference between two measurements.
 The “ACT” or ok LED behaves as well as in the lesson 3, but the difference is that we are using the system timer, which sleeps within a specified interval of microseconds then gets up. As a result of that, the LED turns on and off based on the timer two statuses of sleeping and waking up.


2- Materials and Procedures:
In order to carry this assignment out, there are two types of requirements .The first type is the required equipment and the second one is the software and the operating system.
2.1Equipment:
   1-A Raspberry Pi board (it is a single circuit that considered as a computer which, primary runs on a version of Linux).
   2-A computer uses a Microsoft Windows-based Operating System.
   3- A SD card (it is a memory card).
   4- A power supply.

2.2Software:
1-     Using  the GNU compiler toolchain in order to deal with the architecture
2-     The OS Template File
 (It provides a Makefile script, a Linker script and no assembly code would be provided. Since the compiler needs required instructions in order to create Operating System for the Raspberry Pi, those instructions have been provided by the OS Template file )

2.3 Experimental Procedure



The ARM assembly code for Lesson 4:
GPIO;s:
.globl GetGpioAddress
GetGpioAddress:
               gpioAddr .req r0
               ldr gpioAddr,=0x20200000
               mov pc,lr
               .unreq gpioAddr
Loading the GPIO controller address(0x20200000)
In r0  ,then return

.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
Set pinNum in register r0 and pinFunc in register r1. Since there are 54 pins, we set both the pin and the function within the restricted range (0-53).
Chick for r0 if the pin number in (0-53) and for r1 if the pin in (0-7) .
By storing lr, we can make a method call.
In order to make sure  that r0  would not be overwritten by  the value of a return  function of
GetGpioAddress , then storing  it in 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                                                           
               .unreq pinFunc
               .unreq gpioAddr
               pop {pc}
Now, by comparing the value of pinNum to 9, if the value of pinNum is not greater than 9 then the GPIO functions are in the group, otherwise it is not.
Moving the GPIO address in r0 by 4 increments and decrementing pinNum by 10.
 The loop will be repeated if did match the right group.

The address that needs to be adjusted is stored In r0 and the offset that needs to be adjusted will be stored in pinNum.
In each group, there exists 3 status bits for each pin. So, in order to find out what is the required bit offset, the value of pinNum will be multiplied by 3.
Since the multiplication is a slow process rather than logical –shift –left(lsl), we  use the (lsl by 1) which gives a similar effect of using the  multiplication  by 2 .eventually the value will be added  again.

  pinFunc contains the 3 bits that are responsible of setting the pin’s status  and because of that, by using the (lsl) ,we shift the value in pinFunc bt the value of pinNum to the right. Then we return back to the stack because it contains lr.

In order to turn pin on or off, we should figure out the byte that the pin is in. 

.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
In order to turn pin on or off, we should figure out the byte that the pin is in. 

By using the logical -shift t- the right(lsr) by 5 bits, we will be able to figure out if the pin is in the first set  , which means that if  the pin is <32,so its value is 0, otherwise the pin is in the second set , which means the pin is> 32 and its value is 1. In order to get the required offset to match the correct bank, we use   logical-shift –left (lsl) by 2 and then add it to the GPIO controller.
Since the first set is  (from0 to 31 of 1st  byte ) ,and  the second set is(from 0 to21 of 2nd   byte),so it is essential  that the  register only contains the bit offset. Beside that we know which byte group that we are looking for.


main's:
.section .init
.globl _start
_start:
 .section .init and .globl _start are directives that instructs the assembler in order to put our assembly code in a section its name is ( .init ).  Because of that, we will be able to control the order of the code execution. Also, the GNU toolchain needs a entry point to work properly, so we need to include symbol _start. Then, we need global, which is required by the linker. Then ( _start:) to start the address of the new line.


In order to branch to the actual main code, we use (b main)
main:
mov sp,#0x8000

mov r0,#16
mov r1,#1
bl SetGpioFunction
Moving the stack pointer to the location (0x8000).
Move r0 to pin 16 and r2 to pin 1
In order to set the function of GPIO pin16 to be ‘ACT’LED with (001) ,we use SetGpioFunction function.

loop$:
mov r0,#16
mov r1,#0
bl SetGpio
In order to turn on the LED, we need to bring down the voltage at the pin 16 in GPIO controller to low status or level, and to do that we are going to use the SetGpio function.

ldr r0,=100000
bl Wait
In order to achieve the delay, we load the value of
 100000 micro seconds in r0 ,then that will make the light to flash 5 times/sec
mov r0,#16
mov r1,#1
bl SetGpio
By setting pin 16 on a high voltage (on) , the LED will be turn off and this can be done by using  SetGpio function in order to turn on GPIO pin 16.
ldr r0,=100000
bl Wait
b loop$
In order to achieve the delay, we load the value of
 100000 micro seconds in r0, then that will make the light to flash 5 times/sec.
Loop will keep running to keep the LED turning on and off until disconnecting from a proper power supply.



systemtimer's:
              

We need code to deal with the system timer, which is a counter that runs at 1MHz, and that system timer is used to count the difference between two measurements.

In order to return the value of the base address of the System Timer region into register r0, we use GetSystemTimerBase.

.globl GetTimeStamp
GetSystemTimerBase:
               ldr r0,=0x20003000
               mov pc,lr
Loading the address of the system timer (0x20003000) in r0, then move the pc to the value of the lr.

In order to get the current timestamp of the system timer, we use the GetTimeStamp. Then the return will be in register r0 and r1, while r1 is the most significant 32 bits.

.globl GetTimeStamp
GetTimeStamp:
               push {lr}
               bl GetSystemTimerBase
               ldrd r0,r1,[r0,#4]
               pop {pc}
Pushing the ( lr ),then we call the function (GetSystemTimerBase).since the value of  counter is  8 byte  and a register is 4byte,we need to store the value of the counter which is 8 byte into two registers. After that, we pop the pc.

.globl Wait
Wait:
               delay .req r2
               mov delay,r0     
               push {lr}
               bl GetTimeStamp
               start .req r3
               mov start,r0
In order to make a delay, we need to store a specified number of microseconds in r2, and then copy this waiting value from r2 into r0. Pushing the lr, then call the function of (GetTimeStamp).after assigned the register r3, copy the value of r0 into r3.

              
loop$:
                              bl GetTimeStamp
                              elapsed .req r1
                              sub elapsed,r0,start
                              cmp elapsed,delay
                              .unreq elapsed
                              bls loop$
                             
               .unreq delay
               .unreq start
               pop {pc}
Calling the function of (GetTimeStamp), then subtract r3 from r0. Now, we have a condition that compares if the delay not equals elapsed then continue, otherwise, stop. if the elapsed is less than delay ,then continue and delete alias. Finally, pop pc.



3. Results:


http://youtu.be/avyiiQwRZMs








2 comments:

  1. LuckyClub Casino Site - Lucky Club Live - Lucky Club
    Find out how to sign up for a Lucky Club account, which can then be made available at Lucky Club. Register and get the luckyclub.live latest promotions:

    ReplyDelete
  2. Casino - DrmCD
    Casino. We offer 100% deposit match bonus to all new players. Players who wish 원주 출장마사지 to 구미 출장안마 gamble 창원 출장안마 on our website 의정부 출장샵 should join this club! 남양주 출장샵 Rating: 5 · ‎2 votes

    ReplyDelete