From 07c776f634f3c5ba536490763fbf7cc5e9f94572 Mon Sep 17 00:00:00 2001 From: Chris Hager Date: Thu, 2 Jun 2016 21:46:25 +0200 Subject: [PATCH] v2.0.0-beta1: Merged changes from Andy Baker and Reik Hua for compatibility with Pi 0, 2 and 3 --- README.rst | 17 +++ VERSION | 2 +- debian/changelog | 6 + documentation/source/conf.py | 2 +- documentation/source/index.rst | 11 +- fabfile.py | 3 +- setup.py | 4 +- source/RPIO/PWM/__init__.py | 2 +- source/RPIO/__init__.py | 4 +- source/c_gpio/c_gpio.c | 4 +- source/c_gpio/cpuinfo.c | 8 +- source/c_gpio/py_gpio.c | 4 +- source/c_pwm/Makefile | 9 +- source/c_pwm/mailbox.c | 261 +++++++++++++++++++++++++++++++++ source/c_pwm/mailbox.h | 47 ++++++ source/c_pwm/pwm.c | 168 +++++++++++---------- source/c_pwm/pwm_py.c | 3 +- source/scripts/rpio | 2 +- source/scripts/rpio-curses | 2 +- version_update.sh | 4 +- 20 files changed, 462 insertions(+), 101 deletions(-) create mode 100755 source/c_pwm/mailbox.c create mode 100755 source/c_pwm/mailbox.h diff --git a/README.rst b/README.rst index e0a052b..d94646f 100644 --- a/README.rst +++ b/README.rst @@ -55,9 +55,26 @@ License +Building for Development +------------------------ + +On the Raspberry Pi: + + sudo apt-get install python-dev python3 python3.2-dev + +On the developer machine:: + + fab upload + fab build_gpio + fab build_pwm + + Special Thanks -------------- + Andy Baker and Reik Hua for supplying compatibility updates for the + Raspberry Pi 0, 2 and 3. + `csegit `_, `waveform80 `_, `nils-werner `_, `friedcell `_, `zejn `_, `dbeal `_, diff --git a/VERSION b/VERSION index 5712157..dfdc755 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.10.1 +2.0.0-beta1 diff --git a/debian/changelog b/debian/changelog index 33666c2..2a9b18c 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +rpio (2.0.0-beta1) unstable; urgency=low + + * Support for Raspberry Pi 0, 2, 3 (thanks to Andy Baker and Reik Hua) + + -- Chris Hager Thu, 02 Jun 2016 21:32:58 +0100 + rpio (0.10.1) unstable; urgency=low * Updated debian/control Standards-Version to 3.9.3.1 diff --git a/documentation/source/conf.py b/documentation/source/conf.py index 3db1c71..7f8e307 100644 --- a/documentation/source/conf.py +++ b/documentation/source/conf.py @@ -48,7 +48,7 @@ # built documents. # # The short X.Y version. -version = '0.10.1' +version = '2.0.0-beta1' # The full version, including alpha/beta/rc tags. release = version diff --git a/documentation/source/index.rst b/documentation/source/index.rst index 04b804d..58808fb 100644 --- a/documentation/source/index.rst +++ b/documentation/source/index.rst @@ -31,6 +31,7 @@ Documentation News ---- +* v2.0.0-beta1: RPIO works with Raspberry Pi Zero, 2 and 3 (Thanks to Andy Baker and Reik Hua) * v0.9.2: :ref:`PWM via DMA ` * v0.8.4: ``rpio-curses`` * v0.8.2: Socket server callbacks with :ref:`RPIO.add_tcp_callback(port, callback, threaded_callback=False) ` @@ -113,6 +114,10 @@ License & Copyright Changes ------- +* v2.0.0-beta1 + + * RPIO works with Raspberry Pi Zero, 2 and 3 (Thanks to Andy Baker and Reik Hua) + * v0.11.0 * Merged various pull requests: Arch package link, bugfixes, allow Pi to control @@ -157,9 +162,9 @@ Changes * v0.8.2 * Added TCP socket callbacks - * ``RPIO`` does not auto-clean interfaces on exceptions anymore, but will auto-clean them + * ``RPIO`` does not auto-clean interfaces on exceptions anymore, but will auto-clean them as needed. This means you should now call ``RPIO.cleanup_interrupts()`` to properly close - the sockets and unexport the interfaces. + the sockets and unexport the interfaces. * Renamed ``RPIO.rpi_sysinfo()`` to ``RPIO.sysinfo()`` @@ -176,7 +181,7 @@ Changes * v0.7.1 - + * Refactoring and cleanup of c_gpio * Added new constants and methods (see documentation above) * Bugfixes diff --git a/fabfile.py b/fabfile.py index d120887..c2560a2 100644 --- a/fabfile.py +++ b/fabfile.py @@ -14,7 +14,8 @@ # Set default hosts if not env.hosts: - env.hosts = ["raspberry_dev_local"] + # env.hosts = ["raspberry_dev_local"] + env.hosts = ["omxdev"] def _get_cur_version(): diff --git a/setup.py b/setup.py index 4a9b4a4..bf30dad 100644 --- a/setup.py +++ b/setup.py @@ -8,14 +8,14 @@ def read(fname): setup( name="RPIO", - version="0.10.1", + version="2.0.0-beta1", package_dir={"": "source"}, packages=['RPIO', 'RPIO.PWM'], ext_modules=[ Extension('RPIO._GPIO', ['source/c_gpio/py_gpio.c', 'source/c_gpio/c_gpio.c', 'source/c_gpio/cpuinfo.c'], extra_compile_args=["-Wno-error=declaration-after-statement"]), - Extension('RPIO.PWM._PWM', ['source/c_pwm/pwm.c', + Extension('RPIO.PWM._PWM', ['source/c_pwm/pwm.c', 'source/c_pwm/mailbox.c', 'source/c_pwm/pwm_py.c'], extra_compile_args=["-Wno-error=declaration-after-statement"])], scripts=["source/scripts/rpio", "source/scripts/rpio-curses"], diff --git a/source/RPIO/PWM/__init__.py b/source/RPIO/PWM/__init__.py index e664b67..181a09f 100644 --- a/source/RPIO/PWM/__init__.py +++ b/source/RPIO/PWM/__init__.py @@ -206,7 +206,7 @@ def set_servo(self, gpio, pulse_width_us): if _subcycle_us != self._subcycle_time_us: raise AttributeError(("Error: DMA channel %s is setup with a " "subcycle_time of %sus (instead of %sus)") % \ - (self._dma_channel, _subcycle_us, + (self._dma_channel, _subcycle_us, self._subcycle_time_us)) else: init_channel(self._dma_channel, self._subcycle_time_us) diff --git a/source/RPIO/__init__.py b/source/RPIO/__init__.py index ef28d73..fae1705 100644 --- a/source/RPIO/__init__.py +++ b/source/RPIO/__init__.py @@ -116,7 +116,7 @@ def socket_callback(socket, val): from RPIO._RPIO import Interruptor -VERSION = "0.10.1" +VERSION = "2.0.0-beta1" # Exposing constants from RPi.GPIO VERSION_GPIO = _GPIO.VERSION_GPIO @@ -266,7 +266,7 @@ def cleanup_interrupts(): """ Removes all callbacks and closes used GPIO interfaces and sockets. After this you'll need to re-add the interrupt callbacks before waiting for - interrupts again. Since RPIO v0.10.1 this is done automatically on exit. + interrupts again. Since RPIO v2.0.0-beta1 this is done automatically on exit. """ _rpio.cleanup_interrupts() diff --git a/source/c_gpio/c_gpio.c b/source/c_gpio/c_gpio.c index c39385a..25a04ca 100644 --- a/source/c_gpio/c_gpio.c +++ b/source/c_gpio/c_gpio.c @@ -79,7 +79,7 @@ setup(void) if ((uint32_t)gpio_mem % PAGE_SIZE) gpio_mem += PAGE_SIZE - ((uint32_t)gpio_mem % PAGE_SIZE); - gpio_map = (uint32_t *)mmap( (void *)gpio_mem, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FIXED, mem_fd, GPIO_BASE); + gpio_map = (uint32_t *)mmap( (caddr_t)gpio_mem, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FIXED, mem_fd, GPIO_BASE); if ((uint32_t)gpio_map < 0) return SETUP_MMAP_FAIL; @@ -163,5 +163,5 @@ void cleanup(void) { // fixme - set all gpios back to input - munmap((void *)gpio_map, BLOCK_SIZE); + munmap((caddr_t)gpio_map, BLOCK_SIZE); } diff --git a/source/c_gpio/cpuinfo.c b/source/c_gpio/cpuinfo.c index 10de16e..922fc5f 100644 --- a/source/c_gpio/cpuinfo.c +++ b/source/c_gpio/cpuinfo.c @@ -35,7 +35,7 @@ // revision_hex will be four characters revision id (eg. '0004'), // the over-voltage header, if present, is removed (since it is // not consistently present on all overclocked boards). -int +int get_cpuinfo_revision(char *revision_hex) { FILE *fp; @@ -49,7 +49,11 @@ get_cpuinfo_revision(char *revision_hex) while(!feof(fp)) { fgets(buffer, sizeof(buffer) , fp); sscanf(buffer, "Hardware : %s", hardware); - if (strcmp(hardware, "BCM2708") == 0) + if (strcmp(hardware, "BCM2708") == 0|| + strcmp(hardware, "BCM2709") == 0|| + strcmp(hardware, "BCM2835") == 0|| + strcmp(hardware, "BCM2836") == 0 + ) rpi_found = 1; sscanf(buffer, "Revision : %s", revision_hex); } diff --git a/source/c_gpio/py_gpio.c b/source/c_gpio/py_gpio.c index f6fc99f..2e8ab7b 100644 --- a/source/c_gpio/py_gpio.c +++ b/source/c_gpio/py_gpio.c @@ -23,7 +23,7 @@ * http://pythonhosted.org/RPIO * * py_gpio.c is based on RPi.GPIO by Ben Croston, and provides a Python interface to - * interact with the gpio-related C methods. + * interact with the gpio-related C methods. */ #include "Python.h" #include "c_gpio.h" @@ -547,7 +547,7 @@ PyMODINIT_FUNC init_GPIO(void) rpi_revision_hex = Py_BuildValue("s", revision_hex); PyModule_AddObject(module, "RPI_REVISION_HEX", rpi_revision_hex); - version = Py_BuildValue("s", "0.10.1/0.4.2a"); + version = Py_BuildValue("s", "2.0.0-beta1/0.4.2a"); PyModule_AddObject(module, "VERSION_GPIO", version); // set up mmaped areas diff --git a/source/c_pwm/Makefile b/source/c_pwm/Makefile index 9fca73c..66dd765 100644 --- a/source/c_pwm/Makefile +++ b/source/c_pwm/Makefile @@ -5,21 +5,24 @@ pwm: py2.6: mkdir -p build + gcc -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -fPIC -I/usr/include/python2.6 -c mailbox.c -o build/mailbox.o gcc -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -fPIC -I/usr/include/python2.6 -c pwm.c -o build/pwm.o gcc -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -fPIC -I/usr/include/python2.6 -c pwm_py.c -o build/pwm_py.o - gcc -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions -Wl,-z,relro build/pwm.o build/pwm_py.o -o _PWM.so + gcc -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions -Wl,-z,relro build/mailbox.o build/pwm.o build/pwm_py.o -o _PWM.so rm -rf build py2.7: mkdir -p build + gcc -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -fPIC -I/usr/include/python2.7 -c mailbox.c -o build/mailbox.o gcc -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -fPIC -I/usr/include/python2.7 -c pwm.c -o build/pwm.o gcc -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -fPIC -I/usr/include/python2.7 -c pwm_py.c -o build/pwm_py.o - gcc -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions -Wl,-z,relro build/pwm.o build/pwm_py.o -o _PWM.so + gcc -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions -Wl,-z,relro build/mailbox.o build/pwm.o build/pwm_py.o -o _PWM.so rm -rf build py3.2: mkdir -p build + gcc -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -fPIC -I/usr/include/python3.2mu -c mailbox.c -o build/mailbox.o gcc -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -fPIC -I/usr/include/python3.2mu -c pwm.c -o build/pwm.o gcc -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -fPIC -I/usr/include/python3.2mu -c pwm_py.c -o build/pwm_py.o - gcc -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions -Wl,-z,relro build/pwm.o build/pwm_py.o -o _PWM.so + gcc -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions -Wl,-z,relro build/mailbox.o build/pwm.o build/pwm_py.o -o _PWM.so rm -rf build diff --git a/source/c_pwm/mailbox.c b/source/c_pwm/mailbox.c new file mode 100755 index 0000000..139482a --- /dev/null +++ b/source/c_pwm/mailbox.c @@ -0,0 +1,261 @@ +/* +Copyright (c) 2012, Broadcom Europe Ltd. +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. + +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 +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mailbox.h" + +#define PAGE_SIZE (4*1024) + +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); +#ifdef DEBUG + 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; +} + +void *unmapmem(void *addr, unsigned size) +{ + int s = munmap(addr, size); + if (s != 0) { + printf("munmap error %d\n", s); + exit (-1); + } + + return NULL; +} + +/* + * use ioctl to send mbox property message + */ + +static int mbox_property(int file_desc, void *buf) +{ + int ret_val = ioctl(file_desc, IOCTL_MBOX_PROPERTY, buf); + + 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 + +#define MAJOR_NUM 100 +#define IOCTL_MBOX_PROPERTY _IOWR(MAJOR_NUM, 0, char *) +#define DEVICE_FILE_NAME "/dev/vcio-mb" + +int mbox_open(); +void mbox_close(int file_desc); + +unsigned get_version(int file_desc); +unsigned mem_alloc(int file_desc, unsigned size, unsigned align, unsigned flags); +unsigned mem_free(int file_desc, unsigned handle); +unsigned mem_lock(int file_desc, unsigned handle); +unsigned mem_unlock(int file_desc, unsigned handle); +void *mapmem(unsigned base, unsigned size); +void *unmapmem(void *addr, unsigned size); + +unsigned execute_code(int file_desc, unsigned code, unsigned r0, unsigned r1, unsigned r2, unsigned r3, unsigned r4, unsigned r5); +unsigned execute_qpu(int file_desc, unsigned num_qpus, unsigned control, unsigned noflush, unsigned timeout); +unsigned qpu_enable(int file_desc, unsigned enable); diff --git a/source/c_pwm/pwm.c b/source/c_pwm/pwm.c index 3b9db7a..08fa381 100644 --- a/source/c_pwm/pwm.c +++ b/source/c_pwm/pwm.c @@ -85,7 +85,8 @@ #include #include #include "pwm.h" - +#include "mailbox.h" +#define MBFILE DEVICE_FILE_NAME /* From mailbox.h */ // 15 DMA channels are usable on the RPi (0..14) #define DMA_CHANNELS 15 @@ -93,17 +94,42 @@ #define PAGE_SIZE 4096 #define PAGE_SHIFT 12 +static struct { + int handle; /* From mbox_open() */ + + uint8_t *virt_addr; /* From mapmem() */ +} mbox; +#define BUS_TO_PHYS(x) ((x)&~0xC0000000) +static uint32_t mem_flag = 0x0c; + // Memory Addresses -#define DMA_BASE 0x20007000 + +static volatile unsigned int BCM2708_PERI_BASE = 0x20000000 ; //for PI1 + +static volatile unsigned int periph_phys_base = 0x7e000000; +static volatile unsigned int periph_virt_base = 0x20000000; + +#define DMA_BASE_OFFSET 0x00007000 +#define PWM_BASE_OFFSET 0x0020C000 +#define CLK_BASE_OFFSET 0x00101000 +#define GPIO_BASE_OFFSET 0x00200000 +#define PCM_BASE_OFFSET 0x00203000 + +#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 DMA_CHANNEL_INC 0x100 #define DMA_LEN 0x24 -#define PWM_BASE 0x2020C000 #define PWM_LEN 0x28 -#define CLK_BASE 0x20101000 #define CLK_LEN 0xA8 -#define GPIO_BASE 0x20200000 #define GPIO_LEN 0x100 -#define PCM_BASE 0x20203000 #define PCM_LEN 0x24 // Datasheet p. 51: @@ -173,20 +199,15 @@ typedef struct { uint32_t pad[2]; // _reserved_ } dma_cb_t; -// Memory mapping -typedef struct { - uint8_t *virtaddr; - uint32_t physaddr; -} page_map_t; // Main control structure per channel struct channel { uint8_t *virtbase; uint32_t *sample; dma_cb_t *cb; - page_map_t *page_map; volatile uint32_t *dma_reg; - + unsigned mem_ref; /* From mem_alloc() */ + unsigned bus_addr; /* From mem_lock() */ // Set by user uint32_t subcycle_time_us; @@ -218,7 +239,7 @@ static int delay_hw = DELAY_VIA_PWM; static int log_level = LOG_LEVEL_DEFAULT; // if set to 1, calls to fatal will not exit the program or shutdown DMA/PWM, but just sets -// the error_message and returns an error code. soft_fatal is enabled by default by the +// the error_message and returns an error code. soft_fatal is enabled by default by the // python wrapper, in order to convert calls to fatal(..) to exceptions. static int soft_fatal = 0; @@ -299,6 +320,8 @@ shutdown(void) udelay(10); } } + _is_setup =0; + unlink(MBFILE); } // Terminate is triggered by signals @@ -340,7 +363,7 @@ static void setup_sighandlers(void) { int i; - for (i = 1; i < 32; i++) { + for (i = 0; i < 64; i++) { // whitelist non-terminating signals if (i == SIGCHLD || i == SIGCONT || @@ -365,15 +388,16 @@ setup_sighandlers(void) static uint32_t mem_virt_to_phys(int channel, void *virt) { - uint32_t offset = (uint8_t *)virt - channels[channel].virtbase; - return channels[channel].page_map[offset >> PAGE_SHIFT].physaddr + (offset % PAGE_SIZE); + uint32_t offset = (uint8_t *)virt - channels[channel].virtbase; + + return channels[channel].bus_addr + offset; } // Peripherals memory mapping static void * map_peripheral(uint32_t base, uint32_t len) { - int fd = open("/dev/mem", O_RDWR); + int fd = open("/dev/mem", O_RDWR|O_SYNC); void * vaddr; if (fd < 0) { @@ -423,7 +447,17 @@ clear_channel(int channel) for (i = 0; i < channels[channel].num_samples; i++) { *(dp + i) = 0; } - + if (channels[channel].virtbase != NULL) { + unmapmem(channels[channel].virtbase, channels[channel].num_pages * 4096); + mem_unlock(mbox.handle, channels[channel].mem_ref); + mem_free(mbox.handle, channels[channel].mem_ref); + log_debug("close mail box handle start\n"); + mbox_close(mbox.handle); + log_debug("close mail box handle returned---------------\n"); + channels[channel].virtbase = NULL; + log_debug("close mail box handle finish---------------\n"); + + } return EXIT_SUCCESS; } @@ -496,56 +530,17 @@ add_channel_pulse(int channel, int gpio, int width_start, int width) return EXIT_SUCCESS; } - - -// Get a channel's pagemap -static int -make_pagemap(int channel) -{ - int i, fd, memfd, pid; - char pagemap_fn[64]; - - channels[channel].page_map = malloc(channels[channel].num_pages * sizeof(*channels[channel].page_map)); - - if (channels[channel].page_map == 0) - return fatal("rpio-pwm: Failed to malloc page_map: %m\n"); - memfd = open("/dev/mem", O_RDWR); - if (memfd < 0) - return fatal("rpio-pwm: Failed to open /dev/mem: %m\n"); - pid = getpid(); - sprintf(pagemap_fn, "/proc/%d/pagemap", pid); - fd = open(pagemap_fn, O_RDONLY); - if (fd < 0) - return fatal("rpio-pwm: Failed to open %s: %m\n", pagemap_fn); - if (lseek(fd, (uint32_t)channels[channel].virtbase >> 9, SEEK_SET) != - (uint32_t)channels[channel].virtbase >> 9) { - return fatal("rpio-pwm: Failed to seek on %s: %m\n", pagemap_fn); - } - for (i = 0; i < channels[channel].num_pages; i++) { - uint64_t pfn; - channels[channel].page_map[i].virtaddr = channels[channel].virtbase + i * PAGE_SIZE; - // Following line forces page to be allocated - channels[channel].page_map[i].virtaddr[0] = 0; - if (read(fd, &pfn, sizeof(pfn)) != sizeof(pfn)) - return fatal("rpio-pwm: Failed to read %s: %m\n", pagemap_fn); - if (((pfn >> 55) & 0x1bf) != 0x10c) - return fatal("rpio-pwm: Page %d not present (pfn 0x%016llx)\n", i, pfn); - channels[channel].page_map[i].physaddr = (uint32_t)pfn << PAGE_SHIFT | 0x40000000; - } - close(fd); - close(memfd); - return EXIT_SUCCESS; -} - static int init_virtbase(int channel) { - channels[channel].virtbase = mmap(NULL, channels[channel].num_pages * PAGE_SIZE, PROT_READ|PROT_WRITE, - MAP_SHARED|MAP_ANONYMOUS|MAP_NORESERVE|MAP_LOCKED, -1, 0); - if (channels[channel].virtbase == MAP_FAILED) - return fatal("rpio-pwm: Failed to mmap physical pages: %m\n"); - if ((unsigned long)channels[channel].virtbase & (PAGE_SIZE-1)) - return fatal("rpio-pwm: Virtual address is not page aligned\n"); + channels[channel].mem_ref= mem_alloc(mbox.handle, channels[channel].num_pages * 4096, 4096, mem_flag); + /* TODO: How do we know that succeeded? */ + printf("mem_ref %u\n", channels[channel].mem_ref); + channels[channel].bus_addr = mem_lock(mbox.handle, channels[channel].mem_ref); + printf("bus_addr = %u\n", channels[channel].bus_addr); + + channels[channel].virtbase = mapmem(BUS_TO_PHYS(channels[channel].bus_addr), channels[channel].num_pages * 4096); + printf("virtbase %p\n", channels[channel].virtbase); return EXIT_SUCCESS; } @@ -557,17 +552,17 @@ init_ctrl_data(int channel) uint32_t *sample = (uint32_t *) channels[channel].virtbase; uint32_t phys_fifo_addr; - uint32_t phys_gpclr0 = 0x7e200000 + 0x28; + uint32_t phys_gpclr0 = GPIO_PHYS_BASE + 0x28; int i; - channels[channel].dma_reg = map_peripheral(DMA_BASE, DMA_LEN) + (DMA_CHANNEL_INC * channel); + channels[channel].dma_reg = map_peripheral(DMA_VIRT_BASE, DMA_LEN) + (DMA_CHANNEL_INC * channel); if (channels[channel].dma_reg == NULL) return EXIT_FAILURE; if (delay_hw == DELAY_VIA_PWM) - phys_fifo_addr = (PWM_BASE | 0x7e000000) + 0x18; + phys_fifo_addr = PWM_PHYS_BASE + 0x18; else - phys_fifo_addr = (PCM_BASE | 0x7e000000) + 0x04; + phys_fifo_addr = PCM_PHYS_BASE + 0x04; // Reset complete per-sample gpio mask to 0 memset(sample, 0, sizeof(channels[channel].num_samples * sizeof(uint32_t))); @@ -684,8 +679,7 @@ init_channel(int channel, int subcycle_time_us) // Initialize channel if (init_virtbase(channel) == EXIT_FAILURE) return EXIT_FAILURE; - if (make_pagemap(channel) == EXIT_FAILURE) - return EXIT_FAILURE; + printf("after init virtbase"); if (init_ctrl_data(channel) == EXIT_FAILURE) return EXIT_FAILURE; return EXIT_SUCCESS; @@ -723,6 +717,22 @@ get_error_message(void) int setup(int pw_incr_us, int hw) { + unsigned char buf[4]; + FILE *fp; + + // get peri base from device tree + if ((fp = fopen("/proc/device-tree/soc/ranges", "rb")) != NULL) { + fseek(fp, 4, SEEK_SET); + if (fread(buf, 1, sizeof buf, fp) == sizeof buf) { + BCM2708_PERI_BASE = buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3] << 0; + } + fclose(fp); + } + if(BCM2708_PERI_BASE != periph_virt_base) + { + periph_virt_base = BCM2708_PERI_BASE; + mem_flag = 0x04; + } delay_hw = hw; pulse_width_incr_us = pw_incr_us; @@ -736,16 +746,22 @@ setup(int pw_incr_us, int hw) setup_sighandlers(); // Initialize common stuff - pwm_reg = map_peripheral(PWM_BASE, PWM_LEN); - pcm_reg = map_peripheral(PCM_BASE, PCM_LEN); - clk_reg = map_peripheral(CLK_BASE, CLK_LEN); - gpio_reg = map_peripheral(GPIO_BASE, GPIO_LEN); + pwm_reg = map_peripheral(PWM_VIRT_BASE, PWM_LEN); + pcm_reg = map_peripheral(PCM_VIRT_BASE, PCM_LEN); + clk_reg = map_peripheral(CLK_VIRT_BASE, CLK_LEN); + gpio_reg = map_peripheral(GPIO_VIRT_BASE, GPIO_LEN); if (pwm_reg == NULL || pcm_reg == NULL || clk_reg == NULL || gpio_reg == NULL) return EXIT_FAILURE; // Start PWM/PCM timing activity init_hardware(); + /* Use the mailbox interface to the VC to ask for physical memory */ + if (mknod(MBFILE, S_IFCHR|0600, makedev(249, 0)) < 0) + return fatal("Failed to create mailbox device\n"); + mbox.handle = mbox_open(); + if (mbox.handle < 0) + return fatal("Failed to open mailbox\n"); _is_setup = 1; return EXIT_SUCCESS; } diff --git a/source/c_pwm/pwm_py.c b/source/c_pwm/pwm_py.c index 7a008c1..82c8c0c 100644 --- a/source/c_pwm/pwm_py.c +++ b/source/c_pwm/pwm_py.c @@ -24,6 +24,7 @@ */ #include "Python.h" #include +#include "mailbox.h" #include "pwm.h" static void * @@ -245,7 +246,7 @@ PyMODINIT_FUNC init_PWM(void) return; #endif - PyModule_AddObject(module, "VERSION", Py_BuildValue("s", "0.10.1")); + PyModule_AddObject(module, "VERSION", Py_BuildValue("s", "2.0.0-beta1")); PyModule_AddObject(module, "DELAY_VIA_PWM", Py_BuildValue("i", DELAY_VIA_PWM)); PyModule_AddObject(module, "DELAY_VIA_PCM", Py_BuildValue("i", DELAY_VIA_PCM)); PyModule_AddObject(module, "LOG_LEVEL_DEBUG", Py_BuildValue("i", LOG_LEVEL_DEBUG)); diff --git a/source/scripts/rpio b/source/scripts/rpio index 02b7607..7637136 100644 --- a/source/scripts/rpio +++ b/source/scripts/rpio @@ -95,7 +95,7 @@ def main(): "GPIOs separate ids with commas (eg. `-i 17,18,19`) " "or specify a range (eg. `-i 2-20`)"), metavar="gpio-id") - parser.add_option("-I", "--inspect-all", dest="inspect_all", + parser.add_option("-I", "--inspect-all", dest="inspect_all", help="Inspect all available GPIOs", action="store_true") parser.add_option("-w", "--wait_for_interrupts", dest="interrupt", diff --git a/source/scripts/rpio-curses b/source/scripts/rpio-curses index 3c990ee..fc549ec 100644 --- a/source/scripts/rpio-curses +++ b/source/scripts/rpio-curses @@ -176,7 +176,7 @@ class Drawer(object): pos_y = POS_GPIOLIST_Y for gpio in self.gpios: - + gpio_id, func, state = gpio screen.addstr(pos_y, POS_GPIOLIST_X, "GPIO %s: " % (gpio_id)) screen.addstr(pos_y, POS_GPIOLIST_X+9, "%s " % (GPIO_FUNCTIONS[func]), curses.color_pair(3) if func == 4 else 0) diff --git a/version_update.sh b/version_update.sh index d83944a..6c4c6a2 100644 --- a/version_update.sh +++ b/version_update.sh @@ -28,9 +28,9 @@ if [ "$confirm" != "y" ]; then fi echo "Updating project to v$version..." -for fn in ${VERSION_FILES[@]}; do +for fn in ${VERSION_FILES[@]}; do echo "- $fn"; - sed -i '' "s/$VERSION_LAST/$version/" $fn + sed -i "s/$VERSION_LAST/$version/" $fn done echo $version > VERSION