Make the program more resilient to different configurations wrt the mailbox device

master
Christophe Jacquet 2015-09-06 20:02:31 +00:00
rodzic 293b8f2000
commit c0d45323e4
3 zmienionych plików z 213 dodań i 191 usunięć

Wyświetl plik

@ -4,14 +4,14 @@ All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
@ -34,6 +34,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <stdint.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include "mailbox.h"
@ -41,41 +42,41 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
void *mapmem(unsigned base, unsigned size)
{
int mem_fd;
unsigned offset = base % PAGE_SIZE;
base = base - offset;
/* open /dev/mem */
if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) {
printf("can't open /dev/mem\nThis program should be run as root. Try prefixing command with: sudo\n");
exit (-1);
}
void *mem = mmap(
0,
size,
PROT_READ|PROT_WRITE,
MAP_SHARED/*|MAP_FIXED*/,
mem_fd,
base);
int mem_fd;
unsigned offset = base % PAGE_SIZE;
base = base - offset;
/* open /dev/mem */
if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) {
printf("can't open /dev/mem\nThis program should be run as root. Try prefixing command with: sudo\n");
exit (-1);
}
void *mem = mmap(
0,
size,
PROT_READ|PROT_WRITE,
MAP_SHARED/*|MAP_FIXED*/,
mem_fd,
base);
#ifdef DEBUG
printf("base=0x%x, mem=%p\n", base, mem);
printf("base=0x%x, mem=%p\n", base, mem);
#endif
if (mem == MAP_FAILED) {
printf("mmap error %d\n", (int)mem);
exit (-1);
}
close(mem_fd);
return (char *)mem + offset;
if (mem == MAP_FAILED) {
printf("mmap error %d\n", (int)mem);
exit (-1);
}
close(mem_fd);
return (char *)mem + offset;
}
void *unmapmem(void *addr, unsigned size)
{
int s = munmap(addr, size);
if (s != 0) {
printf("munmap error %d\n", s);
exit (-1);
}
int s = munmap(addr, size);
if (s != 0) {
printf("munmap error %d\n", s);
exit (-1);
}
return NULL;
return NULL;
}
/*
@ -84,177 +85,192 @@ void *unmapmem(void *addr, unsigned size)
static int mbox_property(int file_desc, void *buf)
{
int ret_val = ioctl(file_desc, IOCTL_MBOX_PROPERTY, buf);
int ret_val = ioctl(file_desc, IOCTL_MBOX_PROPERTY, buf);
if (ret_val < 0) {
printf("ioctl_set_msg failed:%d\n", ret_val);
}
if (ret_val < 0) {
printf("ioctl_set_msg failed:%d\n", ret_val);
}
#ifdef DEBUG
unsigned *p = buf; int i; unsigned size = *(unsigned *)buf;
for (i=0; i<size/4; i++)
printf("%04x: 0x%08x\n", i*sizeof *p, p[i]);
unsigned *p = buf; int i; unsigned size = *(unsigned *)buf;
for (i=0; i<size/4; i++)
printf("%04x: 0x%08x\n", i*sizeof *p, p[i]);
#endif
return ret_val;
return ret_val;
}
unsigned mem_alloc(int file_desc, unsigned size, unsigned align, unsigned flags)
{
int i=0;
unsigned p[32];
p[i++] = 0; // size
p[i++] = 0x00000000; // process request
int i=0;
unsigned p[32];
p[i++] = 0; // size
p[i++] = 0x00000000; // process request
p[i++] = 0x3000c; // (the tag id)
p[i++] = 12; // (size of the buffer)
p[i++] = 12; // (size of the data)
p[i++] = size; // (num bytes? or pages?)
p[i++] = align; // (alignment)
p[i++] = flags; // (MEM_FLAG_L1_NONALLOCATING)
p[i++] = 0x3000c; // (the tag id)
p[i++] = 12; // (size of the buffer)
p[i++] = 12; // (size of the data)
p[i++] = size; // (num bytes? or pages?)
p[i++] = align; // (alignment)
p[i++] = flags; // (MEM_FLAG_L1_NONALLOCATING)
p[i++] = 0x00000000; // end tag
p[0] = i*sizeof *p; // actual size
p[i++] = 0x00000000; // end tag
p[0] = i*sizeof *p; // actual size
mbox_property(file_desc, p);
return p[5];
if(mbox_property(file_desc, p) < 0) return 0;
return p[5];
}
unsigned mem_free(int file_desc, unsigned handle)
{
int i=0;
unsigned p[32];
p[i++] = 0; // size
p[i++] = 0x00000000; // process request
int i=0;
unsigned p[32];
p[i++] = 0; // size
p[i++] = 0x00000000; // process request
p[i++] = 0x3000f; // (the tag id)
p[i++] = 4; // (size of the buffer)
p[i++] = 4; // (size of the data)
p[i++] = handle;
p[i++] = 0x3000f; // (the tag id)
p[i++] = 4; // (size of the buffer)
p[i++] = 4; // (size of the data)
p[i++] = handle;
p[i++] = 0x00000000; // end tag
p[0] = i*sizeof *p; // actual size
p[i++] = 0x00000000; // end tag
p[0] = i*sizeof *p; // actual size
mbox_property(file_desc, p);
return p[5];
if(mbox_property(file_desc, p) < 0) return 0;
return p[5];
}
unsigned mem_lock(int file_desc, unsigned handle)
{
int i=0;
unsigned p[32];
p[i++] = 0; // size
p[i++] = 0x00000000; // process request
int i=0;
unsigned p[32];
p[i++] = 0; // size
p[i++] = 0x00000000; // process request
p[i++] = 0x3000d; // (the tag id)
p[i++] = 4; // (size of the buffer)
p[i++] = 4; // (size of the data)
p[i++] = handle;
p[i++] = 0x3000d; // (the tag id)
p[i++] = 4; // (size of the buffer)
p[i++] = 4; // (size of the data)
p[i++] = handle;
p[i++] = 0x00000000; // end tag
p[0] = i*sizeof *p; // actual size
p[i++] = 0x00000000; // end tag
p[0] = i*sizeof *p; // actual size
mbox_property(file_desc, p);
return p[5];
if(mbox_property(file_desc, p) < 0) return 0;
return p[5];
}
unsigned mem_unlock(int file_desc, unsigned handle)
{
int i=0;
unsigned p[32];
p[i++] = 0; // size
p[i++] = 0x00000000; // process request
int i=0;
unsigned p[32];
p[i++] = 0; // size
p[i++] = 0x00000000; // process request
p[i++] = 0x3000e; // (the tag id)
p[i++] = 4; // (size of the buffer)
p[i++] = 4; // (size of the data)
p[i++] = handle;
p[i++] = 0x3000e; // (the tag id)
p[i++] = 4; // (size of the buffer)
p[i++] = 4; // (size of the data)
p[i++] = handle;
p[i++] = 0x00000000; // end tag
p[0] = i*sizeof *p; // actual size
p[i++] = 0x00000000; // end tag
p[0] = i*sizeof *p; // actual size
mbox_property(file_desc, p);
return p[5];
if(mbox_property(file_desc, p) < 0) return 0;
return p[5];
}
unsigned execute_code(int file_desc, unsigned code, unsigned r0, unsigned r1, unsigned r2, unsigned r3, unsigned r4, unsigned r5)
{
int i=0;
unsigned p[32];
p[i++] = 0; // size
p[i++] = 0x00000000; // process request
int i=0;
unsigned p[32];
p[i++] = 0; // size
p[i++] = 0x00000000; // process request
p[i++] = 0x30010; // (the tag id)
p[i++] = 28; // (size of the buffer)
p[i++] = 28; // (size of the data)
p[i++] = code;
p[i++] = r0;
p[i++] = r1;
p[i++] = r2;
p[i++] = r3;
p[i++] = r4;
p[i++] = r5;
p[i++] = 0x30010; // (the tag id)
p[i++] = 28; // (size of the buffer)
p[i++] = 28; // (size of the data)
p[i++] = code;
p[i++] = r0;
p[i++] = r1;
p[i++] = r2;
p[i++] = r3;
p[i++] = r4;
p[i++] = r5;
p[i++] = 0x00000000; // end tag
p[0] = i*sizeof *p; // actual size
p[i++] = 0x00000000; // end tag
p[0] = i*sizeof *p; // actual size
mbox_property(file_desc, p);
return p[5];
if(mbox_property(file_desc, p) < 0) return 0;
return p[5];
}
unsigned qpu_enable(int file_desc, unsigned enable)
{
int i=0;
unsigned p[32];
int i=0;
unsigned p[32];
p[i++] = 0; // size
p[i++] = 0x00000000; // process request
p[i++] = 0; // size
p[i++] = 0x00000000; // process request
p[i++] = 0x30012; // (the tag id)
p[i++] = 4; // (size of the buffer)
p[i++] = 4; // (size of the data)
p[i++] = enable;
p[i++] = 0x30012; // (the tag id)
p[i++] = 4; // (size of the buffer)
p[i++] = 4; // (size of the data)
p[i++] = enable;
p[i++] = 0x00000000; // end tag
p[0] = i*sizeof *p; // actual size
p[i++] = 0x00000000; // end tag
p[0] = i*sizeof *p; // actual size
mbox_property(file_desc, p);
return p[5];
if(mbox_property(file_desc, p) < 0) return 0;
return p[5];
}
unsigned execute_qpu(int file_desc, unsigned num_qpus, unsigned control, unsigned noflush, unsigned timeout) {
int i=0;
unsigned p[32];
int i=0;
unsigned p[32];
p[i++] = 0; // size
p[i++] = 0x00000000; // process request
p[i++] = 0x30011; // (the tag id)
p[i++] = 16; // (size of the buffer)
p[i++] = 16; // (size of the data)
p[i++] = num_qpus;
p[i++] = control;
p[i++] = noflush;
p[i++] = timeout; // ms
p[i++] = 0; // size
p[i++] = 0x00000000; // process request
p[i++] = 0x30011; // (the tag id)
p[i++] = 16; // (size of the buffer)
p[i++] = 16; // (size of the data)
p[i++] = num_qpus;
p[i++] = control;
p[i++] = noflush;
p[i++] = timeout; // ms
p[i++] = 0x00000000; // end tag
p[0] = i*sizeof *p; // actual size
p[i++] = 0x00000000; // end tag
p[0] = i*sizeof *p; // actual size
mbox_property(file_desc, p);
return p[5];
if(mbox_property(file_desc, p) < 0) return 0;
return p[5];
}
int mbox_open() {
int file_desc;
int file_desc;
// open a char device file used for communicating with kernel mbox driver
file_desc = open(DEVICE_FILE_NAME, 0);
if (file_desc < 0) {
printf("Can't open device file: %s\n", DEVICE_FILE_NAME);
printf("Try creating a device file with: sudo mknod %s c %d 0\n", DEVICE_FILE_NAME, MAJOR_NUM);
exit(-1);
}
return file_desc;
// Open a char device file used for communicating with kernel mbox driver.
file_desc = open(DEVICE_FILE_NAME, 0);
if(file_desc >= 0) {
printf("Using mbox device " DEVICE_FILE_NAME ".\n");
return file_desc;
}
// Try to create one
unlink(LOCAL_DEVICE_FILE_NAME);
if(mknod(LOCAL_DEVICE_FILE_NAME, S_IFCHR|0600, makedev(MAJOR_NUM_A, 0)) >= 0 &&
(file_desc = open(LOCAL_DEVICE_FILE_NAME, 0)) >= 0) {
printf("Using local mbox device file with major %d.\n", MAJOR_NUM_A);
return file_desc;
}
unlink(LOCAL_DEVICE_FILE_NAME);
if(mknod(LOCAL_DEVICE_FILE_NAME, S_IFCHR|0600, makedev(MAJOR_NUM_B, 0)) >= 0 &&
(file_desc = open(LOCAL_DEVICE_FILE_NAME, 0)) >= 0) {
printf("Using local mbox device file with major %d.\n", MAJOR_NUM_B);
return file_desc;
}
return -1;
}
void mbox_close(int file_desc) {
close(file_desc);
close(file_desc);
}

Wyświetl plik

@ -27,9 +27,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <linux/ioctl.h>
#define MAJOR_NUM 100
#define IOCTL_MBOX_PROPERTY _IOWR(MAJOR_NUM, 0, char *)
#define DEVICE_FILE_NAME "mbox"
// Newer kernels (>= 4.1) use major 249, older ones major 100.
#define MAJOR_NUM_A 249
#define MAJOR_NUM_B 100
#define IOCTL_MBOX_PROPERTY _IOWR(MAJOR_NUM_B, 0, char *)
#define DEVICE_FILE_NAME "/dev/vcio"
#define LOCAL_DEVICE_FILE_NAME "mbox"
int mbox_open();
void mbox_close(int file_desc);

Wyświetl plik

@ -109,7 +109,7 @@
#include "control_pipe.h"
#include "mailbox.h"
#define MBFILE DEVICE_FILE_NAME /* From mailbox.h */
#define MBFILE DEVICE_FILE_NAME /* From mailbox.h */
#if (RASPI)==1
#define PERIPH_VIRT_BASE 0x20000000
@ -140,24 +140,24 @@
#define DMA_CONBLK_AD (0x04/4)
#define DMA_DEBUG (0x20/4)
#define DMA_BASE_OFFSET 0x00007000
#define DMA_BASE_OFFSET 0x00007000
#define DMA_LEN 0x24
#define PWM_BASE_OFFSET 0x0020C000
#define PWM_LEN 0x28
#define CLK_BASE_OFFSET 0x00101000
#define CLK_LEN 0xA8
#define GPIO_BASE_OFFSET 0x00200000
#define GPIO_LEN 0x100
#define PWM_BASE_OFFSET 0x0020C000
#define PWM_LEN 0x28
#define CLK_BASE_OFFSET 0x00101000
#define CLK_LEN 0xA8
#define GPIO_BASE_OFFSET 0x00200000
#define GPIO_LEN 0x100
#define DMA_VIRT_BASE (PERIPH_VIRT_BASE + DMA_BASE_OFFSET)
#define PWM_VIRT_BASE (PERIPH_VIRT_BASE + PWM_BASE_OFFSET)
#define CLK_VIRT_BASE (PERIPH_VIRT_BASE + CLK_BASE_OFFSET)
#define GPIO_VIRT_BASE (PERIPH_VIRT_BASE + GPIO_BASE_OFFSET)
#define PCM_VIRT_BASE (PERIPH_VIRT_BASE + PCM_BASE_OFFSET)
#define DMA_VIRT_BASE (PERIPH_VIRT_BASE + DMA_BASE_OFFSET)
#define PWM_VIRT_BASE (PERIPH_VIRT_BASE + PWM_BASE_OFFSET)
#define CLK_VIRT_BASE (PERIPH_VIRT_BASE + CLK_BASE_OFFSET)
#define GPIO_VIRT_BASE (PERIPH_VIRT_BASE + GPIO_BASE_OFFSET)
#define PCM_VIRT_BASE (PERIPH_VIRT_BASE + PCM_BASE_OFFSET)
#define PWM_PHYS_BASE (PERIPH_PHYS_BASE + PWM_BASE_OFFSET)
#define PCM_PHYS_BASE (PERIPH_PHYS_BASE + PCM_BASE_OFFSET)
#define GPIO_PHYS_BASE (PERIPH_PHYS_BASE + GPIO_BASE_OFFSET)
#define PWM_PHYS_BASE (PERIPH_PHYS_BASE + PWM_BASE_OFFSET)
#define PCM_PHYS_BASE (PERIPH_PHYS_BASE + PCM_BASE_OFFSET)
#define GPIO_PHYS_BASE (PERIPH_PHYS_BASE + GPIO_BASE_OFFSET)
#define PWM_CTL (0x00/4)
@ -201,12 +201,12 @@ typedef struct {
static struct {
int handle; /* From mbox_open() */
unsigned mem_ref; /* From mem_alloc() */
unsigned bus_addr; /* From mem_lock() */
uint8_t *virt_addr; /* From mapmem() */
int handle; /* From mbox_open() */
unsigned mem_ref; /* From mem_alloc() */
unsigned bus_addr; /* From mem_lock() */
uint8_t *virt_addr; /* From mapmem() */
} mbox;
static volatile uint32_t *pwm_reg;
@ -278,9 +278,9 @@ fatal(char *fmt, ...)
static uint32_t
mem_virt_to_phys(void *virt)
{
uint32_t offset = (uint8_t *)virt - mbox.virt_addr;
uint32_t offset = (uint8_t *)virt - mbox.virt_addr;
return mbox.bus_addr + offset;
return mbox.bus_addr + offset;
}
static uint32_t
@ -327,22 +327,25 @@ int tx(uint32_t carrier_freq, char *audio_file, uint16_t pi, char *ps, char *rt,
clk_reg = map_peripheral(CLK_VIRT_BASE, CLK_LEN);
gpio_reg = map_peripheral(GPIO_VIRT_BASE, GPIO_LEN);
/* Use the mailbox interface to the VC to ask for physical memory */
unlink(MBFILE);
if (mknod(MBFILE, S_IFCHR|0600, makedev(100, 0)) < 0)
fatal("Failed to create mailbox device.\n");
mbox.handle = mbox_open();
if (mbox.handle < 0)
fatal("Failed to open mailbox.\n");
printf("Allocating physical memory: size = %d ", NUM_PAGES * 4096);
mbox.mem_ref = mem_alloc(mbox.handle, NUM_PAGES * 4096, 4096, MEM_FLAG);
/* TODO: How do we know that succeeded? */
printf("mem_ref = %u ", mbox.mem_ref);
mbox.bus_addr = mem_lock(mbox.handle, mbox.mem_ref);
printf("bus_addr = %x ", mbox.bus_addr);
mbox.virt_addr = mapmem(BUS_TO_PHYS(mbox.bus_addr), NUM_PAGES * 4096);
printf("virt_addr = %p\n", mbox.virt_addr);
// Use the mailbox interface to the VC to ask for physical memory.
mbox.handle = mbox_open();
if (mbox.handle < 0)
fatal("Failed to open mailbox. Check kernel support for vcio / BCM2708 mailbox.\n");
printf("Allocating physical memory: size = %d ", NUM_PAGES * 4096);
if(! (mbox.mem_ref = mem_alloc(mbox.handle, NUM_PAGES * 4096, 4096, MEM_FLAG))) {
fatal("Could not allocate memory.\n");
}
// TODO: How do we know that succeeded?
printf("mem_ref = %u ", mbox.mem_ref);
if(! (mbox.bus_addr = mem_lock(mbox.handle, mbox.mem_ref))) {
fatal("Could not lock memory.\n");
}
printf("bus_addr = %x ", mbox.bus_addr);
if(! (mbox.virt_addr = mapmem(BUS_TO_PHYS(mbox.bus_addr), NUM_PAGES * 4096))) {
fatal("Could not map memory.\n");
}
printf("virt_addr = %p\n", mbox.virt_addr);
// GPIO4 needs to be ALT FUNC 0 to output the clock
gpio_reg[GPFSEL0] = (gpio_reg[GPFSEL0] & ~(7 << 12)) | (4 << 12);