Example #1
0
 def test_set_transfer_length(self):
     cb_word_offset = 16
     target = dma.ControlBlock(self.mv, cb_word_offset)
     transfer_length = random.randint(0, 0xFFFFFFFF)
     target.set_transfer_length(transfer_length)
     self.assertEqual(transfer_length,
                      self.mv[cb_word_offset + self.OFFSET_WORDS_TXFR_LEN])
Example #2
0
 def test_set_source_addr(self):
     cb_word_offset = 16
     target = dma.ControlBlock(self.mv, cb_word_offset)
     source_addr = random.randint(0, 0xFFFFFFFF)
     target.set_source_addr(source_addr)
     self.assertEqual(source_addr,
                      self.mv[cb_word_offset + self.OFFSET_WORDS_SRC_ADDR])
Example #3
0
 def test_set_destination_addr(self):
     cb_word_offset = 16
     target = dma.ControlBlock(self.mv, cb_word_offset)
     destination_addr = random.randint(0, 0xFFFFFFFF)
     target.set_destination_addr(destination_addr)
     self.assertEqual(destination_addr,
                      self.mv[cb_word_offset + self.OFFSET_WORDS_DEST_ADDR])
Example #4
0
 def test_set_transfer_information(self):
     cb_word_offset = 16
     target = dma.ControlBlock(self.mv, cb_word_offset)
     transfer_information = random.randint(0, 0xFFFFFFFF)
     target.set_transfer_information(transfer_information)
     self.assertEqual(transfer_information,
                      self.mv[cb_word_offset + self.OFFSET_WORDS_TI])
Example #5
0
 def test_constructor_sets_src_addr_to_an_address_in_shared_memory_of_cb(
         self):
     cb_word_offset = 16
     dma.ControlBlock(self.mv, cb_word_offset)
     expected_src_addr = mu.get_mem_view_phys_addr_info(
         self.mv[cb_word_offset + self.OFFSET_WORDS_DATA_DEFAULT:]).p_addr
     self.assertEqual(expected_src_addr,
                      self.mv[cb_word_offset + self.OFFSET_WORDS_SRC_ADDR])
Example #6
0
 def test_set_next_cb_addr(self):
     cb_word_offset = 16
     target = dma.ControlBlock(self.mv, cb_word_offset)
     next_cb_addr = random.randint(0, 0xFFFFFFFF)
     target.set_next_cb_addr(next_cb_addr)
     self.assertEqual(
         next_cb_addr,
         self.mv[cb_word_offset + self.OFFSET_WORDS_NEXT_CB_ADDR])
Example #7
0
 def test_set_stride(self):
     cb_word_offset = 16
     target = dma.ControlBlock(self.mv, cb_word_offset)
     stride_src = random.randint(0, 0xFFFF)
     stride_dest = random.randint(0, 0xFFFF)
     stride = stride_src | stride_dest << 16
     target.set_stride(stride_src, stride_dest)
     self.assertEqual(stride,
                      self.mv[cb_word_offset + self.OFFSET_WORDS_STRIDE])
Example #8
0
 def test_set_transfer_length_stride(self):
     cb_word_offset = 16
     target = dma.ControlBlock(self.mv, cb_word_offset)
     transfer_length_x = random.randint(0, 0xFFFF)
     transfer_length_y = random.randint(0, 0xFFFF)
     transfer_length = transfer_length_x | (transfer_length_y - 1) << 16
     target.set_transfer_length_stride(transfer_length_x, transfer_length_y)
     self.assertEqual(transfer_length,
                      self.mv[cb_word_offset + self.OFFSET_WORDS_TXFR_LEN])
Example #9
0
 def test_write_word_to_source_data(self):
     cb_word_offset = 16
     target = dma.ControlBlock(self.mv, cb_word_offset)
     word = random.randint(0, 0xFFFFFFFF)
     write_offset_bytes = 3
     target.write_word_to_source_data(write_offset_bytes, word)
     self.assertEqual(
         word, self.mv[cb_word_offset + int(write_offset_bytes / 4) +
                       self.OFFSET_WORDS_DATA_DEFAULT])
Example #10
0
def configure_and_start_pwm(dma_ch, pwm_clk_src, pwm_clk_div_int,
                            pwm_clk_div_frac, pwm_cycles):
    if pwm_clk_src not in __allowed_clk_src_list:
        raise Exception("{} is not a valid clock source.".format(pwm_clk_src))

    if pwm_clk_div_int < 2:
        raise Exception("Clock integer divider must be 2 or greater.")

    if pwm_clk_div_frac < 0 or pwm_clk_div_frac > 4095:
        raise Exception(
            "Clock fractional divider must be between 0 (inclusive) and 4095 (inclusive)."
        )

    pwm_period_ns = 1000000000 / CLK_SRC_RATES[pwm_clk_src] * (
        (pwm_clk_div_int + pwm_clk_div_frac / 4096) * pwm_cycles)
    print("Starting PWM with a period of " + str(pwm_period_ns) + " ns.")

    clk_cb = dma.ControlBlock()
    clk_cb.set_destination_addr(PWM_CLK_BASE_BUS)
    clk_cb.set_transfer_information(dma.DMA_TI_NO_WIDE_BURSTS
                                    | dma.DMA_TI_WAIT_RESP | dma.DMA_TI_SRC_INC
                                    | dma.DMA_TI_DEST_INC)

    # Stop and configure PWM clock
    clk_cb.set_transfer_length(8)
    clk_cb.write_word_to_source_data(PWM_CLK_CTL, PWM_CLK_PWD | pwm_clk_src)
    clk_cb.write_word_to_source_data(
        PWM_CLK_DIV, PWM_CLK_PWD | pwm_clk_div_frac | pwm_clk_div_int << 12)
    dma.activate_channel_with_cb(dma_ch, clk_cb.addr)
    time.sleep(0.1)

    # Start PWM clock
    clk_cb.write_word_to_source_data(PWM_CLK_CTL,
                                     PWM_CLK_PWD | pwm_clk_src | PWM_CLK_ENAB)
    dma.activate_channel_with_cb(dma_ch, clk_cb.addr)
    time.sleep(0.1)

    # Configure and start PWM
    with mu.mmap_dev_mem(PWM_BASE_PHYS) as m:
        mu.write_word_to_byte_array(m, PWM_CTL, 0)  # Reset PWM
        mu.write_word_to_byte_array(m, PWM_RNG1, pwm_cycles)
        mu.write_word_to_byte_array(m, PWM_DMAC,
                                    PWM_DMAC_ENAB | PWM_DMAC_THRSHLD)
        mu.write_word_to_byte_array(m, PWM_CTL, PWM_CTL_CLRF)  # Clear FIFO
        mu.write_word_to_byte_array(
            m, PWM_CTL, PWM_CTL_USEF1 | PWM_CTL_RPTL1 | PWM_CTL_PWEN1)
        time.sleep(0.1)
Example #11
0
def stop_pwm(dma_ch, pwm_clk_src):
    if pwm_clk_src not in __allowed_clk_src_list:
        raise Exception("{} is not a valid clock source.".format(pwm_clk_src))

    # Reset PWM
    with mu.mmap_dev_mem(PWM_BASE_PHYS) as m:
        mu.write_word_to_byte_array(m, PWM_CTL, PWM_CTL_CLRF)  # Clear FIFO
        mu.write_word_to_byte_array(m, PWM_CTL, 0)  # Reset PWM

    time.sleep(0.1)

    # Stop PWM Clock
    clk_cb = dma.ControlBlock()
    clk_cb.set_destination_addr(PWM_CLK_BASE_BUS)
    clk_cb.set_transfer_information(dma.DMA_TI_NO_WIDE_BURSTS
                                    | dma.DMA_TI_WAIT_RESP | dma.DMA_TI_SRC_INC
                                    | dma.DMA_TI_DEST_INC)
    clk_cb.write_word_to_source_data(PWM_CLK_CTL, PWM_CLK_PWD | pwm_clk_src)
    dma.activate_channel_with_cb(dma_ch, clk_cb.addr)
    time.sleep(0.1)
Example #12
0
 def test_constructor_sets_transfer_length_to_one_word_by_default(self):
     cb_word_offset = 16
     dma.ControlBlock(self.mv, cb_word_offset)
     expected_transfer_length = 4
     self.assertEqual(expected_transfer_length,
                      self.mv[cb_word_offset + self.OFFSET_WORDS_TXFR_LEN])
Example #13
0
 def test_constructor_calculate_correct_cb_address(self):
     cb_word_offset = 16
     target = dma.ControlBlock(self.mv, cb_word_offset)
     expected_address = mu.get_mem_view_phys_addr_info(
         self.mv).p_addr + 4 * cb_word_offset
     self.assertEqual(expected_address, target.addr)
Example #14
0
 def test_constructor_defaults(self):
     target = dma.ControlBlock()
     self.assertEqual(0, target.word_offset)
     self.assertEqual(16, len(target.shared_mem))
Example #15
0
    def __init__(self, num_leds, gpio_pins: [gpio.GpioInfo]):
        self.dma_data = fd.LedDmaFrameData(num_leds)

        # SET and CLR registers are spaced as follows, spanning 5 registers:
        # SET  SET  --   CLR  CLR
        # 1C   20   24   28   2C
        # MS_MBOX_0 - MS_MBOX_7 are peripheral registers usable for storing this data.
        # We will only need MS_MBOX_0 - MS_MBOX_4.
        # The first two registers will be used to always set / clear gpio pins, so the appropriate bits in MS_MBOX_0 and
        # MS_MBOX_1 should just statically be set for this purpose. MS_MBOX_3 and MS_MBOX_4 will be used for optionally
        # clearing the GPIO pins.

        with mu.mmap_dev_mem(MS_BASE) as m:
            mu.write_word_to_byte_array(
                m, MS_MBOX_REG_OFFSET + GPIO_INFO_PIN18.set_clr_register_index,
                1 << GPIO_INFO_PIN18.pin_flip_bit_shift
                | 1 << GPIO_INFO_PIN15.pin_flip_bit_shift)

        # Allocate enough memory for all the CBs.
        self.shared_mem = mu.create_aligned_phys_contig_int_view(32, 32)

        # CBs
        self.cb_idle_wait = dma.ControlBlock()
        self.cb_idle_clr = dma.ControlBlock()

        self.cb_data_advance = dma.ControlBlock(
            self.shared_mem,
            0)  # Advances own SRC_ADDR and cb_data_upd's SRC_ADDR
        self.cb_data_upd = dma.ControlBlock(
            self.shared_mem,
            24)  # Writes next bit to be copied to GPIO into MS_MBOX

        self.cb_data_wait1 = dma.ControlBlock()
        self.cb_data_set_clr = dma.ControlBlock()
        self.cb_data_wait2 = dma.ControlBlock()
        self.cb_data_clr = dma.ControlBlock(
            self.shared_mem,
            8)  # Clears GPIO pins. Goes to cb_data_advance or cb_pause

        self.cb_pause = dma.ControlBlock(
        )  # Resets cb_idle_clr's NEXT_CB_ADDR to get into the idle CB loop

        # Configure idle loop
        self.cb_idle_wait.set_transfer_information(DMA_FLAGS_PWM)
        self.cb_idle_wait.set_destination_addr(pwm.PWM_BASE_BUS + pwm.PWM_FIFO)
        self.cb_idle_wait.set_next_cb_addr(self.cb_idle_clr.addr)

        self.cb_idle_clr.set_transfer_information(dma.DMA_TI_SRC_INC
                                                  | dma.DMA_TI_DEST_INC)
        self.cb_idle_clr.set_transfer_length(8)
        self.cb_idle_clr.set_source_addr(MS_BASE_BUS + MS_MBOX_REG_OFFSET)
        self.cb_idle_clr.set_destination_addr(gpio.GPIO_BASE_BUS + gpio.GPCLR0)
        self.cb_idle_clr.set_next_cb_addr(self.cb_idle_wait.addr)

        # Configure data loop
        cb_data_advance_src_addr = self.cb_data_advance.addr + 0x4
        src_stride = 4
        dest_stride = 48
        self.cb_data_advance.set_transfer_information(dma.DMA_TI_TD_MODE)
        self.cb_data_advance.set_source_addr(self.dma_data.start_address)
        self.cb_data_advance.set_destination_addr(cb_data_advance_src_addr)
        self.cb_data_advance.set_transfer_length_stride(4, 3)
        self.cb_data_advance.set_stride(src_stride, dest_stride)
        self.cb_data_advance.set_next_cb_addr(self.cb_data_upd.addr)

        # writes GPIO CLR data to MS_MBOX_3,4
        self.cb_data_upd.set_transfer_information(dma.DMA_TI_SRC_INC
                                                  | dma.DMA_TI_DEST_INC)
        self.cb_data_upd.set_transfer_length(8)
        self.cb_data_upd.set_destination_addr(MS_BASE_BUS +
                                              MS_MBOX_REG_OFFSET + 12)
        self.cb_data_upd.set_next_cb_addr(self.cb_data_wait1.addr)

        self.cb_data_wait1.set_transfer_information(DMA_FLAGS_PWM)
        self.cb_data_wait1.set_destination_addr(pwm.PWM_BASE_BUS +
                                                pwm.PWM_FIFO)
        self.cb_data_wait1.set_next_cb_addr(self.cb_data_set_clr.addr)

        self.cb_data_set_clr.set_transfer_information(dma.DMA_TI_NO_WIDE_BURSTS
                                                      | dma.DMA_TI_DEST_INC
                                                      | dma.DMA_TI_SRC_INC
                                                      | DMA_WAITS)
        self.cb_data_set_clr.set_transfer_length(20)
        self.cb_data_set_clr.set_source_addr(MS_BASE_BUS + MS_MBOX_REG_OFFSET)
        self.cb_data_set_clr.set_destination_addr(gpio.GPIO_BASE_BUS +
                                                  gpio.GPSET0)
        self.cb_data_set_clr.set_next_cb_addr(self.cb_data_wait2.addr)

        self.cb_data_wait2.set_transfer_information(DMA_FLAGS_PWM)
        self.cb_data_wait2.set_destination_addr(pwm.PWM_BASE_BUS +
                                                pwm.PWM_FIFO)
        self.cb_data_wait2.set_next_cb_addr(self.cb_data_clr.addr)

        self.cb_data_clr.set_transfer_information(dma.DMA_TI_NO_WIDE_BURSTS
                                                  | dma.DMA_TI_SRC_INC
                                                  | dma.DMA_TI_DEST_INC)
        self.cb_data_clr.set_transfer_length(8)
        self.cb_data_clr.set_source_addr(MS_BASE_BUS + MS_MBOX_REG_OFFSET)
        self.cb_data_clr.set_destination_addr(gpio.GPIO_BASE_BUS + gpio.GPCLR0)

        self.cb_pause.set_transfer_length(4)
        self.cb_pause.write_word_to_source_data(0, self.cb_idle_wait.addr)
        self.cb_pause.set_destination_addr(self.cb_idle_clr.addr + 0x14)
        self.cb_pause.set_next_cb_addr(self.cb_idle_clr.addr)

        self.dma_data.set_cb_addrs(self.cb_data_advance.addr,
                                   self.cb_pause.addr)

        self.gpio_pins = gpio_pins
Example #16
0
 def setUp(self):
     self.cb = dma.ControlBlock()