Tuesday, May 31, 2016

Pulse Any GPIO Pin with the ARM System Timer from Bare Metal on the Raspberry Pi 3

650nm 5mW Red Laser Pulsed at 20Hz from Bare Metal on a Raspberry Pi 3
Sony NoIR 8mp Camera Module for Raspberry Pi Model 3 B


The ARM system timer register can be used for creating a clock to pulse the GPIO pins on the Raspberry Pi 3 at a predetermined frequency.

In the below code, a 5v, 650nm 5mW Red Laser diode is pulsed at 20Hz on GPIO pin 22 via bare metal C code on the Raspberry Pi 3.

$ arm-none-eabi-gcc -O2 -mfpu=neon-vfpv4 -mfloat-abi=hard -march=armv8-a -mtune=cortex-a53 -nostartfiles pulse.c -o kernel.elf

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

/* Pulse a GPIO pin using the ARM system timer via Bare Metal on the Raspberry Pi 3 */
 * Copyright (C) Bryan R. Hinton 05-31-2016

 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

/* for rpi3, base addresses can be calculcated by subtracting 0x3f000000 from the 
/* base address in the ARM Peripherals data sheet for the BCM2835 */
#define GPIO_BASE    0x3f200000  /* GPIO base address */
#define ARM_SYSTIMER_CLO 0x3f003004  /* ARM System Timer Counter Lower 32 bits */
#define GPSET0_OFFSET    0x07        /* GPIO Pin Output Set 0 Offset */
#define GPCLR0_OFFSET    0x0a        /* GPIO Pin Output Clear 0 Offset */
#define MAXPINCNT   3 
#define TIMEOUT   0xC350     /* 0.05 seconds = 20hz*/

int main(void)
{
   /* static const array of usable gpio pins on raspberry pi 3 */
   static const unsigned int gpiopin[MAXPINCNT] =  {22,17,4};

   /* pin index, pin 22 */
   int pinidx = 0; 

   /* lower 32 bits of current system timer value */
   unsigned int cur_tval; 

   /* setup gpio base address */
   volatile unsigned int *gpio_base = (unsigned int *)GPIO_BASE;

   /* setup system timer base address */
   volatile unsigned int *systimer_clo = (unsigned int *)ARM_SYSTIMER_CLO;

   /* set gpio(n) for input by clearing bits (GPIO_PIN%10)*3 GPFSEL(N)
    * where (GPIO_PIN%10)*3 is FSEL(N) or the three configuration bits for GPIO(N)
    * 1. Find the gpio function select(gpfsel) register for the GPIO pin.
    *  Pins 0-9 use gpfsel 0
    *  Pins 10-19 use gpfsel 1
    *  Pins 20-29 use gpfsel 2
    *  Pins 30-39 use gpfsel 3
    *  Pins 40-49 use gpfsel 4
    *  Pins 50-53 use gpfsel 5
    * 2. Set or Clear the function select bits in that register for the designated gpio pin
    *  gpio pin 5 is set for input in gpfsel 0 by clearing bits 15-17  
    *  gpio pin 5 is set for output in gpfsel 0 by setting bits 15-17 to 001  
    *  gpio pin 22 is set for input in gpfsel 2 by clearing bits 6-8  
    *  gpio pin 22 is set for output in gpfsel 2 by setting bits 6-8 to 001 */

   /*  set gpiopin[idx] for input by clearing bits k,k+1,K+2 in gpfsel n.
    *  gpfsel(2) gpiopin 22 bit string mask for gp input 11111111111111111111111000111111 (rval)
    *  gpfsel(0) gpiopin 3 bit string mask for gp input 11111111111111111111000111111111 (rval) */
    *(gpio_base + (*(gpiopin+pinidx)%10)) &= ~(7  < ((*(gpiopin+pinidx)%10)*3));

   /*  set gpiopin[idx] for output by setting bits k,k+1,k+2 to 001 in gpfsel n.
    *  gpfsel(2) gpiopin 22 bit string mask for gp output 00000000000000000000000001000000 (rval)
    *  gpfsel(2) gpiopin 3 bit string mask for gp output 00000000000000000000001000000000 (rval) */
    *(gpio_base + (*(gpiopin+pinidx)%10)) |= (1 << ((*(gpiopin+pinidx)%10)*3));
 
    /* iterate through each usable gpio pin and pulse it */
    /* one single iteration of this loop equals the frequency of the timer or 20hz for this example */
    while(1) {

 /* set gpio pin */
       *(gpio_base + GPSET0_OFFSET) |= (1 << (*(gpiopin+pinidx)));

 for(;;) {
  /* prefetch current lower 32 bit val of read only timer register */
  cur_tval = *(systimer_clo); 
  /* if timer val was just reset, loop, 1/2*period or half cycle mark */
  if((cur_tval & TIMEOUT) == TIMEOUT)
   break;
 }
        /* clear gpio pin */
 *(gpio_base + GPCLR0_OFFSET) &= (1 << (*(gpiopin+pinidx)));

 for(;;) {
  /* prefetch current lower 32 bit val of read only timer register */
  cur_tval = *(systimer_clo); 
  /* if timer val is zero, loop, 1/2*period or half cycle mark */
  if((cur_tval & TIMEOUT) == 0)
   break;
 }
    }
}
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1

iQIcBAEBAgAGBQJXTml/AAoJEPbndIT4b5KAHuoQALeHhpc32TSfKt632Vwn92Zv
cd93o6a9lnQLgBLYUCfW1y23UUgoUGgd7aXm2ssUjt9vwdqj5AZSq7lNcNdOb5nM
PR81A1VVu8QuOj/gI6sMOLotcbI70hFZWqD3x8CNTYQXTz1J8wPae85oY3rEmSxz
a8U43QBpx98RcHZIsc52MiPDzPTiqBSzaPsJMFQqlUDSo9T8G1J2BqLnL35dI1Yw
7jr8vZGNDHcujLFIIt/GY24M71Cyw1J+VqxAguvgzebc+pj/4kKTG8AKXueSed0A
ztE5DOQDOqs+HmNEkF/LU+SASvQz3czl0dOhIbhO+HFVDjlX7Qv7I/iLwQ3hWbef
XROdoP2wWRR8Bs7fFTKtaQ5+32O31xdovwtmUXCwGT4i0cckD/97LND8ntdpiA8n
w6ek19QZvxVIeZ5Mm4H7C/zbLN3n6OEstfxRzHpmgqntOcrCSuKhtx5em6XGfhLT
uJv4Xgo35eh5aCKV2GsOxLE9eymHVMQpV6GQGCIeMCIxawmlRu2k/whpBR/u1F/l
4CyYhXHoCpEP6Lr3YFiZPbYueRySo9uPkz77u/RhmnMamSytnGCiyYr5BhpeZYMu
OwtjdN8vPFHged4hroDAC4RKdGD/gVPKqvlZ9zgCMIvlzLWNgJdev/iVXqOOf1FW
ASSma5+BFeK5VUL1ITjI
=Wxx/
-----END PGP SIGNATURE-----

No comments:

Post a Comment