fix PWM usage

This commit is contained in:
Nikolay Khabarov
2017-05-20 15:05:00 +03:00
parent 78804a438a
commit 3b73d7dcc4
3 changed files with 35 additions and 29 deletions
+10 -8
View File
@@ -93,7 +93,7 @@ class DMAGPIO(DMAProto):
otherwise memory will be unlocked and it could be overwritten by
operating system.
"""
super(DMAGPIO, self).__init__(31 * 1024 * 1024, 5)
super(DMAGPIO, self).__init__(30 * 1024 * 1024, 4)
self.__current_address = 0
# get helpers registers, this class uses PWM module to create precise
@@ -133,7 +133,7 @@ class DMAGPIO(DMAProto):
next1 = next2 - self._DMA_CONTROL_BLOCK_SIZE
source1 = next1 - 8 # last 8 bytes are padding, use it to store data
length2 = 16 * length_us
length2 = length_us << 4 # * 16
source3 = next3 - 8
data = (
@@ -158,7 +158,7 @@ class DMAGPIO(DMAProto):
raise MemoryError("Out of allocated memory.")
next1 = self._physmem.get_bus_address() + next_cb
source = next1 - 8 # last 8 bytes are padding, use it to store data
length = 16 * delay_us
length = delay_us << 4 # * 16
data = (
self._delay_info, source, self._delay_destination, length,
self._delay_stride, next1, 0, 0
@@ -180,11 +180,13 @@ class DMAGPIO(DMAProto):
"""
# configure PWM hardware module which will clocks DMA
self._pwm.write_int(PWM_CTL, 0)
self._clock.write_int(CM_CNTL, CM_PASSWORD | CM_SRC_PLLD) # disable
while (self._clock.read_int(CM_CNTL) & (1 << 7)) != 0:
self._clock.write_int(CM_PWM_CNTL, CM_PASSWORD | CM_SRC_PLLD) # disable
while (self._clock.read_int(CM_PWM_CNTL) & CM_CNTL_BUSY) != 0:
time.sleep(0.00001) # 10 us, wait until BUSY bit is clear
self._clock.write_int(CM_DIV, CM_PASSWORD | CM_DIV_VALUE(50)) # 10MHz
self._clock.write_int(CM_CNTL, CM_PASSWORD | CM_SRC_PLLD | CM_ENABLE)
self._clock.write_int(CM_PWM_DIV, CM_PASSWORD | CM_DIV_VALUE(5)) # 100MHz
self._clock.write_int(CM_PWM_CNTL, CM_PASSWORD | CM_SRC_PLLD |
CM_CNTL_ENABLE)
self._pwm.write_int(PWM_RNG1, 100)
self._pwm.write_int(PWM_DMAC, PWM_DMAC_ENAB
| PWM_DMAC_PANIC(15) | PWM_DMAC_DREQ(15))
@@ -350,7 +352,7 @@ def main():
print("now " + hex(a))
del cma
dg = DMAGPIO()
dg.add_pulse(1 << pin, 100000)
dg.add_pulse(1 << pin, 200000)
dg.add_delay(600000)
dg.run(True)
print("dmagpio is started")
+22 -15
View File
@@ -39,6 +39,8 @@ PHYSICAL_GPIO_BUS = 0x7E000000 + GPIO_REGISTER_BASE
# registers and values for DMA
DMA_BASE = 0x007000
DMA_CS = 0x00
DMA_CONBLK_AD = 0x04
DMA_TI_NO_WIDE_BURSTS = 1 << 26
DMA_TI_SRC_INC = 1 << 8
DMA_TI_DEST_INC = 1 << 4
@@ -79,16 +81,20 @@ def DMA_CS_PANIC_PRIORITY(x):
# hardware PWM controller registers
PWM_BASE = 0x0020C000
PHYSICAL_PWM_BUS = 0x7E000000 + PWM_BASE
PWM_CTL= 0x00
PWM_DMAC = 0x08
PWM_RNG1 = 0x10
PWM_RNG2 = 0x20
PWM_FIFO = 0x18
PWM_CTL_MODE1 = 1 << 1
PWM_CTL_MODE2 = 1 << 9
PWM_CTL_PWEN1 = 1 << 0
PWM_CTL_PWEN2 = 1 << 8
PWM_CTL_CLRF = 1 << 6
PWM_CTL_USEF1 = 1 << 5
PWM_CTL_USEF2 = 1 << 13
PWM_DMAC_ENAB = 1 << 31
PHYSICAL_PWM_BUS = 0x7E000000 + PWM_BASE
def PWM_DMAC_PANIC(x):
return x << 8
@@ -98,10 +104,13 @@ def PWM_DMAC_DREQ(x):
# clock manager module
CM_BASE = 0x00101000
CM_CNTL = 40
CM_DIV = 41
CM_PCM_CNTL = 0x98
CM_PCM_DIV = 0x9C
CM_PWM_CNTL = 0xA0
CM_PWM_DIV = 0xA4
CM_PASSWORD = 0x5A << 24
CM_ENABLE = 1 << 4
CM_CNTL_ENABLE = 1 << 4
CM_CNTL_BUSY = 1 << 7
CM_SRC_OSC = 1 # 19.2 MHz
CM_SRC_PLLC = 5 # 1000 MHz
CM_SRC_PLLD = 6 # 500 MHz
@@ -218,26 +227,24 @@ class DMAProto(object):
""" Run DMA module from created buffer.
"""
address = 0x100 * self._DMA_CHANNEL
cs = self._dma.read_int(address)
cs |= DMA_CS_END
self._dma.write_int(address, cs)
self._dma.write_int(address + 4, self._physmem.get_bus_address())
self._dma.write_int(address + DMA_CS, DMA_CS_END)
self._dma.write_int(address + DMA_CONBLK_AD, self._physmem.get_bus_address())
cs = DMA_CS_PRIORITY(7) | DMA_CS_PANIC_PRIORITY(7) | DMA_CS_DISDEBUG
self._dma.write_int(address, cs)
self._dma.write_int(address + DMA_CS, cs)
cs |= DMA_CS_ACTIVE
self._dma.write_int(address, cs)
self._dma.write_int(address + DMA_CS, cs)
def _stop_dma(self):
""" Stop DMA
"""
address = 0x100 * self._DMA_CHANNEL
cs = self._dma.read_int(address)
cs = self._dma.read_int(address + DMA_CS)
cs |= DMA_CS_ABORT
self._dma.write_int(address, cs)
self._dma.write_int(address + DMA_CS, cs)
cs &= ~DMA_CS_ACTIVE
self._dma.write_int(address, cs)
self._dma.write_int(address + DMA_CS, cs)
cs |= DMA_CS_RESET
self._dma.write_int(address, cs)
self._dma.write_int(address + DMA_CS, cs)
def is_active(self):
""" Check if DMA is working. Method can check if single sequence
@@ -245,7 +252,7 @@ class DMAProto(object):
:return: boolean value
"""
address = 0x100 * self._DMA_CHANNEL
cs = self._dma.read_int(address)
cs = self._dma.read_int(address + DMA_CS)
if cs & DMA_CS_ACTIVE == DMA_CS_ACTIVE:
return True
return False