mirror of
https://github.com/sinseman44/PyCNC.git
synced 2026-07-16 08:37:09 +00:00
review rpgpio
This commit is contained in:
+23
-23
@@ -5,7 +5,6 @@ from .rpgpio_private import *
|
|||||||
import time
|
import time
|
||||||
import logging
|
import logging
|
||||||
import sys
|
import sys
|
||||||
import struct
|
|
||||||
|
|
||||||
|
|
||||||
class GPIO(object):
|
class GPIO(object):
|
||||||
@@ -45,7 +44,7 @@ class GPIO(object):
|
|||||||
v = self._mem.read_int(addr)
|
v = self._mem.read_int(addr)
|
||||||
v &= ~(7 << ((pin % 10) * 3)) # input value
|
v &= ~(7 << ((pin % 10) * 3)) # input value
|
||||||
if mode == self.MODE_OUTPUT:
|
if mode == self.MODE_OUTPUT:
|
||||||
v |= (1 << ((pin % 10) * 3)) # output value, base on input
|
v |= (1 << ((pin % 10) * 3)) # output value, base on input
|
||||||
self._mem.write_int(addr, v)
|
self._mem.write_int(addr, v)
|
||||||
else:
|
else:
|
||||||
self._mem.write_int(addr, v)
|
self._mem.write_int(addr, v)
|
||||||
@@ -83,7 +82,7 @@ class GPIO(object):
|
|||||||
# clock for delay). So, do not create two or more instances of DMAGPIO.
|
# clock for delay). So, do not create two or more instances of DMAGPIO.
|
||||||
class DMAGPIO(DMAProto):
|
class DMAGPIO(DMAProto):
|
||||||
_DMA_CONTROL_BLOCK_SIZE = 32
|
_DMA_CONTROL_BLOCK_SIZE = 32
|
||||||
_DMA_CHANNEL = 5
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
""" Create object which control GPIO pins via DMA(Direct Memory
|
""" Create object which control GPIO pins via DMA(Direct Memory
|
||||||
Access).
|
Access).
|
||||||
@@ -94,7 +93,7 @@ class DMAGPIO(DMAProto):
|
|||||||
otherwise memory will be unlocked and it could be overwritten by
|
otherwise memory will be unlocked and it could be overwritten by
|
||||||
operating system.
|
operating system.
|
||||||
"""
|
"""
|
||||||
super(DMAGPIO, self).__init__(31 * 1024 * 1024)
|
super(DMAGPIO, self).__init__(31 * 1024 * 1024, 5)
|
||||||
self.__current_address = 0
|
self.__current_address = 0
|
||||||
|
|
||||||
# get helpers registers, this class uses PWM module to create precise
|
# get helpers registers, this class uses PWM module to create precise
|
||||||
@@ -106,7 +105,7 @@ class DMAGPIO(DMAProto):
|
|||||||
self._delay_info = DMA_TI_NO_WIDE_BURSTS | DMA_SRC_IGNORE \
|
self._delay_info = DMA_TI_NO_WIDE_BURSTS | DMA_SRC_IGNORE \
|
||||||
| DMA_TI_PER_MAP(DMA_TI_PER_MAP_PWM) \
|
| DMA_TI_PER_MAP(DMA_TI_PER_MAP_PWM) \
|
||||||
| DMA_TI_DEST_DREQ
|
| DMA_TI_DEST_DREQ
|
||||||
self._delay_destination = PHYSICAL_PWM_BUS + 0x18
|
self._delay_destination = PHYSICAL_PWM_BUS + PWM_FIFO
|
||||||
self._delay_stride = 0
|
self._delay_stride = 0
|
||||||
|
|
||||||
self._pulse_info = DMA_TI_NO_WIDE_BURSTS | DMA_TI_TDMODE \
|
self._pulse_info = DMA_TI_NO_WIDE_BURSTS | DMA_TI_TDMODE \
|
||||||
@@ -138,16 +137,16 @@ class DMAGPIO(DMAProto):
|
|||||||
source3 = next3 - 8
|
source3 = next3 - 8
|
||||||
|
|
||||||
data = (
|
data = (
|
||||||
self._pulse_info, source1, self._pulse_destination,
|
self._pulse_info, source1, self._pulse_destination,
|
||||||
self._pulse_length,
|
self._pulse_length,
|
||||||
self._pulse_stride, next1, pins_mask, 0,
|
self._pulse_stride, next1, pins_mask, 0,
|
||||||
self._delay_info, 0, self._delay_destination, length2,
|
self._delay_info, 0, self._delay_destination, length2,
|
||||||
self._delay_stride, next2, 0, 0,
|
self._delay_stride, next2, 0, 0,
|
||||||
self._pulse_info, source3, self._pulse_destination,
|
self._pulse_info, source3, self._pulse_destination,
|
||||||
self._pulse_length,
|
self._pulse_length,
|
||||||
self._pulse_stride, next3, 0, pins_mask
|
self._pulse_stride, next3, 0, pins_mask
|
||||||
)
|
)
|
||||||
self._physmem.write(self.__current_address, data)
|
self._physmem.write(self.__current_address, "24I", data)
|
||||||
self.__current_address = next_cb
|
self.__current_address = next_cb
|
||||||
|
|
||||||
def add_delay(self, delay_us):
|
def add_delay(self, delay_us):
|
||||||
@@ -157,14 +156,14 @@ class DMAGPIO(DMAProto):
|
|||||||
next_cb = self.__current_address + self._DMA_CONTROL_BLOCK_SIZE
|
next_cb = self.__current_address + self._DMA_CONTROL_BLOCK_SIZE
|
||||||
if next_cb > self._physmem.get_size():
|
if next_cb > self._physmem.get_size():
|
||||||
raise MemoryError("Out of allocated memory.")
|
raise MemoryError("Out of allocated memory.")
|
||||||
next = self._physmem.get_bus_address() + next_cb
|
next1 = self._physmem.get_bus_address() + next_cb
|
||||||
source = next - 8 # last 8 bytes are padding, use it to store data
|
source = next1 - 8 # last 8 bytes are padding, use it to store data
|
||||||
length = 16 * delay_us
|
length = 16 * delay_us
|
||||||
data = (
|
data = (
|
||||||
self._delay_info, source, self._delay_destination, length,
|
self._delay_info, source, self._delay_destination, length,
|
||||||
self._delay_stride, next, 0, 0
|
self._delay_stride, next1, 0, 0
|
||||||
)
|
)
|
||||||
self._physmem.write(self.__current_address, data)
|
self._physmem.write(self.__current_address, "8I", data)
|
||||||
self.__current_address = next_cb
|
self.__current_address = next_cb
|
||||||
|
|
||||||
def finalize_stream(self):
|
def finalize_stream(self):
|
||||||
@@ -188,7 +187,7 @@ class DMAGPIO(DMAProto):
|
|||||||
self._clock.write_int(CM_CNTL, CM_PASSWORD | CM_SRC_PLLD | CM_ENABLE)
|
self._clock.write_int(CM_CNTL, CM_PASSWORD | CM_SRC_PLLD | CM_ENABLE)
|
||||||
self._pwm.write_int(PWM_RNG1, 100)
|
self._pwm.write_int(PWM_RNG1, 100)
|
||||||
self._pwm.write_int(PWM_DMAC, PWM_DMAC_ENAB
|
self._pwm.write_int(PWM_DMAC, PWM_DMAC_ENAB
|
||||||
| PWM_DMAC_PANIC(15) | PWM_DMAC_DREQ(15))
|
| PWM_DMAC_PANIC(15) | PWM_DMAC_DREQ(15))
|
||||||
self._pwm.write_int(PWM_CTL, PWM_CTL_CLRF)
|
self._pwm.write_int(PWM_CTL, PWM_CTL_CLRF)
|
||||||
self._pwm.write_int(PWM_CTL, PWM_CTL_USEF1 | PWM_CTL_PWEN1)
|
self._pwm.write_int(PWM_CTL, PWM_CTL_USEF1 | PWM_CTL_PWEN1)
|
||||||
super(DMAGPIO, self)._run_dma()
|
super(DMAGPIO, self)._run_dma()
|
||||||
@@ -222,10 +221,10 @@ class DMAGPIO(DMAProto):
|
|||||||
|
|
||||||
|
|
||||||
class DMAPWM(DMAProto):
|
class DMAPWM(DMAProto):
|
||||||
_DMA_CHANNEL = 14
|
|
||||||
_DMA_CONTROL_BLOCK_SIZE = 32
|
_DMA_CONTROL_BLOCK_SIZE = 32
|
||||||
_DMA_DATA_OFFSET = 24
|
_DMA_DATA_OFFSET = 24
|
||||||
_TOTAL_NUMBER_OF_BLOCKS = 256
|
_TOTAL_NUMBER_OF_BLOCKS = 256
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
""" Initialise PWM. PWM has 8 bit resolution and fixed frequency
|
""" Initialise PWM. PWM has 8 bit resolution and fixed frequency
|
||||||
(~11.5 KHz and may flow). Though duty cycle is quite precise and
|
(~11.5 KHz and may flow). Though duty cycle is quite precise and
|
||||||
@@ -239,7 +238,7 @@ class DMAPWM(DMAProto):
|
|||||||
Cycles in info field of control blocks.
|
Cycles in info field of control blocks.
|
||||||
"""
|
"""
|
||||||
super(DMAPWM, self).__init__(self._TOTAL_NUMBER_OF_BLOCKS
|
super(DMAPWM, self).__init__(self._TOTAL_NUMBER_OF_BLOCKS
|
||||||
* self._DMA_CONTROL_BLOCK_SIZE)
|
* self._DMA_CONTROL_BLOCK_SIZE, 14)
|
||||||
self._clear_pins = dict()
|
self._clear_pins = dict()
|
||||||
# first control block always set pins
|
# first control block always set pins
|
||||||
self.__add_control_block(0, GPIO_SET_OFFSET)
|
self.__add_control_block(0, GPIO_SET_OFFSET)
|
||||||
@@ -266,7 +265,7 @@ class DMAPWM(DMAProto):
|
|||||||
0, # padding, uses as data storage
|
0, # padding, uses as data storage
|
||||||
0 # padding
|
0 # padding
|
||||||
)
|
)
|
||||||
self._physmem.write(address, data)
|
self._physmem.write(address, "8I", data)
|
||||||
|
|
||||||
def add_pin(self, pin, duty_cycle):
|
def add_pin(self, pin, duty_cycle):
|
||||||
""" Add pin to PMW with specified duty cycle.
|
""" Add pin to PMW with specified duty cycle.
|
||||||
@@ -321,6 +320,7 @@ class DMAPWM(DMAProto):
|
|||||||
self.remove_pin(pin)
|
self.remove_pin(pin)
|
||||||
assert len(self._clear_pins) == 0
|
assert len(self._clear_pins) == 0
|
||||||
|
|
||||||
|
|
||||||
# for testing purpose
|
# for testing purpose
|
||||||
def main():
|
def main():
|
||||||
pin = 21
|
pin = 21
|
||||||
@@ -340,7 +340,7 @@ def main():
|
|||||||
print("clear " + str(g.read(pin)))
|
print("clear " + str(g.read(pin)))
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
cma = CMAPhysicalMemory(1*1024*1024)
|
cma = CMAPhysicalMemory(1*1024*1024)
|
||||||
print(str(cma.get_size() / 1024 / 1024) + "MB of memory allocated at " \
|
print(str(cma.get_size() / 1024 / 1024) + "MB of memory allocated at "
|
||||||
+ hex(cma.get_phys_address()))
|
+ hex(cma.get_phys_address()))
|
||||||
a = cma.read_int(0)
|
a = cma.read_int(0)
|
||||||
print("was " + hex(a))
|
print("was " + hex(a))
|
||||||
|
|||||||
@@ -122,6 +122,7 @@ class PhysicalMemory(object):
|
|||||||
self._rmap = mmap.mmap(fd, size, flags=mmap.MAP_SHARED,
|
self._rmap = mmap.mmap(fd, size, flags=mmap.MAP_SHARED,
|
||||||
prot=mmap.PROT_READ | mmap.PROT_WRITE,
|
prot=mmap.PROT_READ | mmap.PROT_WRITE,
|
||||||
offset=phys_address)
|
offset=phys_address)
|
||||||
|
self._close_dev(fd)
|
||||||
atexit.register(self.cleanup)
|
atexit.register(self.cleanup)
|
||||||
|
|
||||||
def cleanup(self):
|
def cleanup(self):
|
||||||
@@ -139,14 +140,13 @@ class PhysicalMemory(object):
|
|||||||
os.close(fd)
|
os.close(fd)
|
||||||
|
|
||||||
def write_int(self, address, int_value):
|
def write_int(self, address, int_value):
|
||||||
self._rmap[address:address + 4] = struct.pack("I", int_value)
|
ctypes.c_uint32.from_buffer(self._rmap, address).value = int_value
|
||||||
|
|
||||||
def write(self, address, data):
|
def write(self, address, fmt, data):
|
||||||
self._rmap.seek(address)
|
struct.pack_into(fmt, self._rmap, address, *data)
|
||||||
self._rmap.write(struct.pack(str(len(data)) + "I", *data))
|
|
||||||
|
|
||||||
def read_int(self, address):
|
def read_int(self, address):
|
||||||
return struct.unpack("I", self._rmap[address:address + 4])[0]
|
return ctypes.c_uint32.from_buffer(self._rmap, address).value
|
||||||
|
|
||||||
def get_size(self):
|
def get_size(self):
|
||||||
return self._size
|
return self._size
|
||||||
@@ -154,6 +154,7 @@ class PhysicalMemory(object):
|
|||||||
|
|
||||||
class CMAPhysicalMemory(PhysicalMemory):
|
class CMAPhysicalMemory(PhysicalMemory):
|
||||||
IOCTL_MBOX_PROPERTY = ctypes.c_long(0xc0046400).value
|
IOCTL_MBOX_PROPERTY = ctypes.c_long(0xc0046400).value
|
||||||
|
|
||||||
def __init__(self, size):
|
def __init__(self, size):
|
||||||
""" This class allocates continuous memory with specified size, lock it
|
""" This class allocates continuous memory with specified size, lock it
|
||||||
and provide access to it with Python's mmap. It uses RPi video
|
and provide access to it with Python's mmap. It uses RPi video
|
||||||
@@ -162,10 +163,12 @@ class CMAPhysicalMemory(PhysicalMemory):
|
|||||||
"""
|
"""
|
||||||
size = (size + PAGE_SIZE - 1) // PAGE_SIZE * PAGE_SIZE
|
size = (size + PAGE_SIZE - 1) // PAGE_SIZE * PAGE_SIZE
|
||||||
self._vcio_fd = self._open_dev("/dev/vcio")
|
self._vcio_fd = self._open_dev("/dev/vcio")
|
||||||
self._handle = self._send_data(0x3000c, [size, PAGE_SIZE, 0xC]) # allocate memory
|
# allocate memory
|
||||||
|
self._handle = self._send_data(0x3000c, [size, PAGE_SIZE, 0xC])
|
||||||
if self._handle == 0:
|
if self._handle == 0:
|
||||||
raise OSError("No memory to allocate with /dev/vcio")
|
raise OSError("No memory to allocate with /dev/vcio")
|
||||||
self._busmem = self._send_data(0x3000d, [self._handle]) # lock memory
|
# lock memory
|
||||||
|
self._busmem = self._send_data(0x3000d, [self._handle])
|
||||||
if self._busmem == 0:
|
if self._busmem == 0:
|
||||||
# memory should be freed in __del__
|
# memory should be freed in __del__
|
||||||
raise OSError("Failed to lock memory with /dev/vcio")
|
raise OSError("Failed to lock memory with /dev/vcio")
|
||||||
@@ -201,10 +204,11 @@ class CMAPhysicalMemory(PhysicalMemory):
|
|||||||
|
|
||||||
|
|
||||||
class DMAProto(object):
|
class DMAProto(object):
|
||||||
def __init__(self, memory_size):
|
def __init__(self, memory_size, dma_channel):
|
||||||
""" This class provides basic access to DMA and creates buffer for
|
""" This class provides basic access to DMA and creates buffer for
|
||||||
control blocks.
|
control blocks.
|
||||||
"""
|
"""
|
||||||
|
self._DMA_CHANNEL = dma_channel
|
||||||
# allocate buffer for control blocks
|
# allocate buffer for control blocks
|
||||||
self._physmem = CMAPhysicalMemory(memory_size)
|
self._physmem = CMAPhysicalMemory(memory_size)
|
||||||
# prepare dma registers memory map
|
# prepare dma registers memory map
|
||||||
|
|||||||
Reference in New Issue
Block a user