2017年9月4日 星期一

用arecord 同時開兩個terminal來錄音

$aplay -L
看有沒有 dsnoop 相關訊息
有的話,應該可以用

terminal A
$arecord -D plug:\'dsnoop:0,0\'  aaa.wav

terminal B
$arecord -D plug:\'dsnoop:0,0\'  bbb.wav

ref : Basic Virtual PCM Devices for Playback/Capture, ALSA

2017年9月3日 星期日

Building Ubuntu rootfs for ARM

00. Download Ubuntu core
download address
01. Generate the image
sudo dd if=/dev/zero of=rootfs.img bs=512 count=1024*10
//kernel use the label linuxroot to mount the rootfs as /
sudo mkfs.ext4 -F -L linuxroot rootfs.img
sudo mount -o loop rootfs.img /mnt
02. Uncompress tar file
sudo tar zxvf ubuntu-*.tar.gz -C /mnt
03. The step is only for ARM base
sudo apt-get install qemu-user-static
sudo cp /usr/bin/qemu-arm-static /mnt/usr/bin/
04. Set up dns
sudo cp /etc/resolv.conf /mnt/etc/
05. Change root
sudo mount -t proc /proc ~/ubuntu-rootfs/proc
sudo mount -t sysfs /sys ~/ubuntu-rootfs/sys
sudo mount -o bind /dev ~/ubuntu-rootfs/dev
sudo mount -o bind /dev/pts ~/ubuntu-rootfs/dev/pts
# 進入 chroot 環境
sudo chroot /mnt
06. Install applications/tools/comands
sudo apt-get update
sudo apt-get install \
  language-pack-en-base \  
  sudo \
  ssh \
  net-tools \
  ethtool \
  wireless-tools \
  ifupdown \
  network-manager \
  iputils-ping \
  rsyslog \
  htop \
  vim \
  xinit xorg \
  alsa-utils \
  --no-install-recommends
07. Set up config
// add user
useradd username

//set up hostname
vim /etc/hostname

//add localhost
vim /etc/hosts
127.0.0.1  localhost
127.0.0.1  hostname

//Make X used by ‘anyuser’
vim /etc/X11/Xwrapper.config
allowed_users=anybody

//set up timezone
dpkg-reconfigure tzdata
//set up group for alsa
vim /etc/group
audio:x:29:pulse,username
// Set up group for fbterm
vim /etc/group
video:x:44:username
08. for Chinese
sudo sed -i '$azh_TW.UTF8 UTF-8' /var/lib/locales/supported.d/local
sudo locale-gen zh_TW.UTF-8
sudo update-locale LANG=zh_TW.UTF-8
sudo update-locale LANGUAGE=zh_TW.UTF-8

sudo apt-get -y install \
language-pack-zh-hant \
language-pack-gnome-zh-hant \
language-pack-zh-hant-base \
language-pack-gnome-zh-hant-base \
language-selector-common \
language-selector-gnome
09.
sudo umount ~/ubuntu-rootfs/proc
sudo umount ~/ubuntu-rootfs/sys
sudo umount ~/ubuntu-rootfs/dev/pts
sudo umount ~/ubuntu-rootfs/dev
ref :
1. Building Ubuntu rootfs for ARM
2. How to make a customize ubuntu rootfs image
3. 如何建構一個armhf的Ubuntu rootfs

使用mmap函式映射Memory的方式來操作GPIO

ref: Here

使用mmap函式映射Memory的方式來操作GPIO,達到高速存取的目的,比起傳統的sysfs更為有效率,使得後面其他功能更為Real time,首先創建gpio.h,宣告函式的原型
gpio.h
#include <stdint.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <sched.h>
#include <sys/mman.h>

#define MMIO_SUCCESS 0
#define MMIO_ERROR_DEVMEM -1
#define MMIO_ERROR_MMAP -2

#define BASE 0xB01B0000
#define GPIO_INC 3
#define GPIO_OUTEN 0
#define GPIO_INEN 1
#define GPIO_DAT 2
#define GPIO_LENGTH 528   

/*
ref1: kernel/arch/arm/mach-owl/include/mach/gpio.h
//GPIOA/B/C/D/E, GPIOE0~4
#define NR_OWL_GPIO
ref2: kernel/arch/arm/mach-owl/gpio.owi.h
owl_gpio_chip.ngpio
*/

int s500_mmio_init(void);
void s500_mmio_set_input(int gpio_number);
void s500_mmio_set_output(int gpio_number);
void s500_mmio_set_high(int gpio_number);
void s500_mmio_set_low(int gpio_number);
uint32_t s500_mmio_read_input(int gpio_number);

void set_max_priority(void);
void set_default_priority(void);
----------------------------------------
其中大部分都是GPIO常用的功能,和程式的Priority,其中BASE,GPIO_INC,GPIO_OUTEN,GPIO_INEN,GPIO_DAT和GPIO_LENGTH由Action S500的Datasheet來決定


gpio.c
#include "gpio.h"
volatile uint32_t* s500_mmio_gpio = NULL;

int s500_mmio_init(void) {
  if (s500_mmio_gpio == NULL) {
    int fd = open("/dev/mem", O_RDWR | O_SYNC);
    if (fd == -1) {
      // Error opening /dev/mem.  Probably not running as root.
      return MMIO_ERROR_DEVMEM;
    }
    // Map GPIO memory to location in process space.
    s500_mmio_gpio = (uint32_t*)mmap(NULL, GPIO_LENGTH, PROT_READ | PROT_WRITE, MAP_SHARED, fd, BASE);
    close(fd);
    if (s500_mmio_gpio == MAP_FAILED) {
      // Don't save the result if the memory mapping failed.
      s500_mmio_gpio = NULL;
      return MMIO_ERROR_MMAP;
    }
  }
  return MMIO_SUCCESS;
}

void s500_mmio_set_input(int gpio_number) {
  *(s500_mmio_gpio + ((gpio_number)/32)*GPIO_INC + GPIO_INEN) |= (1<<((gpio_number)%32));
  *(s500_mmio_gpio + ((gpio_number)/32)*GPIO_INC + GPIO_OUTEN) &= ~(1<<((gpio_number)%32));
}

void s500_mmio_set_output(int gpio_number) {
  *(s500_mmio_gpio + ((gpio_number)/32)*GPIO_INC + GPIO_INEN) &= ~(1<<((gpio_number)%32));
  *(s500_mmio_gpio + ((gpio_number)/32)*GPIO_INC + GPIO_OUTEN) |= (1<<((gpio_number)%32)); 
}

void s500_mmio_set_high(int gpio_number) {
  *(s500_mmio_gpio + ((gpio_number)/32)*GPIO_INC + GPIO_DAT) |= (1<<((gpio_number)%32));
}

void s500_mmio_set_low(int gpio_number) {
  *(s500_mmio_gpio + ((gpio_number)/32)*GPIO_INC + GPIO_DAT) &= ~(1<<((gpio_number)%32));
}

uint32_t s500_mmio_read_input(int gpio_number) {
  return (*(s500_mmio_gpio + ((gpio_number)/32)*GPIO_INC + GPIO_DAT) & (1<<((gpio_number)%32)) ? 1 : 0);
}

void set_max_priority(void) {
  struct sched_param sched;
  memset(&sched, 0, sizeof(sched));
  // Use FIFO scheduler with highest priority for the lowest chance of the kernel context switching.
  sched.sched_priority = sched_get_priority_max(SCHED_FIFO);
  sched_setscheduler(0, SCHED_FIFO, &sched);
}

void set_default_priority(void) {
  struct sched_param sched;
  memset(&sched, 0, sizeof(sched));
  // Go back to default scheduler with default 0 priority.
  sched.sched_priority = 0;
  sched_setscheduler(0, SCHED_OTHER, &sched);
}
---------------------------------------
main.c

#include <stdio.h>
#include <stdlib.h>
#include "gpio.h"

void main (void)
{
    if (s500_mmio_init() < 0)
        printf("error open mem!n");

    set_max_priority();
    s500_mmio_set_output(IN1);
    set_default_priority();
}
ref: 【LeMaker Guitar試用體驗】居家水族箱