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
+3 -6
View File
@@ -33,13 +33,10 @@ So having Raspberry Pi connected this way, there is no need to configure
pin map for project. pin map for project.
# Hardware # Hardware
Currently, this project supports Raspberry Pi 1-3. Tested with RPI2. But there Currently, this project supports Raspberry Pi 1-3. Tested with RPI2 and RPI3.
is a way to add new boards. See [hal.py](./cnc/hal.py) file. But there is a way to add new boards. See [hal.py](./cnc/hal.py) file.
_Note: Current Raspberry Pi implementation uses the same resources as on board _Note: Current Raspberry Pi implementation uses the same resources as on board
GPU(memory). So video output will not work with this project. Use ssh 3.5 mm jack(PWM module), so do not use it. HDMI audio works._
connection to board. And do not connect HDMI cable, otherwise project would not
run. Probably, increasing of GPU dedicated memory(at least to 64 MB) could solve
it and allow to work project and GPU together, but it was never tested._
# Usage # Usage
Just clone this repo and run `./pycnc` from repo root. It will start in Just clone this repo and run `./pycnc` from repo root. It will start in
+10 -8
View File
@@ -93,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, 5) super(DMAGPIO, self).__init__(30 * 1024 * 1024, 4)
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
@@ -133,7 +133,7 @@ class DMAGPIO(DMAProto):
next1 = next2 - self._DMA_CONTROL_BLOCK_SIZE next1 = next2 - self._DMA_CONTROL_BLOCK_SIZE
source1 = next1 - 8 # last 8 bytes are padding, use it to store data 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 source3 = next3 - 8
data = ( data = (
@@ -158,7 +158,7 @@ class DMAGPIO(DMAProto):
raise MemoryError("Out of allocated memory.") raise MemoryError("Out of allocated memory.")
next1 = self._physmem.get_bus_address() + next_cb next1 = self._physmem.get_bus_address() + next_cb
source = next1 - 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 = delay_us << 4 # * 16
data = ( data = (
self._delay_info, source, self._delay_destination, length, self._delay_info, source, self._delay_destination, length,
self._delay_stride, next1, 0, 0 self._delay_stride, next1, 0, 0
@@ -180,11 +180,13 @@ class DMAGPIO(DMAProto):
""" """
# configure PWM hardware module which will clocks DMA # configure PWM hardware module which will clocks DMA
self._pwm.write_int(PWM_CTL, 0) self._pwm.write_int(PWM_CTL, 0)
self._clock.write_int(CM_CNTL, CM_PASSWORD | CM_SRC_PLLD) # disable self._clock.write_int(CM_PWM_CNTL, CM_PASSWORD | CM_SRC_PLLD) # disable
while (self._clock.read_int(CM_CNTL) & (1 << 7)) != 0: while (self._clock.read_int(CM_PWM_CNTL) & CM_CNTL_BUSY) != 0:
time.sleep(0.00001) # 10 us, wait until BUSY bit is clear 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_PWM_DIV, CM_PASSWORD | CM_DIV_VALUE(5)) # 100MHz
self._clock.write_int(CM_CNTL, CM_PASSWORD | CM_SRC_PLLD | CM_ENABLE) 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_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))
@@ -350,7 +352,7 @@ def main():
print("now " + hex(a)) print("now " + hex(a))
del cma del cma
dg = DMAGPIO() dg = DMAGPIO()
dg.add_pulse(1 << pin, 100000) dg.add_pulse(1 << pin, 200000)
dg.add_delay(600000) dg.add_delay(600000)
dg.run(True) dg.run(True)
print("dmagpio is started") print("dmagpio is started")
+22 -15
View File
@@ -39,6 +39,8 @@ PHYSICAL_GPIO_BUS = 0x7E000000 + GPIO_REGISTER_BASE
# registers and values for DMA # registers and values for DMA
DMA_BASE = 0x007000 DMA_BASE = 0x007000
DMA_CS = 0x00
DMA_CONBLK_AD = 0x04
DMA_TI_NO_WIDE_BURSTS = 1 << 26 DMA_TI_NO_WIDE_BURSTS = 1 << 26
DMA_TI_SRC_INC = 1 << 8 DMA_TI_SRC_INC = 1 << 8
DMA_TI_DEST_INC = 1 << 4 DMA_TI_DEST_INC = 1 << 4
@@ -79,16 +81,20 @@ def DMA_CS_PANIC_PRIORITY(x):
# hardware PWM controller registers # hardware PWM controller registers
PWM_BASE = 0x0020C000 PWM_BASE = 0x0020C000
PHYSICAL_PWM_BUS = 0x7E000000 + PWM_BASE
PWM_CTL= 0x00 PWM_CTL= 0x00
PWM_DMAC = 0x08 PWM_DMAC = 0x08
PWM_RNG1 = 0x10 PWM_RNG1 = 0x10
PWM_RNG2 = 0x20
PWM_FIFO = 0x18 PWM_FIFO = 0x18
PWM_CTL_MODE1 = 1 << 1 PWM_CTL_MODE1 = 1 << 1
PWM_CTL_MODE2 = 1 << 9
PWM_CTL_PWEN1 = 1 << 0 PWM_CTL_PWEN1 = 1 << 0
PWM_CTL_PWEN2 = 1 << 8
PWM_CTL_CLRF = 1 << 6 PWM_CTL_CLRF = 1 << 6
PWM_CTL_USEF1 = 1 << 5 PWM_CTL_USEF1 = 1 << 5
PWM_CTL_USEF2 = 1 << 13
PWM_DMAC_ENAB = 1 << 31 PWM_DMAC_ENAB = 1 << 31
PHYSICAL_PWM_BUS = 0x7E000000 + PWM_BASE
def PWM_DMAC_PANIC(x): def PWM_DMAC_PANIC(x):
return x << 8 return x << 8
@@ -98,10 +104,13 @@ def PWM_DMAC_DREQ(x):
# clock manager module # clock manager module
CM_BASE = 0x00101000 CM_BASE = 0x00101000
CM_CNTL = 40 CM_PCM_CNTL = 0x98
CM_DIV = 41 CM_PCM_DIV = 0x9C
CM_PWM_CNTL = 0xA0
CM_PWM_DIV = 0xA4
CM_PASSWORD = 0x5A << 24 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_OSC = 1 # 19.2 MHz
CM_SRC_PLLC = 5 # 1000 MHz CM_SRC_PLLC = 5 # 1000 MHz
CM_SRC_PLLD = 6 # 500 MHz CM_SRC_PLLD = 6 # 500 MHz
@@ -218,26 +227,24 @@ class DMAProto(object):
""" Run DMA module from created buffer. """ Run DMA module from created buffer.
""" """
address = 0x100 * self._DMA_CHANNEL address = 0x100 * self._DMA_CHANNEL
cs = self._dma.read_int(address) self._dma.write_int(address + DMA_CS, DMA_CS_END)
cs |= DMA_CS_END self._dma.write_int(address + DMA_CONBLK_AD, self._physmem.get_bus_address())
self._dma.write_int(address, cs)
self._dma.write_int(address + 4, self._physmem.get_bus_address())
cs = DMA_CS_PRIORITY(7) | DMA_CS_PANIC_PRIORITY(7) | DMA_CS_DISDEBUG 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 cs |= DMA_CS_ACTIVE
self._dma.write_int(address, cs) self._dma.write_int(address + DMA_CS, cs)
def _stop_dma(self): def _stop_dma(self):
""" Stop DMA """ Stop DMA
""" """
address = 0x100 * self._DMA_CHANNEL address = 0x100 * self._DMA_CHANNEL
cs = self._dma.read_int(address) cs = self._dma.read_int(address + DMA_CS)
cs |= DMA_CS_ABORT cs |= DMA_CS_ABORT
self._dma.write_int(address, cs) self._dma.write_int(address + DMA_CS, cs)
cs &= ~DMA_CS_ACTIVE cs &= ~DMA_CS_ACTIVE
self._dma.write_int(address, cs) self._dma.write_int(address + DMA_CS, cs)
cs |= DMA_CS_RESET cs |= DMA_CS_RESET
self._dma.write_int(address, cs) self._dma.write_int(address + DMA_CS, cs)
def is_active(self): def is_active(self):
""" Check if DMA is working. Method can check if single sequence """ Check if DMA is working. Method can check if single sequence
@@ -245,7 +252,7 @@ class DMAProto(object):
:return: boolean value :return: boolean value
""" """
address = 0x100 * self._DMA_CHANNEL 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: if cs & DMA_CS_ACTIVE == DMA_CS_ACTIVE:
return True return True
return False return False