Thursday, May 26, 2016

Pulse an IR Laser from Bare Metal on the Raspberry Pi 3



Pulsing an LED or Laser from code running on bare metal is faster than pulsing the LED or Laser from userspace on a preemptive, time sliced operating system such as Linux.  The GPIO pins on the Raspberry Pi 3 model B can be toggled via bare metal code.  The following code was cross-compiled on Linux using the latest generic ARM toolchain for the Quad Core Cortex-A53 processor on the Raspberry Pi 3 model B.


The Cortex-A53 supports the ARMv8-A Architecture.  The following commands were used to compile this code on the Raspberry Pi 3. Please note, you will need to pull bootcode.bin and start.elf from the Raspberry Pi github master branch.





$ arm-none-eabi-gcc -O2 -mfpu=neon-vfpv4 -mfloat-abi=hard -march=armv8-a -mtune=cortex-a53 \ -nostartfiles pulse.c -o kernel.elf
$ arm-none-eabi-objcopy kernel.elf -O binary kernel7.img
$ cp kernel7.img kernel.img



-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1


/* 
 * Bare Metal program for toggling a GPIO pin on the Raspberry Pi 3 Model B
 * Copyright (C) 05-26-2016  Bryan R. Hinton
 * 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 3 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, see <http://www.gnu.org/licenses/>.
 */

#define GPIO_BASE  0x3f200000 /* GPIO base address for rpi3 */
#define GPSET0_OFFSET  0x07    /* GPIO Pin Output Set 0 Offset */
#define GPCLR0_OFFSET  0x0a    /* GPIO Pin Output Clear 0 Offset */
#define GPFSEL2_OFFSET  0x02    /* GPFSEL2 Offset */
#define GPFSEL_OFFSET GPFSEL2_OFFSET
#define GPIO_PIN 22

int main(void)
{
   /* setup gpio base address */
   volatile unsigned int *gpio_base = (unsigned int *)GPIO_BASE;
  
  /* clear gpio(n) for input by setting bits (GPIO_PIN%10)*3 to 000 in GPFSEL(N)
   * where (GPIO_PIN%10)*3 is FSEL(N) or the three configuration bits for GPIO(N)
   */
  *(gpio_base + GPFSEL2_OFFSET) &= ~(7 << (GPFSEL2_OFFSET*3));
  /* set gpio(n) for output by setting bits (GPIO_PIN%10)*3 to 001 in GPFSEL(N)
   * for FSEL(N) 
   */
  *(gpio_base + GPFSEL2_OFFSET) |= (1 << ((GPFSEL2_OFFSET)*3));

   while(1) {
      /* set gpio pin */
      *(gpio_base + GPSET0_OFFSET) |= (1 << GPIO_PIN);
      /* clear gpio pin */
      *(gpio_base + GPCLR0_OFFSET) &= (1 << GPIO_PIN);
  }
}
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1

iQIcBAEBAgAGBQJXR79kAAoJEKJTsaf+3Ky+ZGcP/RwA6WePGwbcSrbFIERqIdHG
hrIA48VpwUQ/SIVvKyH93fvTzlqfrSrHzFbI9IUmqtZgWOah1X/dCfnFSrNRTn4x
6ZaZgCADlKCuarC/7tuMLkqtP6cOuvH0rWsKAtEIkmSyFPp22GttkkiHrW6ZvKZd
Z9AybVJ5XemzYVwolnkdFFb8C6oFwijaKqbkUrlHFEvvyILnsrnNhKo18iQ3dEaH
fvZCwDRMYOrHM8XqMb0ZVP27UBAuXlkaFElNeHs0iG1qmS82C7fFRwlAQe9PWo87
0xzYyeP93+pQFCo5lRtdRsm3w9R6gkhliKztyRVROiL0onzi/MGc850JX9TkWwP+
z1+uSJNf93THe9vNc9SMiuMPmx2SjCTT2WoVKFJ31K8PYvGA7nfOD/s0msV02WKr
hnPVDdQDzGSYio4uIs5J4QDvNgfFjxMZSvZvWgT/vuI3KZVxwVDU1VQxAtlx3BuA
CCBSbVa0X2Wum6XQqafZuXd11I3IIMoFXFHIH1VwLdxRYVWBtC8Bj41hR9iiOKXo
3omOCve73GozpgDMaW53BoyFqNYbyqzRN6JUtvbO8ST6a/szWARZcVOI4bwHZPIB
cSSQ75YszsNz7rSTGMdyNOy4V4e7YrfSyBn/Arc1FWmtPddU55DEjXy5mqiUIep6
lsPoPUfgviuYvzqtEVxR
=RCpP
-----END PGP SIGNATURE-----

No comments:

Post a Comment