Перейти к содержанию
    

BSACPLD

Свой
  • Постов

    922
  • Зарегистрирован

  • Посещение

  • Победитель дней

    5

Весь контент BSACPLD


  1. Запуск HSPI на CH569

    Спасибо. С CRC разобрался. У меня ещё пара вопросов по сигналам HTREQ/HTRDY. 1. Правильно ли я понимаю, что HTRDY служит только для подтверждения со стороны slave начала передачи и что нельзя приостанавливать передачу опуская HTRDY в ноль когда приемный FIFO почти переполнился? 2. Правильно ли я понимаю, что master отслеживает окончание приема со стороны slave по переходу HTRDY из 1 в 0 после того как HTREQ перешёл в 0?
  2. Запуск HSPI на CH569

    Коллеги, удалось ли кому-нибудь запустить HSPI на CH569W? У меня никак не получается правильно посчитать CRC. Режим 8 бит, согласно документации полином для 8 бит должен быть 0x8005 (x^16 + x^15 + x^2 + 1). На реальном устройстве для тестовой последовательности 0x01 0x00 0x00 0xC8 0x06 0x00 0xEC 0x00 0x00 0x02 0x0E 0x00 на выходе получается CRC равная 0xDD62 (см. скриншот с лог. анализатора). В CRC калькуляторе совсем другое значение: 0x99EC. http://www.sunshine2k.de/coding/javascript/crc/crc_js.html Пробовал все варианты галочек Input reflected, Result reflected, пробовал менять значения Initial Value на 0xFFFF, 0x0000 - все равно результат в калькуляторе и с выхода CH569W не совпадает.
  3. Коллеги, мне тут понадобилось нарисовать PCIe разъём для PCIe карты под стандартную материнскую плату. Раньше такого не делал, поэтому возник ряд вопросов: 1. Как правильно сделать компонент? Нарисовать пины и контур в слое Assembly, а затем совместить Board Outline и Assembly при установке на плату? 2. Как правильно указать, что у края платы где сделан разъём нужно снять фаску? 3. Где найти чертежи на разъём? Я пока нашел только на ответную часть которая ставится на материнские платы...
  4. Функции из Verilog позволяют инициализировать содержимое памяти, но в отсинтезированном проекте при их использовании нельзя обновлять содержимое памяти без пересборки всего проекта целиком - используйте готовый IP для RAM/ROM или мегафункцию altsyncram и сможете обновлять содержимое памяти всего парой команд: Processing->Update Memory Initialization File, Processing->Start->Start Assembler. Вот пример: `timescale 1 ns / 1 ps module picorv32_prog_wrapper #( parameter DATA_SIZE = 8192, parameter DATA_WIDTH = 32, parameter INIT_FILE = "picorv32_fw.mem", parameter FPGA_VENDOR = "SIM", parameter DEVICE_FAMILY = "SIM", parameter SIM_INIT = "FALSE" ) ( input clock, input [$clog2(DATA_SIZE)-1:0] address, input [DATA_WIDTH-1:0] data, input wren, output [DATA_WIDTH-1:0] q ) ; generate if ((FPGA_VENDOR == "ALTERA") | (FPGA_VENDOR == "INTEL")) begin altsyncram #( .clock_enable_input_a ("BYPASS"), .clock_enable_output_a ("BYPASS"), .init_file (INIT_FILE), .intended_device_family (DEVICE_FAMILY), .lpm_type ("altsyncram"), .numwords_a (DATA_SIZE), .operation_mode ("SINGLE_PORT"), .outdata_aclr_a ("NONE"), .outdata_reg_a ("CLOCK0"), .power_up_uninitialized ("FALSE"), .widthad_a ($clog2(DATA_SIZE)), .width_a (DATA_WIDTH), .width_byteena_a (1) ) program_ram ( .clock0 (clock), .clock1 (1'b1), .address_a (address), .address_b ({$clog2(DATA_SIZE){1'b0}}), .data_a (data), .data_b ({DATA_WIDTH{1'b0}}), .wren_a (wren), .wren_b (1'b0), .q_a (q), .q_b (), .aclr0 (1'b0), .aclr1 (1'b0), .byteena_a (1'b1), .byteena_b (1'b1), .addressstall_a (1'b0), .addressstall_b (1'b0), .clocken0 (1'b1), .clocken1 (1'b1), .clocken2 (1'b1), .clocken3 (1'b1), .rden_a (1'b1), .rden_b (1'b1), .eccstatus () ) ; end else if (FPGA_VENDOR == "XILINX") begin xpm_memory_spram #( .ADDR_WIDTH_A ($clog2(DATA_SIZE)), .AUTO_SLEEP_TIME (0), .BYTE_WRITE_WIDTH_A (DATA_WIDTH), .CASCADE_HEIGHT (0), .ECC_MODE ("no_ecc"), .MEMORY_INIT_FILE (INIT_FILE), .MEMORY_INIT_PARAM ("0"), .MEMORY_OPTIMIZATION ("false"), .MEMORY_PRIMITIVE ("block"), .MEMORY_SIZE (DATA_WIDTH*DATA_SIZE), .MESSAGE_CONTROL (0), .READ_DATA_WIDTH_A (DATA_WIDTH), .READ_LATENCY_A (2), .READ_RESET_VALUE_A ("0"), .RST_MODE_A ("ASYNC"), .SIM_ASSERT_CHK (0), .USE_MEM_INIT (1), .WAKEUP_TIME ("disable_sleep"), .WRITE_DATA_WIDTH_A (DATA_WIDTH), .WRITE_MODE_A ("no_change") ) program_ram ( .dbiterra (), .douta (q), .sbiterra (), .addra (address), .clka (clock), .dina (data), .ena (1'b1), .injectdbiterra (1'b0), .injectsbiterra (1'b0), .regcea (1'b1), .rsta (1'b0), .sleep (1'b0), .wea (wren) ) ; end else if (FPGA_VENDOR == "LATTICE") begin pmi_ram_dq #( .pmi_addr_width ($clog2(DATA_SIZE)), .pmi_addr_depth (DATA_SIZE), .pmi_data_width (DATA_WIDTH), .pmi_regmode ("reg"), .pmi_gsr ("disable"), .pmi_resetmode ("async"), .pmi_optimization ("speed"), .pmi_init_file (INIT_FILE), .pmi_init_file_format ("hex"), .pmi_write_mode ("normal"), .pmi_family (DEVICE_FAMILY) ) program_ram ( .Reset (1'b0), .Clock (clock), .ClockEn (1'b1), .Address (address), .Data (data), .WE (wren), .Q (q) ) ; end else begin end endgenerate endmodule
  5. Попробовал собрать с pci_mmap_resource_range: ERROR: "pci_mmap_resource_range" [.../dma_dev.ko] undefined! #include <linux/pci.h> включен, но pci_mmap_resource_range не видится при сборке.
  6. Можно пример использования? Беглый поиск примеров в google ничего не дал 😞 Не пойму что передавать в mmap_state...
  7. Из define присваиваются константы. static int dma_dev_major = DEV_MAJOR; // < Major ID для символьного устройства static int dma_dev_minor = DEV_MINOR; // < Minor ID для символьного устройства #define DEV_MAJOR (83) #define DEV_MINOR (12) Устройство действительно нестандартное - специализированный сопроцессор. Поэтому и свой драйвер. DMA там тоже свой. Из готовых IP только AXI Memory Mapped To PCI Express. И если это важно, устройство в системе только одно.
  8. Нашел причину. В функции: static int dma_dev_remap_mmap(struct file *filp, struct vm_area_struct *vma) { unsigned long vm_pgoff_old; dma_dev_dev_t* dma_dev_dev_ptr = 0; dma_dev_dev_ptr = (dma_dev_dev_t*)filp->private_data; #ifdef VM_RESERVED vma->vm_flags |= (VM_PFNMAP | VM_SHARED | VM_RESERVED); #else vma->vm_flags |= (VM_PFNMAP | VM_SHARED | (VM_DONTEXPAND | VM_DONTDUMP) ); #endif ... if(direction == PC_2_DEV) { ... } if(direction == DEV_2_PC) { printk(KERN_NOTICE "dma_dev: tx_dma_buffers map %lx\n", vma->vm_pgoff); if(dma_dev_dev_ptr->tx_dma_buffers[index_tx_buffer].base_va == NULL) { printk(KERN_ALERT "dma_dev: tx_dma_buffers[%d].base_va == NULL\n", index_tx_buffer); direction = NO_TRANSFER; return -EAGAIN; } vm_pgoff_old = vma->vm_pgoff; vma->vm_pgoff = 0; if(dma_mmap_coherent(&(dma_dev_dev_ptr->pci_dev->dev), vma, dma_dev_dev_ptr->tx_dma_buffers[index_tx_buffer].base_va, dma_dev_dev_ptr->tx_dma_buffers[index_tx_buffer].base_ba, (size_t)(vma->vm_end - vma->vm_start))) { printk(KERN_ALERT "dma_dev: tx_dma_buffers map error!"); return -EAGAIN; } vma->vm_pgoff = vm_pgoff_old; direction = NO_TRANSFER; vma->vm_ops = &dma_dev_remap_vm_ops; dma_dev_vma_open(vma); return 0; } return -EAGAIN; } через указатель некорректно передается структура с дескриптором устройства: dma_dev_dev_ptr = (dma_dev_dev_t*)filp->private_data; На x86, Radxa Rockchip работает, а на Firefly Rockchip - нет. Но если передать структуру с дескриптором устройства просто через глобальную переменную: dma_dev_dev_ptr = &(dma_dev_dev[0]); то корректно работает на всех выше перечисленных платформах. Может быть я как-то некорректно работаю с данным указателем или неправильно сохраняю указатель на структуру? // Открытие файла устройства int dma_dev_open(struct inode *inode, struct file *filp) { dma_dev_dev_t* dev; /* device information */ printk(KERN_NOTICE "dma_dev_open.\n"); // Сохраняем указатель на структуру dev = container_of(inode->i_cdev, dma_dev_dev_t, cdev); filp->private_data = dev; /* for other methods */ return 0; /* success */ } // Инициализация для устройства dma_dev_dev_t структуры cdev и ее регистрация в ОС static void dma_dev_setup_cdev(dma_dev_dev_t *dev, int index) { int err, devno = MKDEV(dma_dev_major, dma_dev_minor + index); //printk(KERN_NOTICE "dma_dev_setup_cdev"); cdev_init(&dev->cdev, &dma_dev_fops); dev->cdev.owner = THIS_MODULE; dev->cdev.ops = &dma_dev_fops; err = cdev_add (&dev->cdev, devno, 1); if(err) { printk(KERN_ALERT "dma_dev: error %d at adding dma_dev%d", err, index); } } Коллеги, нужна ваша помощь Я в упор не вижу в чем проблема
  9. Странная проблема... На RK3588 на компьютере от Radxa работает без проблем, а на том же RK3588 на компьютере от Firefly зависает при вызове mmap. При этом dmesg выдает следующую информацию об ошибке:
  10. Нашел решение. Вручную выкачать недостающие файлы: cd /usr/src/linux-headers-5.10.110-rockchip-rk3588/ wget https://raw.githubusercontent.com/torvalds/linux/v5.10/arch/arm64/kernel/vdso/vdso.lds.S -P arch/arm64/kernel/vdso wget https://raw.githubusercontent.com/torvalds/linux/v5.10/arch/arm64/kernel/vdso/vgettimeofday.c -P arch/arm64/kernel/vdso wget https://raw.githubusercontent.com/torvalds/linux/v5.10/lib/vdso/gettimeofday.c -P lib/vdso wget https://raw.githubusercontent.com/torvalds/linux/v5.10/arch/arm64/kernel/vdso/note.c -P arch/arm64/kernel/vdso wget https://raw.githubusercontent.com/torvalds/linux/v5.10/arch/arm64/kernel/vdso/note.S -P arch/arm64/kernel/vdso wget https://raw.githubusercontent.com/torvalds/linux/v5.10/arch/arm64/kernel/vdso/sigreturn.S -P arch/arm64/kernel/vdso wget https://raw.githubusercontent.com/torvalds/linux/v5.10/arch/arm64/kernel/vdso/gen_vdso_offsets.sh -P arch/arm64/kernel/vdso make KERNELVERSION=5.10.110-rockchip-rk3588 -j3 modules_prepare
  11. Я его не собирал. Взял готовый образ: https://www.armbian.com/rock-5b/
  12. у меня в linux-headers нет скриптов необходимых для сборки драйверов, и при попытке собрать их через sudo make modules_prepare появляется приведенная выше ошибка. sudo apt install linux-headers-$(uname -r) На armbian так делать нельзя - версия будет не соответствовать текущему ядру. linux-headers и linux-kernel нужно ставить через утилиту armbian-config, иначе будут расхождения в версиях. По этим граблям я уже прошелся 😞
  13. Коллеги, я тут пытаюсь установить linux-headers на дистрибутив Armbian 23.02.2 под плату Rock 5 model B. При выполнении sudo make modules_prepare возникает такая ошибка: @rock-5b:/usr/src/linux-headers-5.10.110-rockchip-rk3588$ sudo make modules_prepare UPD include/config/kernel.release UPD include/generated/utsrelease.h CC scripts/mod/empty.o HOSTCC scripts/mod/mk_elfconfig MKELF scripts/mod/elfconfig.h HOSTCC scripts/mod/modpost.o CC scripts/mod/devicetable-offsets.s HOSTCC scripts/mod/file2alias.o HOSTCC scripts/mod/sumversion.o HOSTLD scripts/mod/modpost scripts/Makefile.build:423: предупреждение: переопределение способа для цели «modules.order» Makefile:1518: предупреждение: старый способ для цели «modules.order» игнорируются make[1]: *** Нет правила для сборки цели «arch/arm64/kernel/vdso/vdso.lds», требуемой для «arch/arm64/kernel/vdso/vdso.so.dbg». Останов. make: *** [arch/arm64/Makefile:194: vdso_prepare] Ошибка 2 Что я делаю не так? Все package обновлены до самой последеней версии, пробовал и предыдущую версию Armbian 22.11.2, там такая же ошибка...
  14. Ещё один вопрос возник. Как корректно маппить регистры BAR PCIe устройства чтобы это работало и на x86 и на ARM? Вот такой код: if(remap_pfn_range(vma, vma->vm_start, PHYS_PFN(dma_dev_dev_ptr->regs_pa[0]), vma->vm_end - vma->vm_start, vma->vm_page_prot)) { printk(KERN_ALERT "dma_dev: reg map BAR0_REGS_BASE_ADDR error!"); return -EAGAIN; } работает только на x86 😞
  15. На практике у меня получилось обратное. На x86 dma_mmap_coherent некорректно отрабатывает. Приходится использовать remap_pfn_range для x86 ветки. UPD. Вы были правы. Если вместо (void*)(vma->vm_start) передавать виртуальный адрес от dma_alloc_coherent, то dma_mmap_coherent работает и на x86 тоже 🙂
  16. Разобрался. Надо было физический адрес не из виртуального через virt_to_phys получать, а брать тот что возвращает dma_alloc_coherent. Ну и ещё момент. Если делать универсально ARM/x86, для для x86 ветки нужно использовать remap_pfn_range. vm_pgoff_old = vma->vm_pgoff; #if defined(__aarch64__) || defined(__arm__) vma->vm_pgoff = 0; if(dma_mmap_coherent(&(dma_dev_dev_ptr->pci_dev->dev), vma, (void*)(vma->vm_start), dma_dev_dev_ptr->tx_dma_buffers[index_tx_buffer].base_ba, (size_t)(vma->vm_end - vma->vm_start))) #else if(remap_pfn_range(vma, vma->vm_start, page_to_pfn(virt_to_page(dma_dev_dev_ptr->tx_dma_buffers[index_tx_buffer].base_va)), vma->vm_end - vma->vm_start, vma->vm_page_prot)) #endif { printk(KERN_ALERT "dma_dev: tx_dma_buffers map error!"); return -EAGAIN; } vma->vm_pgoff = vm_pgoff_old;
  17. dma_mmap_coherent

    Народ, подскажите, пожалуйста, как правильно использовать dma_mmap_coherent на ARM (RK3588). Пытаюсь маппить из kernel в userspace следующим образом: static int dma_dev_remap_mmap(struct file *filp, struct vm_area_struct *vma) { dma_dev_dev_t* dma_dev_dev_ptr = 0; dma_dev_dev_ptr = (dma_dev_dev_t*)filp->private_data; #ifdef VM_RESERVED vma->vm_flags |= (VM_PFNMAP | VM_SHARED | VM_RESERVED); #else vma->vm_flags |= (VM_PFNMAP | VM_SHARED | (VM_DONTEXPAND | VM_DONTDUMP) ); #endif .......... vma->vm_pgoff = 0; if(dma_mmap_coherent(&(dma_dev_dev_ptr->pci_dev->dev), vma, (void*)(vma->vm_start), virt_to_phys(dma_dev_dev_ptr->tx_dma_buffers[index_tx_buffer].base_va), (size_t)(vma->vm_end - vma->vm_start))) { printk(KERN_ALERT "dma_dev: tx_dma_buffers map error!"); return -EAGAIN; } vma->vm_ops = &dma_dev_remap_vm_ops; .......... } Но в userspace получаю какой-то левый указатель. В драйвере при создании буфера я забиваю его магическими числами 0xEB, а из userspace читается 0x00. Что я делаю не так?
  18. Так может Вам написать свой собственный захватчик видео вместо Gstreamer? Я так делал в своем проекте - получилось и просто и сложно одновременно. Просто - прошивка для ПЛИС и софт на компьютере получились очень простые. Сложно - свой собственный драйвер пока удалось запустить только на x86 и Jetson...
  19. Если не париться со сборкой, то только BMTI - там вообще патчи не нужны. У K325 Fudan такой же геморрой со сборкой как и у JFMK50T4 - в инструкции по сборке те же самые пункты что и для 50. Ну и опять же смотря что собирать. Если без GTP/PCIe, то и у Fudan нет особых проблем со сборкой. А вот если они нужны, тогда да.
  20. 1. В Procise есть jfm7a200t4, но мне пока не удалось получить информацию о возможности их поставки ни от Эпсилон, ни от Феникс Электроникс. 2. Да. Нужна лицензия на Procise. И придется извращатся с EDIF перегоняя нетлист из Vivado в Procise.
  21. Тут главный вопрос как автоматизировать переписывание констрейнов для IP из Vivado... У Procise и Vivado мягко говоря разный формат констрейнов.
  22. Procise как-то не очень дружит с командной строкой. Либо я не нашел как его правильно запускать через командную строку... К тому же он под Windows, поэтому живёт у меня в виртуалке, а Vivado с остальным софтом под Linux на основной системе.
  23. Да. Но только по кривому маршруту. Vivado+патч+переписывание констрейнов для IP блока PCIe+Procise. Сначала в Vivado собираем EDIF под xc7k325t попутно не забывая вручную вызывать ряд команд, т.к. автоматический патч правит далеко не все, потом транслируем его в EDIF для Procise фирменным конвертером от Fudan, руками переписываем xdc для IP PCIe под формат констрейнов для Fudan, потом всем это дело собираем в Procise. В общем куча ручной работы для каждой сборки. Нормально отлаживаться в таком режиме не реально. Только если тащить из Vivado отдельные IP либо прототип отлаживать на Xilinx, а в серию уже ставить Fudan. Добиться от Fudan чтобы они починили свой патч и не приходилось использовать Procise если нужен PCIe пока не удалось.
  24. Коллеги, тут мне поступило предложение изготовить разработанную мной отладочную плату на Fudan на продажу, но одну штуку нашей компании делать не выгодно. Если есть ещё желающие - пишите в личку. Если наберётся хотя бы 10 шт., сможем запустить в производство. User Manual с описанием что это за зверь чуть позже приложу. Пока вот Вам фото 🙂
  25. UPD3. Пока изыскания следующие: Чтобы начать отправку пакета, после того как данные готовы, нужно изменить состояние конечной точки: USB30_IN_set(ENDP_1, ENABLE, ACK, DEF_ENDP1_IN_BURST_LEVEL, 1024); USB30_send_ERDY(ENDP_1 | IN, DEF_ENDP1_IN_BURST_LEVEL); После этого начинает вызываться EP1_IN_Callback(). Когда данные закончились, нужно поменять состояние конечной точки на NRDY: USB30_IN_set(ENDP_1, ENABLE, NRDY, DEF_ENDP1_IN_BURST_LEVEL, 1024); USB30_send_ERDY(ENDP_1 | IN, DEF_ENDP1_IN_BURST_LEVEL); И вот тут как раз и возникает проблема как определить момент, когда данные уже отправлены... Я пробовал отслеживать изменение nump: nump = USB30_IN_nump(ENDP_1); //nump: number of remaining packets to be sent status = ACK; if(prev_nump != nump) { status = NRDY; } prev_nump = nump; Но при таком подходе у меня успевает отправиться несколько пакетов прежде чем изменится nump...
×
×
  • Создать...