{"id":456029,"date":"2025-04-14T15:01:41","date_gmt":"2025-04-14T15:01:41","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=456029"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=456029","title":{"rendered":"<span>\u0417\u0430\u0442\u043e\u043b\u043a\u0430\u0435\u043c \u0431\u0440\u0430\u0442\u0446\u044b!!! UART Lite \u0447\u0435\u0440\u0435\u0437 PCIe \u043f\u0440\u044f\u043c\u0438\u043a\u043e\u043c \u0432 Linux: \u0434\u0440\u0430\u0439\u0432\u0435\u0440 \u0437\u0430 \u0432\u0435\u0447\u0435\u0440 (\u043f\u043e\u0447\u0442\u0438)<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u0418\u043d\u043e\u0433\u0434\u0430 \u0441\u0430\u043c\u044b\u0435 \u043f\u0440\u043e\u0441\u0442\u044b\u0435 \u0437\u0430\u0434\u0430\u0447\u0438 \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u044e\u0442\u0441\u044f \u0432 \u043c\u0438\u043d\u0438-\u043f\u0440\u0438\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043a\u043e\u0433\u0434\u0430 \u0432\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c UARTLite \u043d\u0430 FPGA \u043a Linux \u0447\u0435\u0440\u0435\u0437 PCIe. \u041a\u0430\u0436\u0435\u0442\u0441\u044f, \u043d\u0443 \u0447\u0442\u043e \u0442\u0430\u043c? \u041f\u0430\u0440\u0443 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u043e\u0432, \u043f\u0430\u0440\u0430 \u043f\u0440\u0435\u0440\u044b\u0432\u0430\u043d\u0438\u0439\u2026 \u0410 \u043d\u0430 \u0434\u0435\u043b\u0435 \u2014 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0434\u043d\u0435\u0439 \u0437\u0430 Vivado, \u043e\u0442\u043b\u0430\u0434\u043a\u0430 XDMA \u0438 \u0431\u043e\u0440\u044c\u0431\u0430 \u0441 \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430\u043c\u0438. \ud83d\ude05 <\/p>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443, \u043a\u0430\u043a \u044f \u0432\u0441\u0451-\u0442\u0430\u043a\u0438 \u043f\u043e\u0431\u0435\u0434\u0438\u043b UARTLite \u0447\u0435\u0440\u0435\u0437 XDMA \u0438 \u043a\u0430\u043a \u0432\u044b \u0441\u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u044c \u044d\u0442\u043e \u0431\u0435\u0437 \u0431\u043e\u043b\u0438. <\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/c97\/eb5\/40d\/c97eb540deb6db4a6cb07e6fac7b389f.png\" width=\"517\" height=\"496\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/c97\/eb5\/40d\/c97eb540deb6db4a6cb07e6fac7b389f.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/c97\/eb5\/40d\/c97eb540deb6db4a6cb07e6fac7b389f.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<h4>\u0410\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044f<\/h4>\n<p>\u042d\u0442\u043e\u0442 \u043f\u0440\u043e\u0435\u043a\u0442 \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u0442, \u043a\u0430\u043a \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043f\u0435\u0440\u0438\u0444\u0435\u0440\u0438\u0439\u043d\u043e\u0435 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e UARTLite \u043d\u0430 \u0431\u0430\u0437\u0435 FPGA \u043a \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u043c Linux \u0447\u0435\u0440\u0435\u0437 <strong>PCIe<\/strong> <strong>XDMA<\/strong>.<br \/>\u0420\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c <strong>TTY-\u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441<\/strong> (\u0434\u0440\u0430\u0439\u0432\u0435\u0440 <strong>Linux TTY<\/strong> ) <code>\/dev\/ttyULx<\/code> \u0438 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u0431\u044b\u0441\u0442\u0440\u043e\u0433\u043e \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u0447\u0435\u0440\u0435\u0437 <strong>Python<\/strong> \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c <code>mmap<\/code>.<br \/>\u0418\u0434\u0435\u0430\u043b\u044c\u043d\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u0434\u043b\u044f \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438 \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u044b <strong>SDR<\/strong>, \u0440\u043e\u0431\u043e\u0442\u043e\u0442\u0435\u0445\u043d\u0438\u043a\u0438 \u0438 \u0432\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c\u044b\u0445 \u0441\u0438\u0441\u0442\u0435\u043c!<\/p>\n<ul>\n<li>\n<p><strong>\u0427\u0442\u043e \u0437\u0430 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e?<\/strong><br \/>\u2794 \u041c\u043e\u044f SDR-\u043f\u043b\u0430\u0442\u0430 \u043d\u0430 <strong>FPGA Artix-7<\/strong>, <strong>GPS SIM68<\/strong> \u043c\u043e\u0434\u0443\u043b\u0435\u043c \u0438 <strong>AD9361<\/strong> RF \u0440\u0430\u043d\u0441\u0438\u0432\u0435\u0440\u043e\u043c, \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u043c PCIe \u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c\u044e \u043e\u0431\u043c\u0435\u043d\u0430 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u043c\u0435\u0436\u0434\u0443 <strong>FPGA<\/strong> \u0438 <strong>Linux<\/strong> \u0447\u0435\u0440\u0435\u0437 <strong>XDMA<\/strong>.<\/p>\n<\/li>\n<li>\n<p><strong>\u0427\u0442\u043e \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0434\u0435\u043b\u0430\u0442\u044c?<\/strong><br \/>\u2794 \u0420\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u043c Linux-\u0434\u0440\u0430\u0439\u0432\u0435\u0440 \u0434\u043b\u044f UARTLite \u0447\u0435\u0440\u0435\u0437 XDMA \u0438 \u043f\u0440\u043e\u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u043c \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u043f\u0440\u044f\u043c\u043e\u0433\u043e \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u0447\u0435\u0440\u0435\u0437 Python.<\/p>\n<\/li>\n<li>\n<p><strong>\u041f\u043e\u0447\u0435\u043c\u0443 \u044d\u0442\u043e \u0432\u0430\u0436\u043d\u043e?<\/strong><br \/>\u2794 \u0422\u0430\u043a\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043b\u0435\u0433\u043a\u043e \u0438\u043d\u0442\u0435\u0433\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0435 FPGA-\u043f\u0435\u0440\u0438\u0444\u0435\u0440\u0438\u0438 \u0432 Linux-\u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0431\u0435\u0437 \u0441\u043b\u043e\u0436\u043d\u043e\u0439 \u0440\u0443\u0447\u043d\u043e\u0439 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438, \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0432 SDR-\u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445, \u0440\u043e\u0431\u043e\u0442\u043e\u0442\u0435\u0445\u043d\u0438\u043a\u0435, \u0430\u0432\u0442\u043e\u043d\u043e\u043c\u043d\u044b\u0445 \u0441\u0438\u0441\u0442\u0435\u043c\u0430\u0445 \u0438 IoT.<\/p>\n<hr\/>\n<h3>1. \u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435<\/h3>\n<p>\u0412\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c\u044b\u0435 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u043d\u0430 \u0431\u0430\u0437\u0435 <strong>FPGA<\/strong> \u0448\u0438\u0440\u043e\u043a\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u044e\u0442\u0441\u044f \u0432 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u043e-\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c\u044b\u0445 \u0440\u0430\u0434\u0438\u043e\u0441\u0438\u0441\u0442\u0435\u043c\u0430\u0445 (<strong>SDR<\/strong>, Software-Defined Radio).  \u041f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u043e-\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c\u044b\u0435 \u0440\u0430\u0434\u0438\u043e\u0441\u0438\u0441\u0442\u0435\u043c\u044b (SDR) \u0442\u0440\u0435\u0431\u0443\u044e\u0442 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0433\u043e \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u043c\u0435\u0436\u0434\u0443 FPGA \u0438 CPU, \u0447\u0442\u043e \u043e\u0441\u043b\u043e\u0436\u043d\u044f\u0435\u0442\u0441\u044f \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0435\u0439 \u043f\u0435\u0440\u0438\u0444\u0435\u0440\u0438\u0438 \u0447\u0435\u0440\u0435\u0437 PCIe. \u042d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f \u0440\u0435\u0448\u0430\u0435\u0442 \u0437\u0430\u0434\u0430\u0447\u0443 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430 \u0434\u043b\u044f UARTlite \u0447\u0435\u0440\u0435\u0437 XDMA, \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0438\u0440\u0443\u044f \u0434\u0432\u0430 \u043f\u043e\u0434\u0445\u043e\u0434\u0430: \u0447\u0435\u0440\u0435\u0437 \u044f\u0434\u0440\u043e Linux \u0438 Python. \u0426\u0435\u043b\u044c \u2014 \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0443, \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043d\u0430 \u0431\u0430\u0437\u0435 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0439 SDR-\u043f\u043b\u0430\u0442\u044b. <\/p>\n<p><strong>\u041e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430:<\/strong><\/p>\n<\/li>\n<li>\n<p>\u2705 <strong>\u0420\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u043d\u0430\u044f \u0441 \u043d\u0443\u043b\u044f SDR-\u043f\u043b\u0430\u0442\u0430<\/strong> \u043d\u0430 <strong>FPGA Artix-7 \u0438 AD9361<\/strong><\/p>\n<\/li>\n<li>\n<p>\u2705 <strong>\u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u043e\u0439 \u043f\u043b\u0430\u0442\u044b<\/strong> \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f <a href=\"https:\/\/www.lattepanda.com\/lattepanda-sigma\" rel=\"noopener noreferrer nofollow\"><strong>LattePanda Sigma<\/strong><\/a> <\/p>\n<\/li>\n<li>\n<p>\u2705 <strong>\u0412\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0439 UARTlite<\/strong> \u0434\u043b\u044f \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441 GPS \u043c\u043e\u0434\u0443\u043b\u0435\u043c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u044b\u043c \u043a FPGA  <\/p>\n<\/li>\n<li>\n<p>\u2705 <strong>XDMA \u0447\u0435\u0440\u0435\u0437 PCIe<\/strong> \u0434\u043b\u044f \u0432\u044b\u0441\u043e\u043a\u043e\u0441\u043a\u043e\u0440\u043e\u0441\u0442\u043d\u043e\u0439 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0434\u0430\u043d\u043d\u044b\u0445<\/p>\n<\/li>\n<li>\n<p>\u2705 <strong>\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u0434\u0432\u0443\u0445 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0440\u0430\u0431\u043e\u0442\u044b:<\/strong><\/p>\n<ul>\n<li>\n<p><strong>Linux-\u0434\u0440\u0430\u0439\u0432\u0435\u0440 \u0441 TTY-\u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u043c<\/strong> (<code>\/dev\/ttyULx<\/code>)<\/p>\n<\/li>\n<li>\n<p><strong>\u041f\u0440\u044f\u043c\u0430\u044f \u0440\u0430\u0431\u043e\u0442\u0430 \u0441 UARTlite \u043d\u0430 Python \u0447\u0435\u0440\u0435\u0437 XDMA<\/strong><\/p>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<hr\/>\n<h3>2. \u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 \u0440\u0435\u0448\u0435\u043d\u0438\u044f<\/h3>\n<p>\u041f\u0440\u043e\u0435\u043a\u0442 \u043e\u0441\u043d\u043e\u0432\u0430\u043d \u043d\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u043d\u043e\u0439 \u0441 \u043d\u0443\u043b\u044f SDR-\u043f\u043b\u0430\u0442\u0435 \u0441 FPGA \u0438 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u043c PCIe:  <\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/ad7\/248\/23c\/ad724823c2a138ea8d7d01ff2dc59c76.png\" width=\"1209\" height=\"357\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/ad7\/248\/23c\/ad724823c2a138ea8d7d01ff2dc59c76.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/ad7\/248\/23c\/ad724823c2a138ea8d7d01ff2dc59c76.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/7c2\/49d\/aaa\/7c249daaa20ef3e1650586f45676a884.jpg\" width=\"4000\" height=\"1868\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/7c2\/49d\/aaa\/7c249daaa20ef3e1650586f45676a884.jpg 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/7c2\/49d\/aaa\/7c249daaa20ef3e1650586f45676a884.jpg 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/389\/679\/d11\/389679d1152275cbbe28f9c165d5c987.jpeg\" width=\"2048\" height=\"977\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/389\/679\/d11\/389679d1152275cbbe28f9c165d5c987.jpeg 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/389\/679\/d11\/389679d1152275cbbe28f9c165d5c987.jpeg 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p><strong>\u041e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430:<\/strong><\/p>\n<div>\n<div class=\"table\">\n<table>\n<tbody>\n<tr>\n<th>\n<p align=\"left\">\u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442<\/p>\n<\/th>\n<th>\n<p align=\"left\">\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435<\/p>\n<\/th>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\"><strong>FPGA<\/strong><\/p>\n<\/td>\n<td>\n<p align=\"left\">Xilinx Artix-7 (XC7A200T)<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\"><strong>RF-\u0442\u0440\u0430\u043d\u0441\u0438\u0432\u0435\u0440<\/strong><\/p>\n<\/td>\n<td>\n<p align=\"left\">Analog Devices AD9361\u00a0(70 MHz \u2013 6 GHz)<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\"><strong>GPS-\u043c\u043e\u0434\u0443\u043b\u044c<\/strong><\/p>\n<\/td>\n<td>\n<p align=\"left\">SIM68 (NMEA 0183 Output)<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\"><strong>DDR<\/strong><\/p>\n<\/td>\n<td>\n<p align=\"left\">MT41K256M16HA-125 AAT<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\"><strong>\u0425\u043e\u0441\u0442-\u043f\u043b\u0430\u0442\u0430<\/strong><\/p>\n<\/td>\n<td>\n<p align=\"left\"><a href=\"https:\/\/www.lattepanda.com\/lattepanda-sigma\" rel=\"noopener noreferrer nofollow\">LattePanda Sigma<\/a><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\"><strong>\u0418\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438<\/strong><\/p>\n<\/td>\n<td>\n<p align=\"left\">PCIe Gen1 x4\u00a0(10 Gbps \u0447\u0435\u0440\u0435\u0437 \u0440\u0430\u0437\u044a\u0451\u043c M.2)<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\"><strong>\u041f\u0435\u0440\u0435\u0434\u0430\u0447\u0430 \u0434\u0430\u043d\u043d\u044b\u0445<\/strong><\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0427\u0435\u0440\u0435\u0437 XDMA \u0438 AXI \u0448\u0438\u043d\u0443<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\"><strong>UART-\u043f\u0435\u0440\u0438\u0444\u0435\u0440\u0438\u044f<\/strong><\/p>\n<\/td>\n<td>\n<p align=\"left\">AXI UARTLite IP Core (9600 \u0431\u043e\u0434)<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\"><strong>\u0424\u043e\u0440\u043c-\u0444\u0430\u043a\u0442\u043e\u0440<\/strong><\/p>\n<\/td>\n<td>\n<p align=\"left\">M.2 2280 (80mm \u00d7 22mm)<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<h4>\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0441\u0438\u0441\u0442\u0435\u043c\u044b<\/h4>\n<p>\u0421\u0438\u0441\u0442\u0435\u043c\u0430 \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0438 \u0438\u0445 \u0441\u0432\u044f\u0437\u0435\u0439:<\/p>\n<ol>\n<li>\n<p><strong>SIM68 (GPS Module)<\/strong><\/p>\n<ul>\n<li>\n<p>\u042d\u0442\u043e GPS-\u043c\u043e\u0434\u0443\u043b\u044c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u0447\u0435\u0440\u0435\u0437 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 UART.<\/p>\n<\/li>\n<li>\n<p>\u0421\u0432\u044f\u0437\u0430\u043d \u0441 <strong>UartLite (UART Controller)<\/strong> \u0447\u0435\u0440\u0435\u0437 <strong>UART<\/strong>.<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><strong>UartLite (UART Controller)<\/strong><\/p>\n<ul>\n<li>\n<p>\u041a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440 UART, \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u044e\u0449\u0438\u0439 \u0434\u0430\u043d\u043d\u044b\u0435 \u043e\u0442 GPS-\u043c\u043e\u0434\u0443\u043b\u044f.<\/p>\n<\/li>\n<li>\n<p>\u0421\u0432\u044f\u0437\u0430\u043d \u0441 <strong>XDMA (PCIe DMA)<\/strong> \u0447\u0435\u0440\u0435\u0437 \u0448\u0438\u043d\u0443 <strong>AXI<\/strong>.<\/p>\n<p><a href=\"https:\/\/docs.amd.com\/v\/u\/en-US\/pg142-axi-uartlite\" rel=\"noopener noreferrer nofollow\">AXI UARTLite Product Guide (PG142)<\/a><\/p>\n<p><a href=\"https:\/\/docs.amd.com\/r\/en-US\/pg059-axi-interconnect\" rel=\"noopener noreferrer nofollow\">AXI Interconnect Product Guide (PG059)<\/a><\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><strong>XDMA (PCIe DMA)<\/strong><\/p>\n<ul>\n<li>\n<p>\u041a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440 \u043f\u0440\u044f\u043c\u043e\u0433\u043e \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u043f\u0430\u043c\u044f\u0442\u0438 (DMA) \u0447\u0435\u0440\u0435\u0437 PCIe. (<a href=\"https:\/\/docs.amd.com\/r\/en-US\/pg195-pcie-dma\" rel=\"noopener noreferrer nofollow\">AXI PCIe DMA Product Guide (PG195)<\/a>)<\/p>\n<\/li>\n<li>\n<p>\u0421\u0432\u044f\u0437\u0430\u043d \u0441 <strong>CPU (Latte Panda Sigma)<\/strong> \u0447\u0435\u0440\u0435\u0437 <strong>PCIe<\/strong>.<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><strong>CPU (Latte Panda Sigma)<\/strong><\/p>\n<ul>\n<li>\n<p>\u0426\u0435\u043d\u0442\u0440\u0430\u043b\u044c\u043d\u044b\u0439 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u043e\u0442 XDMA.<\/p>\n<\/li>\n<li>\n<p>\u0421\u0432\u044f\u0437\u0430\u043d \u0441 <strong>Linux Kernel<\/strong> \u0447\u0435\u0440\u0435\u0437 \u043e\u0431\u043e\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 <strong>User-space<\/strong> (\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f).<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><strong>Linux Kernel<\/strong><\/p>\n<ul>\n<li>\n<p>\u042f\u0434\u0440\u043e \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b Linux, \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0435\u0435 \u043d\u0430 CPU.<\/p>\n<\/li>\n<li>\n<p>\u0421\u0432\u044f\u0437\u0430\u043d \u0441 <strong>User Application<\/strong> \u0447\u0435\u0440\u0435\u0437 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u044b <strong>TTY \/ Python<\/strong>.<\/p>\n<p><a href=\"https:\/\/docs.kernel.org\/driver-api\/tty\/index.html\" rel=\"noopener noreferrer nofollow\">Linux TTY Documentation<\/a><\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><strong>User Application<\/strong><\/p>\n<ul>\n<li>\n<p>\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0443\u0435\u0442 \u0441 \u044f\u0434\u0440\u043e\u043c Linux \u0434\u043b\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u0434\u0430\u043d\u043d\u044b\u043c, \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u0447\u0435\u0440\u0435\u0437 TTY-\u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 \u0438\u043b\u0438 \u0441\u043a\u0440\u0438\u043f\u0442\u044b \u043d\u0430 Python.<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<h4>2.1 \u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u043d\u0430\u044f \u0441\u0445\u0435\u043c\u0430 \u0441\u0438\u0441\u0442\u0435\u043c\u044b<\/h4>\n<p>\u041d\u0430 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0438 \u043d\u0438\u0436\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0430 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u043d\u0430\u044f \u0441\u0445\u0435\u043c\u0430 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0441 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u043c \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u043e\u043c: <\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/aec\/c84\/6c1\/aecc846c10b00039a10d6f75998426cf.png\" width=\"422\" height=\"723\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/aec\/c84\/6c1\/aecc846c10b00039a10d6f75998426cf.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/aec\/c84\/6c1\/aecc846c10b00039a10d6f75998426cf.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u0440\u043e\u0445\u043e\u0434\u044f\u0442 \u043f\u043e \u0446\u0435\u043f\u043e\u0447\u043a\u0435:<\/p>\n<ol>\n<li>\n<p><strong>SIM68<\/strong> \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u0442 <a href=\"https:\/\/receiverhelp.trimble.com\/alloy-gnss\/en-us\/NMEA-0183messages_MessageOverview.html\" rel=\"noopener noreferrer nofollow\">NMEA<\/a>-\u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0432 <strong>UartLite<\/strong> \u043d\u0430 FPGA \u0447\u0435\u0440\u0435\u0437 <strong>UART<\/strong><\/p>\n<\/li>\n<li>\n<p><strong>UartLite<\/strong> \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0443\u0435\u0442 \u0441 <strong>XDMA (PCIe DMA)<\/strong> \u0447\u0435\u0440\u0435\u0437 <strong>AXI<\/strong>.<\/p>\n<\/li>\n<li>\n<p><strong>XDMA<\/strong> \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u0447\u0435\u0440\u0435\u0437 <strong>PCIe<\/strong> \u0432 <strong>CPU (Latte Panda Sigma)<\/strong>.<\/p>\n<\/li>\n<li>\n<p><strong>CPU<\/strong> \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 <strong>user-space<\/strong> \u0438 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0443\u0435\u0442 \u0441 <strong>\u044f\u0434\u0440\u043e\u043c Linux<\/strong>.<\/p>\n<\/li>\n<li>\n<p><strong>Linux Kernel<\/strong> \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 <strong>TTY \/ Python API<\/strong> \u0434\u043b\u044f <strong>\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f<\/strong> (<code>\/dev\/ttyUL0<\/code>).<\/p>\n<\/li>\n<li>\n<p><strong>User Application<\/strong> \u2013 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0443\u0435\u0442 \u0441 UART \u0447\u0435\u0440\u0435\u0437 Python \u0438\u043b\u0438 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b.<\/p>\n<\/li>\n<\/ol>\n<p>\u041d\u0430 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0438 \u043d\u0438\u0436\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0430 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u043d\u0430\u044f \u0441\u0445\u0435\u043c\u0430 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u043f\u0440\u0438 \u043f\u0440\u044f\u043c\u043e\u043c \u0434\u043e\u0441\u0442\u0443\u043f\u0435 \u0447\u0435\u0440\u0435\u0437 Python:<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/4fd\/5f3\/87a\/4fd5f387ad907716969cec02369f0a84.png\" alt=\"Screenshot from 20250410 171712png\" width=\"743\" height=\"264\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/4fd\/5f3\/87a\/4fd5f387ad907716969cec02369f0a84.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/4fd\/5f3\/87a\/4fd5f387ad907716969cec02369f0a84.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>Screenshot from 20250410 171712png<\/figcaption><\/div>\n<\/figure>\n<p>\u0414\u0430\u043d\u043d\u044b\u0435 \u043f\u0440\u043e\u0445\u043e\u0434\u044f\u0442 \u043f\u043e \u0446\u0435\u043f\u043e\u0447\u043a\u0435:<\/p>\n<ol>\n<li>\n<p><strong>SIM68<\/strong> \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u0442 <a href=\"https:\/\/receiverhelp.trimble.com\/alloy-gnss\/en-us\/NMEA-0183messages_MessageOverview.html\" rel=\"noopener noreferrer nofollow\">NMEA<\/a>-\u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0432 <strong>UartLite<\/strong> \u043d\u0430 FPGA \u0447\u0435\u0440\u0435\u0437 <strong>UART<\/strong>.<\/p>\n<\/li>\n<li>\n<p><strong>UartLite<\/strong> \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0443\u0435\u0442 \u0441 <strong>XDMA (PCIe DMA)<\/strong> \u0447\u0435\u0440\u0435\u0437 <strong>AXI<\/strong>.<\/p>\n<\/li>\n<li>\n<p><strong>XDMA<\/strong> \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u0447\u0435\u0440\u0435\u0437 <strong>PCIe<\/strong> \u0432 <strong>CPU (Latte Panda Sigma)<\/strong>.<\/p>\n<\/li>\n<li>\n<p><strong>CPU<\/strong> \u0447\u0435\u0440\u0435\u0437 <code>\/dev\/xdma0_user<\/code> \u043c\u0430\u043f\u0438\u0442 \u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u043e \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <strong>mmap<\/strong>.<\/p>\n<\/li>\n<li>\n<p><strong>Python Application<\/strong> \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u0447\u0438\u0442\u0430\u0435\u0442 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u044b UARTlite (RX FIFO \/ TX FIFO), \u043c\u0438\u043d\u0443\u044f \u0434\u0440\u0430\u0439\u0432\u0435\u0440 \u044f\u0434\u0440\u0430.<\/p>\n<\/li>\n<\/ol>\n<p><strong>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c<\/strong>, \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0431\u0435\u0437 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0433\u043e Linux TTY-\u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430, \u0447\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442:<\/p>\n<ul>\n<li>\n<p>\u041c\u0438\u043d\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u043a\u043b\u0430\u0434\u043d\u044b\u0435 \u0440\u0430\u0441\u0445\u043e\u0434\u044b \u043d\u0430 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u0435 \u0432\u044b\u0437\u043e\u0432\u044b.<\/p>\n<\/li>\n<li>\n<p>\u0421\u043d\u0438\u0437\u0438\u0442\u044c \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u043d\u0430 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440 \u0437\u0430 \u0441\u0447\u0451\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f <strong>async IO<\/strong>.<\/p>\n<\/li>\n<li>\n<p>\u0411\u044b\u0441\u0442\u0440\u043e \u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438 \u043e\u0442\u043b\u0430\u0436\u0438\u0432\u0430\u0442\u044c \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 FPGA.<\/p>\n<\/li>\n<\/ul>\n<p>\u041d\u0430 \u0434\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u0435 \u043d\u0438\u0436\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u043e, \u043a\u0430\u043a \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043e\u0431\u043c\u0435\u043d \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u043c\u0435\u0436\u0434\u0443 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u043c\u0438 \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0435:<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/817\/863\/303\/8178633038d995a51a692ac5a5925b9e.png\" width=\"852\" height=\"529\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/817\/863\/303\/8178633038d995a51a692ac5a5925b9e.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/817\/863\/303\/8178633038d995a51a692ac5a5925b9e.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<h4>2.2 \u0411\u043b\u043e\u043a-\u0441\u0445\u0435\u043c\u0430 \u0432 Vivado<\/h4>\n<ul>\n<li>\n<p>\u0412 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f <strong>XDMA (PCIe-DMA Bridge)<\/strong><\/p>\n<\/li>\n<li>\n<p>AXI Interconnect \u0441\u0432\u044f\u0437\u044b\u0432\u0430\u0435\u0442 <strong>XDMA<\/strong> \u0441 <strong>AXI Register Slice<\/strong>, <strong>AXI UARTLite<\/strong><\/p>\n<\/li>\n<li>\n<p><strong>AXI UARTLite \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d \u043a \u0441\u0438\u0441\u0442\u0435\u043c\u0435 \u0447\u0435\u0440\u0435\u0437 AXI Interconnect \u0438 \u043a GPS \u043c\u043e\u0434\u0443\u043b\u044e SIM68 <\/strong><\/p>\n<\/li>\n<li>\n<p>\u0415\u0441\u0442\u044c \u0442\u0430\u043a\u0436\u0435 <strong>AXI GPIO<\/strong>, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f*<\/p>\n<\/li>\n<\/ul>\n<p><strong>\u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043f\u043e\u0442\u043e\u043a \u0434\u0430\u043d\u043d\u044b\u0445:<\/strong><br \/><strong>FPGA<\/strong> \u2194 <strong>AXI Interconnect<\/strong> \u2194 <strong>AXI UARTLite<\/strong> \u2194 <strong>PCIe XDMA<\/strong> \u2194 <strong>CPU\/Linux<\/strong><\/p>\n<p>\u041d\u0438\u0436\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u0441\u043a\u0440\u0438\u043d \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0432 Vivado \u0438\u0437 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430:<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/421\/b30\/70d\/421b3070d3783464d59a4f6930e0ec20.png\" alt=\"\u0421\u043d\u0438\u043c\u043e\u043a \u044d\u043a\u0440\u0430\u043d\u0430 20250313 211436png\" width=\"2256\" height=\"1139\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/421\/b30\/70d\/421b3070d3783464d59a4f6930e0ec20.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/421\/b30\/70d\/421b3070d3783464d59a4f6930e0ec20.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0421\u043d\u0438\u043c\u043e\u043a \u044d\u043a\u0440\u0430\u043d\u0430 20250313 211436png<\/figcaption><\/div>\n<\/figure>\n<p>\u0438\u043b\u0438 \u043f\u0440\u043e\u0441\u0442\u0430\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f UartLite:<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/010\/063\/fbb\/010063fbb0b4be9aa0cface9f23a9619.png\" alt=\"Screenshot from 20250410 171633png\" width=\"1146\" height=\"382\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/010\/063\/fbb\/010063fbb0b4be9aa0cface9f23a9619.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/010\/063\/fbb\/010063fbb0b4be9aa0cface9f23a9619.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>Screenshot from 20250410 171633png<\/figcaption><\/div>\n<\/figure>\n<h4>2.3 \u0420\u0430\u0437\u0431\u043e\u0440 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 XDMA \u0438 UartLite:<\/h4>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/ef0\/7a2\/411\/ef07a24117f597042a623a70716cd66d.png\" width=\"1022\" height=\"773\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/ef0\/7a2\/411\/ef07a24117f597042a623a70716cd66d.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/ef0\/7a2\/411\/ef07a24117f597042a623a70716cd66d.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<h3>AXI UARTLite (\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 IP)<\/h3>\n<ul>\n<li>\n<p><strong>\u0427\u0430\u0441\u0442\u043e\u0442\u0430 AXI CLK:<\/strong> <code>62.5 \u041c\u0413\u0446<\/code><\/p>\n<\/li>\n<li>\n<p><strong>\u0421\u043a\u043e\u0440\u043e\u0441\u0442\u044c UART:<\/strong> <code>9600 \u0431\u043e\u0434<\/code><\/p>\n<\/li>\n<li>\n<p><strong>\u0414\u043b\u0438\u043d\u0430 \u0434\u0430\u043d\u043d\u044b\u0445:<\/strong> <code>8 \u0431\u0438\u0442<\/code><\/p>\n<\/li>\n<li>\n<p><strong>\u0427\u0435\u0442\u043d\u043e\u0441\u0442\u044c (Parity):<\/strong> <code>\u041e\u0442\u043a\u043b\u044e\u0447\u0435\u043d\u0430 (No Parity)<\/code><\/p>\n<\/li>\n<\/ul>\n<p>\u042d\u0442\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0435 \u0434\u043b\u044f UARTLite, \u043d\u043e \u0435\u0441\u043b\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e <strong>\u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0442\u044c \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c<\/strong> \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438, \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u0441\u0442\u0430\u0432\u0438\u0442\u044c <code>115200 \u0431\u043e\u0434<\/code>.<\/p>\n<h3>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 DMA (PCIe : DMA)<\/h3>\n<p><a href=\"https:\/\/docs.amd.com\/r\/en-US\/pg195-pcie-dma\" rel=\"noopener noreferrer nofollow\">AXI PCIe DMA Product Guide (PG195)<\/a><\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/33d\/5f8\/838\/33d5f8838872563ef80bfe26703e1311.png\" width=\"1347\" height=\"943\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/33d\/5f8\/838\/33d5f8838872563ef80bfe26703e1311.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/33d\/5f8\/838\/33d5f8838872563ef80bfe26703e1311.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/708\/a37\/645\/708a37645afd87b13be966ed7efaffe8.png\" width=\"1347\" height=\"943\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/708\/a37\/645\/708a37645afd87b13be966ed7efaffe8.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/708\/a37\/645\/708a37645afd87b13be966ed7efaffe8.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/afe\/e03\/5ac\/afee035ac862433563f562dd28522253.png\" width=\"1347\" height=\"943\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/afe\/e03\/5ac\/afee035ac862433563f562dd28522253.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/afe\/e03\/5ac\/afee035ac862433563f562dd28522253.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/714\/f6a\/47f\/714f6a47fffd9f8fc5ba13028d7939b1.png\" width=\"1347\" height=\"943\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/714\/f6a\/47f\/714f6a47fffd9f8fc5ba13028d7939b1.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/714\/f6a\/47f\/714f6a47fffd9f8fc5ba13028d7939b1.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/283\/b77\/832\/283b77832991b06f88bf112f5a0872e9.png\" width=\"1347\" height=\"943\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/283\/b77\/832\/283b77832991b06f88bf112f5a0872e9.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/283\/b77\/832\/283b77832991b06f88bf112f5a0872e9.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p><strong>\u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043a\u0430\u043d\u0430\u043b\u043e\u0432<\/strong><\/p>\n<ul>\n<li>\n<p><strong>1 \u043a\u0430\u043d\u0430\u043b \u043d\u0430 \u0447\u0442\u0435\u043d\u0438\u0435 (H2C)<\/strong><\/p>\n<\/li>\n<li>\n<p><strong>1 \u043a\u0430\u043d\u0430\u043b \u043d\u0430 \u0437\u0430\u043f\u0438\u0441\u044c (C2H)<\/strong><\/p>\n<\/li>\n<li>\n<p>\u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e <strong>Request IDs<\/strong>: 32 (\u0447\u0442\u0435\u043d\u0438\u0435), 16 (\u0437\u0430\u043f\u0438\u0441\u044c)<\/p>\n<\/li>\n<li>\n<p><strong>AXI ID Width<\/strong>: 4 (\u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0439 \u0432 AXI)<\/p>\n<p><strong>Descriptor Bypass (\u041e\u0442\u043a\u043b\u044e\u0447\u0435\u043d)<\/strong><\/p>\n<\/li>\n<li>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0435 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0431\u0443\u0444\u0435\u0440\u0430\u043c\u0438 (\u0431\u0435\u0437 \u0431\u0430\u0439\u043f\u0430\u0441\u0430).<\/p>\n<\/li>\n<\/ul>\n<h3>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043f\u0440\u0435\u0440\u044b\u0432\u0430\u043d\u0438\u0439 (PCIe : MISC)<\/h3>\n<p><strong>\u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043f\u0440\u0435\u0440\u044b\u0432\u0430\u043d\u0438\u0439:<\/strong> 16<br \/> <strong>MSI \u0432\u043a\u043b\u044e\u0447\u0435\u043d<\/strong> (Message Signaled Interrupts)<br \/> <strong>\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u044b\u0435 \u0442\u0435\u0433\u0438 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u044b<\/strong> (Extended Tag Field)<\/p>\n<h3>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 BAR (PCIe : BARS)<\/h3>\n<p><strong>PCIe \u2192 AXI Lite Master Interface<\/strong><\/p>\n<ul>\n<li>\n<p><strong>\u0420\u0430\u0437\u043c\u0435\u0440 \u043f\u0430\u043c\u044f\u0442\u0438:<\/strong> 1MB<\/p>\n<\/li>\n<li>\n<p><strong>\u0410\u0434\u0440\u0435\u0441:<\/strong> <code>0x00000000<\/code> <strong>PCIe \u2192 DMA Interface<\/strong> \u0432\u043a\u043b\u044e\u0447\u0435\u043d<\/p>\n<\/li>\n<\/ul>\n<h3>\u0418\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u044b \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 (PCIe ID)<\/h3>\n<p><strong>Vendor ID:<\/strong> <code>10EE<\/code> (Xilinx)<br \/> <strong>Device ID:<\/strong> <code>7011<\/code><br \/> <strong>Class Code:<\/strong> <code>120000<\/code> (\u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e \u043f\u0430\u043c\u044f\u0442\u0438)<\/p>\n<h3>\u0411\u0430\u0437\u043e\u0432\u044b\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 PCIe (Basic)<\/h3>\n<p>[PCIe Base Specification (official summary)](<a href=\"https:\/\/pcisig.com\/specifications\" rel=\"noopener noreferrer nofollow\">Specifications | PCI-SIG<\/a>)<\/p>\n<p><strong>PCIe x1, 2.5 GT\/s<\/strong><br \/> <strong>AXI Address Width: 64-bit<\/strong><br \/> <strong>AXI Data Width: 64-bit<\/strong><br \/> <strong>AXI Clock: 125 MHz<\/strong><br \/> <strong>\u0420\u0435\u0436\u0438\u043c: AXI Memory Mapped<\/strong><\/p>\n<p>\u0410\u0434\u0440\u0435\u0441\u0441 UartLite: <\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/c08\/3b4\/cc4\/c083b4cc4949130cd4e721c8e94cfd87.png\" width=\"955\" height=\"27\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/c08\/3b4\/cc4\/c083b4cc4949130cd4e721c8e94cfd87.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/c08\/3b4\/cc4\/c083b4cc4949130cd4e721c8e94cfd87.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<h4>2.2 \u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 SDR \u043a \u043c\u0430\u0442\u0435\u0440\u0438\u043d\u0441\u043a\u043e\u0439 \u043f\u043b\u0430\u0442\u0435<\/h4>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/bed\/2a0\/1af\/bed2a01af3dc7aeb0ad187abd8f5e8a8.jpeg\" alt=\"1696959565663 1jpeg\" width=\"2048\" height=\"977\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/bed\/2a0\/1af\/bed2a01af3dc7aeb0ad187abd8f5e8a8.jpeg 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/bed\/2a0\/1af\/bed2a01af3dc7aeb0ad187abd8f5e8a8.jpeg 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>1696959565663 1jpeg<\/figcaption><\/div>\n<\/figure>\n<hr\/>\n<h3>3. \u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430<\/h3>\n<h4>3.1 \u041f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0430 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f<\/h4>\n<p><strong>\u0410\u043f\u043f\u0430\u0440\u0430\u0442\u043d\u0430\u044f \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430:<\/strong><\/p>\n<ul>\n<li>\n<p><strong>SDR-\u043f\u043b\u0430\u0442\u0430:<\/strong> \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u043d\u0430\u044f \u043c\u043d\u043e\u0439, FPGA Artix-7 200T<\/p>\n<\/li>\n<li>\n<p><strong>GPS-\u043c\u043e\u0434\u0443\u043b\u044c:<\/strong> SIM68<\/p>\n<\/li>\n<li>\n<p><strong>\u0418\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u044b:<\/strong> PCIe, UART<\/p>\n<\/li>\n<li>\n<p><strong>\u041c\u0430\u0442\u0435\u0440\u0438\u043d\u0441\u043a\u0430\u044f \u043f\u043b\u0430\u0442\u0430<\/strong>: Latte Panda Sigma<\/p>\n<\/li>\n<\/ul>\n<p><strong>\u041f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u043e\u0435 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0435\u043d\u0438\u0435:<\/strong><\/p>\n<ul>\n<li>\n<p><strong>\u041e\u0421:<\/strong> Linux Kernel 6.x+<\/p>\n<\/li>\n<li>\n<p><strong>\u0418\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b:<\/strong> Vivado, Python, GCC<\/p>\n<\/li>\n<li>\n<p><strong>\u041e\u0442\u043b\u0430\u0434\u043a\u0430:<\/strong> <code>dmesg<\/code>, <code>minicom<\/code><\/p>\n<\/li>\n<\/ul>\n<hr\/>\n<h4>3.2 \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439<\/h4>\n<pre><code class=\"bash\">sudo apt update sudo apt install -y build-essential dkms linux-headers-$(uname -r) git sudo apt install -y pciutils lshw sudo apt install -y gcc-13 g++-13  sudo apt install -y gpsd gpsd-clients<\/code><\/pre>\n<p><strong>\u0427\u0442\u043e \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c?<\/strong><\/p>\n<ul>\n<li>\n<p><code>build-essential<\/code> \u2014 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u0441\u0431\u043e\u0440\u043a\u0438 (<code>gcc<\/code>, <code>make<\/code>, <code>binutils<\/code>)<\/p>\n<\/li>\n<li>\n<p><code>dkms<\/code> \u2014 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043c\u043e\u0434\u0443\u043b\u044f\u043c\u0438 \u044f\u0434\u0440\u0430<\/p>\n<\/li>\n<li>\n<p><code>linux-headers-$(uname -r)<\/code> \u2014 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u0447\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u044b \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u044f\u0434\u0440\u0430<\/p>\n<\/li>\n<li>\n<p><code>git<\/code> \u2014 \u0434\u043b\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u043e\u0432 \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430 XDMA<\/p>\n<\/li>\n<li>\n<p><code>pciutils<\/code> (<code>lspci<\/code>) \u2014 \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440 PCIe-\u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432<\/p>\n<\/li>\n<li>\n<p><code>lshw<\/code> \u2014 \u0434\u0435\u0442\u0430\u043b\u044c\u043d\u0430\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e\u0431 \u043e\u0431\u043e\u0440\u0443\u0434\u043e\u0432\u0430\u043d\u0438\u0438<\/p>\n<\/li>\n<li>\n<p><code>gcc-13<\/code>, <code>g++-13<\/code> \u2014 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440\u044b C \u0438 C++ \u0432\u0435\u0440\u0441\u0438\u0438 13<\/p>\n<\/li>\n<li>\n<p><code>gpsd<\/code>, <code>gpsd-clients<\/code> \u2014 \u0434\u0435\u043c\u043e\u043d\u044b \u0438 \u0443\u0442\u0438\u043b\u0438\u0442\u044b \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 GPS-\u043f\u0440\u0438\u0451\u043c\u043d\u0438\u043a\u0430\u043c\u0438<\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0432\u0435\u0440\u0441\u0438\u0438:<\/p>\n<pre><code class=\"bash\">gcc-13 --version<\/code><\/pre>\n<h4>3.3 \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043e\u0431\u043e\u0440\u0443\u0434\u043e\u0432\u0430\u043d\u0438\u044f<\/h4>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0443\u0431\u0435\u0434\u0438\u043c\u0441\u044f, \u0447\u0442\u043e <strong>PCIe-\u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e (FPGA)<\/strong> \u0440\u0430\u0441\u043f\u043e\u0437\u043d\u0430\u0451\u0442\u0441\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u043e\u0439:<\/p>\n<pre><code class=\"bash\">lspci -d 10ee:<\/code><\/pre>\n<p>\u0415\u0441\u043b\u0438 <strong>XDMA-\u043a\u0430\u0440\u0442\u0430 \u0432\u0438\u0434\u043d\u0430<\/strong>, \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0432\u043e\u0434 \u0442\u0438\u043f\u0430:<\/p>\n<pre><code class=\"bash\">59:00.0 Memory controller: Xilinx Corporation Device 7011<\/code><\/pre>\n<p>\u0412\u043e\u0442 \u0447\u0442\u043e \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u0443 \u043c\u0435\u043d\u044f:<\/p>\n<h4>3.4 \u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430<\/h4>\n<h3>\u041f\u0440\u0438\u043d\u0446\u0438\u043f \u0440\u0430\u0431\u043e\u0442\u044b \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430<\/h3>\n<p>\u041f\u0440\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0435 \u043c\u043e\u0434\u0443\u043b\u044f \u0434\u0440\u0430\u0439\u0432\u0435\u0440 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u0442 <strong>PCIe<\/strong>-\u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e \u0441 <strong>Vendor ID<\/strong> <code>0x10EE<\/code> \u0438 <strong>Device ID<\/strong> <code>0x7011<\/code>. \u041f\u043e\u0441\u043b\u0435 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043e\u043d \u0441\u043e\u0437\u0434\u0430\u0451\u0442 <strong>TTY<\/strong>-\u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e <code>\/dev\/ttyUL0<\/code>. \u0412\u0445\u043e\u0434\u044f\u0449\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437 <strong>UARTlite<\/strong> \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c workqueue, \u043f\u0435\u0440\u0435\u0434\u0430\u044e\u0442\u0441\u044f \u0432 \u0431\u0443\u0444\u0435\u0440 <strong>TTY<\/strong> \u0438 \u0441\u0442\u0430\u043d\u043e\u0432\u044f\u0442\u0441\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u0447\u0435\u0440\u0435\u0437 \u0444\u0443\u043d\u043a\u0446\u0438\u044e <code>tty_flip_buffer_push<\/code> (\u043e\u043d\u0430 \u0441\u043e\u043e\u0431\u0449\u0430\u0435\u0442 \u044f\u0434\u0440\u0443 Linux, \u0447\u0442\u043e <strong>\u0432 \u043f\u0440\u0438\u0451\u043c\u043d\u043e\u043c \u0431\u0443\u0444\u0435\u0440\u0435<\/strong> \u043f\u043e\u044f\u0432\u0438\u043b\u0438\u0441\u044c \u043d\u043e\u0432\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435, \u0438 \u044d\u0442\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u043d\u0443\u0436\u043d\u043e <strong>\u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u0432 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0435 \u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u043e<\/strong> \u0438 \u0431\u0435\u0437 \u0435\u0451 \u0432\u044b\u0437\u043e\u0432\u0430 \u0434\u0430\u043d\u043d\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u0432\u0438\u0441\u0435\u0442\u044c \u0432\u043d\u0443\u0442\u0440\u0438 \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430 \u0438 <strong>\u043d\u0435 \u0434\u043e\u0439\u0434\u0443\u0442<\/strong> \u0434\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f).<\/p>\n<p><a href=\"https:\/\/docs.kernel.org\/driver-api\/tty\/index.html\" rel=\"noopener noreferrer nofollow\">Linux TTY Documentation<\/a><\/p>\n<h3>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442<\/h3>\n<pre><code class=\"cpp\">#define DRIVER_NAME \"uartlite_xdma\" \/\/ \u0418\u043c\u044f \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430 #define VENDOR_ID 0x10EE  \/\/ Xilinx Vendor ID #define DEVICE_ID 0x7011  \/\/ Device ID \u0434\u043b\u044f FPGA Hard PCIe block #define UARTLITE_BASE_OFFSET 0x40000 \/\/ \u0411\u0430\u0437\u043e\u0432\u044b\u0439 \u0430\u0434\u0440\u0435\u0441 AXI**<\/code><\/pre>\n<ul>\n<li>\n<p><code>VENDOR_ID = 0x10EE<\/code> \u2014 \u044d\u0442\u043e <strong>Xilinx<\/strong> (\u0437\u0430\u0434\u0430\u0435\u0442\u0441\u044f \u0432 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 IP \u044f\u0434\u0440\u0430 \u0432 Vivado, \u043a\u0430\u0436\u0434\u044b\u0439 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c PCIe-\u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432 \u0438\u043c\u0435\u0435\u0442 \u0441\u0432\u043e\u0439 ID).<\/p>\n<\/li>\n<li>\n<p><code>DEVICE_ID = 0x7011<\/code> \u2014 <strong>\u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430<\/strong> (\u0437\u0430\u0434\u0430\u0435\u0442\u0441\u044f \u0432 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 IP \u044f\u0434\u0440\u0430 \u0432 Vivado).<\/p>\n<\/li>\n<li>\n<p><code>UARTLITE_BASE_OFFSET = 0x40000<\/code> \u2014 <strong>\u0441\u043c\u0435\u0449\u0435\u043d\u0438\u0435 \u0432 \u043f\u0430\u043c\u044f\u0442\u0438<\/strong>, \u0433\u0434\u0435 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f UARTlite \u0432 \u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u0435 XDMA (\u0432 \u043c\u043e\u0435\u043c \u043f\u0440\u043c\u0435\u0440\u0435 <code>0x40000<\/code> , \u043e\u0440\u043f\u0435\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u043c \u0432 Vivado)<\/p>\n<\/li>\n<\/ul>\n<h3>\u0410\u0434\u0440\u0435\u0441\u0430 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u043e\u0432 \u0432 \u043f\u0430\u043c\u044f\u0442\u0438:<\/h3>\n<p>\u0412 \u0441\u043e\u043e\u0442\u0432\u0435\u0441\u0442\u0432\u0438\u0438 \u0441 <a href=\"https:\/\/docs.amd.com\/v\/u\/en-US\/pg142-axi-uartlite\" rel=\"noopener noreferrer nofollow\">datashhet AXI UartLite<\/a><\/p>\n<pre><code class=\"cpp\">#define UARTLITE_RX_FIFO  0x00  \/\/ FIFO \u043f\u0440\u0438\u0451\u043c\u0430 #define UARTLITE_TX_FIFO  0x04  \/\/ FIFO \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 #define UARTLITE_STATUS   0x08  \/\/ \u0420\u0435\u0433\u0438\u0441\u0442\u0440 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f #define UARTLITE_CONTROL  0x0C  \/\/ \u0420\u0435\u0433\u0438\u0441\u0442\u0440 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f<\/code><\/pre>\n<ul>\n<li>\n<p><strong>RX_FIFO (0x00)<\/strong> \u2014 \u0447\u0438\u0442\u0430\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0435, \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0435 \u043e\u0442 UART.<\/p>\n<\/li>\n<li>\n<p><strong>TX_FIFO (0x04)<\/strong> \u2014 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438.<\/p>\n<\/li>\n<li>\n<p><strong>STATUS (0x08)<\/strong> \u2014 \u0444\u043b\u0430\u0433\u0438 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f (\u0434\u0430\u043d\u043d\u044b\u0435 \u0435\u0441\u0442\u044c? FIFO \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d?).<\/p>\n<\/li>\n<li>\n<p><strong>CONTROL (0x0C)<\/strong> \u2014 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 UARTlite.<\/p>\n<\/li>\n<\/ul>\n<h3>\u0424\u043b\u0430\u0433\u0438 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f<\/h3>\n<pre><code class=\"cpp\">#define STATUS_RXVALID    BIT(0) \/\/ \u0414\u0430\u043d\u043d\u044b\u0435 \u0435\u0441\u0442\u044c \u0432 RX FIFO #define STATUS_TXFULL     BIT(3) \/\/ TX FIFO \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d<\/code><\/pre>\n<ul>\n<li>\n<p><strong>RXVALID (\u0431\u0438\u0442 0)<\/strong> \u2014 <code>1<\/code>, \u0435\u0441\u043b\u0438 \u0432 RX FIFO \u0435\u0441\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435.<\/p>\n<\/li>\n<li>\n<p><strong>TXFULL (\u0431\u0438\u0442 3)<\/strong> \u2014 <code>1<\/code>, \u0435\u0441\u043b\u0438 TX FIFO \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d.<\/p>\n<\/li>\n<\/ul>\n<h3>\u041e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0434\u0430\u043d\u043d\u044b\u0445<\/h3>\n<pre><code class=\"cpp\">struct uartlite_priv {     void __iomem *base;     struct tty_port port;     struct work_struct rx_work; \/\/ \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a RX (workqueue)     bool running; };<\/code><\/pre>\n<p><strong>\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 <\/strong><code><strong>uartlite_priv<\/strong><\/code><strong> \u0445\u0440\u0430\u043d\u0438\u0442:<\/strong><\/p>\n<ul>\n<li>\n<p><code>base<\/code> \u2014 <strong>\u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c \u043d\u0430 \u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u0430\u0434\u0440\u0435\u0441 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430<\/strong> \u0432 PCIe.<\/p>\n<\/li>\n<li>\n<p><code>port<\/code> \u2014 <strong>TTY-\u043f\u043e\u0440\u0442<\/strong> \u0434\u043b\u044f \u0441\u0432\u044f\u0437\u0438 \u0441 Linux.<\/p>\n<\/li>\n<li>\n<p><code>rx_work<\/code> \u2014 <strong>\u0437\u0430\u0434\u0430\u0447\u0430<\/strong> \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 (workqueue).<\/p>\n<\/li>\n<li>\n<p><code>running<\/code> \u2014 <strong>\u0444\u043b\u0430\u0433 \u0440\u0430\u0431\u043e\u0442\u044b<\/strong> (\u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d, \u043f\u043e\u043a\u0430 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e \u0430\u043a\u0442\u0438\u0432\u043d\u043e).<\/p>\n<\/li>\n<\/ul>\n<h3>\u0424\u0443\u043d\u043a\u0446\u0438\u0438 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 UARTlite<\/h3>\n<pre><code class=\"cpp\">static int uartlite_tx_ready(struct uartlite_priv *priv) {     return !(ioread32(priv-&gt;base + UARTLITE_STATUS) &amp; STATUS_TXFULL); }<\/code><\/pre>\n<p><strong>\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442, \u043c\u043e\u0436\u043d\u043e \u043b\u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435:<\/strong><\/p>\n<ul>\n<li>\n<p>\u0427\u0438\u0442\u0430\u0435\u0442 <code>STATUS<\/code><\/p>\n<\/li>\n<li>\n<p>\u0415\u0441\u043b\u0438 <code>TXFULL == 0<\/code>, \u0437\u043d\u0430\u0447\u0438\u0442, \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c.<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"cpp\">static void uartlite_write_byte(struct uartlite_priv *priv, u8 val) {     iowrite32(val, priv-&gt;base + UARTLITE_TX_FIFO); }<\/code><\/pre>\n<p><strong>\u0417\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442 1 \u0431\u0430\u0439\u0442 \u0432 TX FIFO<\/strong>.<\/p>\n<pre><code class=\"cpp\">static int uartlite_rx_ready(struct uartlite_priv *priv) {     return ioread32(priv-&gt;base + UARTLITE_STATUS) &amp; STATUS_RXVALID; }<\/code><\/pre>\n<p><strong>\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442, \u0435\u0441\u0442\u044c \u043b\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 RX FIFO.<\/strong><\/p>\n<pre><code class=\"cpp\">static u8 uartlite_read_byte(struct uartlite_priv *priv) {     return ioread32(priv-&gt;base + UARTLITE_RX_FIFO); }<\/code><\/pre>\n<p><strong>\u0421\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u0442 1 \u0431\u0430\u0439\u0442 \u0438\u0437 RX FIFO.<\/strong><\/p>\n<h3>\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043f\u0440\u0438\u0451\u043c\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 (RX)<\/h3>\n<p>\u0412 \u044d\u0442\u043e\u043c \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f <strong>\u043f\u043e\u043b\u043b\u0438\u043d\u0433 RX FIFO<\/strong> (\u043f\u0440\u0438\u0451\u043c\u043d\u043e\u0433\u043e \u0431\u0443\u0444\u0435\u0440\u0430 UARTlite) \u0447\u0435\u0440\u0435\u0437 <strong>workqueue<\/strong> , \u0434\u043b\u044f \u0443\u043f\u0440\u043e\u0449\u0435\u043d\u0438\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438, \u0447\u0442\u043e \u0431\u044b \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u0440\u0430\u0431\u043e\u0442\u044b \u0447\u0435\u0440\u0435\u0437 \u043f\u0440\u0435\u0440\u044b\u0432\u0430\u043d\u0438\u044f.<\/p>\n<p><strong>\u041f\u043e\u043b\u043b\u0438\u043d\u0433 (polling)<\/strong> \u2014 \u044d\u0442\u043e \u043c\u0435\u0442\u043e\u0434 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445, \u043f\u0440\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u043c <strong>\u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440 \u043f\u0435\u0440\u0438\u043e\u0434\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430<\/strong> \u0438 \u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0435, \u0435\u0441\u043b\u0438 \u043e\u043d\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b.<\/p>\n<h3>\u041a\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043f\u043e\u043b\u043b\u0438\u043d\u0433 \u0432 \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0435?<\/h3>\n<p><strong>1. \u041f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0442 TTY-\u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e (<\/strong><code><strong>\/dev\/ttyUL0<\/strong><\/code><strong>)<\/strong><\/p>\n<ul>\n<li>\n<p>\u0412\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f <code>uartlite_tty_open()<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 <strong>\u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442 \u0444\u043b\u0430\u0433 <\/strong><code><strong>running = true<\/strong><\/code>.<\/p>\n<\/li>\n<li>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a <code>uartlite_rx_work()<\/code> \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <code>schedule_work()<\/code>.<\/p>\n<\/li>\n<\/ul>\n<p><strong>2. \u0424\u0443\u043d\u043a\u0446\u0438\u044f <\/strong><code><strong>uartlite_rx_work()<\/strong><\/code><strong> \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442, \u0435\u0441\u0442\u044c \u043b\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 RX FIFO<\/strong><\/p>\n<ul>\n<li>\n<p><strong>\u0427\u0438\u0442\u0430\u0435\u0442 \u0440\u0435\u0433\u0438\u0441\u0442\u0440 \u0441\u0442\u0430\u0442\u0443\u0441\u0430 (<\/strong><code><strong>UARTLITE_STATUS<\/strong><\/code><strong>)<\/strong>.<\/p>\n<\/li>\n<li>\n<p>\u0415\u0441\u043b\u0438 \u0432 <code>RX FIFO<\/code> \u0435\u0441\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 (<code>STATUS_RXVALID<\/code> = <code>1<\/code>), \u0447\u0438\u0442\u0430\u0435\u0442 \u0438 \u0431\u0443\u0444\u0435\u0440\u0438\u0437\u0443\u0435\u0442 \u0438\u0445 \u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u0442 \u0432 TTY (<code>tty_flip_buffer_push<\/code>,<code>tty_insert_flip_string<\/code>).<\/p>\n<\/li>\n<\/ul>\n<p><strong>3. \u0415\u0441\u043b\u0438 FIFO \u043d\u0435 \u043f\u0443\u0441\u0442, \u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u044e\u0442\u0441\u044f \u0432 TTY-\u043f\u043e\u0434\u0441\u0438\u0441\u0442\u0435\u043c\u0443<\/strong><\/p>\n<ul>\n<li>\n<p>\u0412\u044b\u0437\u044b\u0432\u0430\u044e\u0442\u0441\u044f:<\/p>\n<pre><code class=\"cpp\">tty_insert_flip_string(&amp;priv-&gt;port, buf, count);  tty_flip_buffer_push(&amp;priv-&gt;port);<\/code><\/pre>\n<\/li>\n<li>\n<p>\u0414\u0430\u043d\u043d\u044b\u0435 \u0441\u0442\u0430\u043d\u043e\u0432\u044f\u0442\u0441\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0432 <code>\/dev\/ttyUL0<\/code>.<\/p>\n<\/li>\n<\/ul>\n<p><strong>4. \u041f\u043e\u0441\u043b\u0435 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a <\/strong><code><strong>uartlite_rx_work()<\/strong><\/code><strong> \u0441\u0430\u043c\u043e\u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f<\/strong><\/p>\n<ul>\n<li>\n<p><strong>\u0415\u0441\u043b\u0438 <\/strong><code><strong>running = true<\/strong><\/code>, \u0444\u0443\u043d\u043a\u0446\u0438\u044f <strong>\u0441\u043d\u043e\u0432\u0430 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f<\/strong> (<code>schedule_work()<\/code>).<\/p>\n<\/li>\n<li>\n<p><strong>\u0415\u0441\u043b\u0438 <\/strong><code><strong>running = false<\/strong><\/code>, \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442\u0441\u044f (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043f\u043e\u0441\u043b\u0435 \u0437\u0430\u043a\u0440\u044b\u0442\u0438\u044f <code>\/dev\/ttyUL0<\/code>).<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"cpp\">static void uartlite_rx_work(struct work_struct *work) {   struct uartlite_priv *priv = container_of(work, struct uartlite_priv, rx_work);     struct tty_struct *tty = tty_port_tty_get(&amp;priv-&gt;port);     unsigned char buf[16];     int i, count;      if (!tty)         return;      while (priv-&gt;running &amp;&amp; uartlite_rx_ready(priv)) {         count = 0;         for (i = 0; i &lt; sizeof(buf) &amp;&amp; uartlite_rx_ready(priv); i++) {             buf[i] = uartlite_read_byte(priv);             count++;         }         if (count) {             tty_insert_flip_string(&amp;priv-&gt;port, buf, count);             tty_flip_buffer_push(&amp;priv-&gt;port);         }     }      if (priv-&gt;running)         schedule_work(&amp;priv-&gt;rx_work);      tty_kref_put(tty); }<\/code><\/pre>\n<h3>\u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f PCIe-\u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430<\/h3>\n<p>\u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u0442 PCIe-\u0434\u0440\u0430\u0439\u0432\u0435\u0440 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f:<\/p>\n<pre><code class=\"cpp\">static struct pci_driver uartlite_pci_driver = {     .name = DRIVER_NAME,     .id_table = uartlite_pci_tbl,     .probe = uartlite_probe,     .remove = uartlite_remove, };<\/code><\/pre>\n<ul>\n<li>\n<p>\u041f\u0440\u0438 \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0435\u043d\u0438\u0438 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 \u2192 <strong>\u0432\u044b\u0437\u043e\u0432 <\/strong><code><strong>uartlite_probe()<\/strong><\/code><\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u0438 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0438 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 \u2192 <strong>\u0432\u044b\u0437\u043e\u0432 <\/strong><code><strong>uartlite_remove()<\/strong><\/code><\/p>\n<\/li>\n<\/ul>\n<p>\u041a\u043e\u0434 \u043d\u0438\u0436\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442 <strong>\u0442\u0430\u0431\u043b\u0438\u0446\u0443 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u043e\u0432 PCI-\u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432<\/strong>, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0434\u0440\u0430\u0439\u0432\u0435\u0440.<\/p>\n<pre><code class=\"cpp\">static const struct pci_device_id uartlite_pci_tbl[] = {     { PCI_DEVICE(VENDOR_ID, DEVICE_ID) },     { 0, } };<\/code><\/pre>\n<ul>\n<li>\n<p><code><strong>static const struct pci_device_id uartlite_pci_tbl[]<\/strong><\/code><\/p>\n<ul>\n<li>\n<p>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442 <strong>\u043c\u0430\u0441\u0441\u0438\u0432 <\/strong><code><strong>uartlite_pci_tbl<\/strong><\/code> \u0441 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0435\u0439 \u043e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c\u044b\u0445 PCIe-\u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430\u0445.<\/p>\n<\/li>\n<li>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u044f\u0434\u0440\u043e\u043c Linux \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0434\u0440\u0430\u0439\u0432\u0435\u0440 \u043c\u043e\u0436\u0435\u0442 \u043e\u0431\u0441\u043b\u0443\u0436\u0438\u0432\u0430\u0442\u044c.<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><code><strong>{ PCI_DEVICE(0x10EE, 0x7011) }<\/strong><\/code><\/p>\n<ul>\n<li>\n<p><code>PCI_DEVICE(vendor, device)<\/code> \u2014 \u043c\u0430\u043a\u0440\u043e\u0441, \u0441\u043e\u0437\u0434\u0430\u044e\u0449\u0438\u0439 <code>pci_device_id<\/code> \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443.<\/p>\n<\/li>\n<li>\n<p><code>0x10EE<\/code> \u2014 <strong>Vendor ID<\/strong> (Xilinx).<\/p>\n<\/li>\n<li>\n<p><code>0x7011<\/code> \u2014 <strong>Device ID<\/strong> (ID \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430, \u0432 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 UARTlite).<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><code><strong>{ 0, }<\/strong><\/code><\/p>\n<ul>\n<li>\n<p>\u0417\u0430\u0432\u0435\u0440\u0448\u0430\u044e\u0449\u0438\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u043c\u0430\u0441\u0441\u0438\u0432\u0430 (\u043d\u0443\u043b\u0435\u0432\u043e\u0439 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440), \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u043a\u043e\u043d\u0435\u0446 \u0441\u043f\u0438\u0441\u043a\u0430.<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>\u0415\u0441\u043b\u0438 \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u043d\u0430\u0439\u0434\u0451\u0442 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e \u0441 <strong>Vendor ID <\/strong><code><strong>0x10EE<\/strong><\/code><strong> \u0438 Device ID <\/strong><code><strong>0x7011<\/strong><\/code>, \u0432\u044b\u0437\u043e\u0432\u0435\u0442\u0441\u044f <code><strong>probe()<\/strong><\/code>&#8212; \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430:<\/p>\n<pre><code class=\"cpp\">static int uartlite_probe(struct pci_dev *pdev, const struct pci_device_id *ent)<\/code><\/pre>\n<p>\u041e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u0437\u0430\u0434\u0430\u0447\u0430:<\/p>\n<ul>\n<li>\n<p>\u0412\u044b\u0434\u0435\u043b\u0438\u0442\u044c \u043f\u0430\u043c\u044f\u0442\u044c \u0434\u043b\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430 (<code>uartlite_priv<\/code>).<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f \u043a PCIe-\u0440\u0435\u0441\u0443\u0440\u0441\u0430\u043c (IO-\u0430\u0434\u0440\u0435\u0441\u0430, \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u044b).<\/p>\n<\/li>\n<li>\n<p>\u0417\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c UARTlite \u043a\u0430\u043a TTY-\u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e (<code>\/dev\/ttyUL0<\/code>).<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u0438\u0442\u044c \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0437\u0430\u0434\u0430\u0447 (workqueue) \u0434\u043b\u044f \u043f\u0440\u0438\u0451\u043c\u0430 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<\/li>\n<\/ul>\n<h3>\u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043c\u043e\u0434\u0443\u043b\u044f<\/h3>\n<pre><code class=\"cpp\">module_init(uartlite_init); module_exit(uartlite_exit);<\/code><\/pre>\n<h4>3.5 \u041f\u043e\u043b\u043d\u044b\u0439 \u043a\u043e\u0434 \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430 (uartlite_xdma.c)<\/h4>\n<pre><code class=\"cpp\">\/*  * UARTlite TTY Driver over XDMA  *  * Author:   * Date:   *  * This driver enables communication with AXI UART Lite over PCIe XDMA.  * It implements a TTY interface (ttyULx) for user-space interaction and supports  * RX polling using a work queue mechanism.  *  * License: GPL v2  *\/   #include &lt;linux\/version.h&gt; #include &lt;linux\/module.h&gt; #include &lt;linux\/pci.h&gt; #include &lt;linux\/tty.h&gt; #include &lt;linux\/tty_driver.h&gt; #include &lt;linux\/tty_flip.h&gt; \/\/ tty_insert_flip_string \u0438 tty_flip_buffer_push #include &lt;linux\/io.h&gt; #include &lt;linux\/workqueue.h&gt; \/\/ work_struct  \/\/ External information #define DRIVER_NAME \"uartlite_xdma\" \/\/ Driver name #define VENDOR_ID 0x10EE  \/\/ Xilinx Vendor ID #define DEVICE_ID 0x7011  \/\/ Device ID for 7-Series FPGA Hard PCIe block #define UARTLITE_BASE_OFFSET 0x40000 \/\/ AXI base address  \/\/ AXI UART Lite Register Offsets #define UARTLITE_RX_FIFO  0x00  \/\/ Receive FIFO #define UARTLITE_TX_FIFO  0x04  \/\/ Transmit FIFO #define UARTLITE_STATUS   0x08  \/\/ Status register #define UARTLITE_CONTROL  0x0C  \/\/ Control register  \/\/ Status Register Flags #define STATUS_RXVALID    BIT(0) \/\/ Data available in RX FIFO #define STATUS_TXFULL     BIT(3) \/\/ TX FIFO is full    struct uartlite_priv {     void __iomem *base;     struct tty_port port;     struct work_struct rx_work; \/\/ Polling     bool running; };  static struct tty_driver *uartlite_tty_driver;  \/* UART Lite Functions *\/ static int uartlite_tx_ready(struct uartlite_priv *priv) {     return !(ioread32(priv-&gt;base + UARTLITE_STATUS) &amp; STATUS_TXFULL); }  static void uartlite_write_byte(struct uartlite_priv *priv, u8 val) {     iowrite32(val, priv-&gt;base + UARTLITE_TX_FIFO); }  static int uartlite_rx_ready(struct uartlite_priv *priv) {     return ioread32(priv-&gt;base + UARTLITE_STATUS) &amp; STATUS_RXVALID; }  static u8 uartlite_read_byte(struct uartlite_priv *priv) {     return ioread32(priv-&gt;base + UARTLITE_RX_FIFO); }  \/* Work function for polling RX FIFO *\/ static void uartlite_rx_work(struct work_struct *work) {     struct uartlite_priv *priv = container_of(work, struct uartlite_priv, rx_work);     struct tty_struct *tty = tty_port_tty_get(&amp;priv-&gt;port);     unsigned char buf[16];     int i, count;      if (!tty)         return;      while (priv-&gt;running &amp;&amp; uartlite_rx_ready(priv)) {         count = 0;         for (i = 0; i &lt; sizeof(buf) &amp;&amp; uartlite_rx_ready(priv); i++) {             buf[i] = uartlite_read_byte(priv);             count++;         }         if (count) {             tty_insert_flip_string(&amp;priv-&gt;port, buf, count);             tty_flip_buffer_push(&amp;priv-&gt;port);         }     }      if (priv-&gt;running)         schedule_work(&amp;priv-&gt;rx_work);      tty_kref_put(tty); }  \/* TTY Operations *\/ static int uartlite_tty_open(struct tty_struct *tty, struct file *filp) {     struct uartlite_priv *priv = container_of(tty-&gt;port, struct uartlite_priv, port);     priv-&gt;running = true;     schedule_work(&amp;priv-&gt;rx_work);     return tty_port_open(tty-&gt;port, tty, filp); }  static void uartlite_tty_close(struct tty_struct *tty, struct file *filp) {     struct uartlite_priv *priv = container_of(tty-&gt;port, struct uartlite_priv, port);     priv-&gt;running = false;     cancel_work_sync(&amp;priv-&gt;rx_work);     tty_port_close(tty-&gt;port, tty, filp); }   #if LINUX_VERSION_CODE &lt;= KERNEL_VERSION(6, 5, 0) static int uartlite_tty_write(struct tty_struct *tty, const unsigned char *buf, int count) #else static ssize_t uartlite_tty_write(struct tty_struct *tty, const u8 *buf, size_t count) #endif {     struct uartlite_priv *priv = tty-&gt;driver_data;     int i;      for (i = 0; i &lt; count; i++) {         while (!uartlite_tx_ready(priv))             cpu_relax();         uartlite_write_byte(priv, buf[i]);     }     return i; }   static unsigned int uartlite_tty_write_room(struct tty_struct *tty) {     struct uartlite_priv *priv = tty-&gt;driver_data;     return uartlite_tx_ready(priv) ? 16 : 0; }  static unsigned int uartlite_tty_chars_in_buffer(struct tty_struct *tty) {     return 0; }  static const struct tty_operations uartlite_tty_ops = {     .open = uartlite_tty_open,     .close = uartlite_tty_close,     .write = uartlite_tty_write,     .write_room = uartlite_tty_write_room,     .chars_in_buffer = uartlite_tty_chars_in_buffer, };  \/* TTY Port Initialization *\/ static int uartlite_port_activate(struct tty_port *port, struct tty_struct *tty) {     struct uartlite_priv *priv = container_of(port, struct uartlite_priv, port);     tty-&gt;driver_data = priv;     return 0; }  static void uartlite_port_shutdown(struct tty_port *port) {     struct uartlite_priv *priv = container_of(port, struct uartlite_priv, port);     priv-&gt;running = false;     cancel_work_sync(&amp;priv-&gt;rx_work); }  static const struct tty_port_operations uartlite_port_ops = {     .activate = uartlite_port_activate,     .shutdown = uartlite_port_shutdown, };  \/* PCI Probe Function *\/ static int uartlite_probe(struct pci_dev *pdev, const struct pci_device_id *ent) {     struct uartlite_priv *priv;     int ret;      priv = devm_kzalloc(&amp;pdev-&gt;dev, sizeof(*priv), GFP_KERNEL);     if (!priv)         return -ENOMEM;      ret = pcim_enable_device(pdev);     if (ret)         return ret;      priv-&gt;base = pcim_iomap(pdev, 0, 0);     if (!priv-&gt;base)         return -ENOMEM;      priv-&gt;base += UARTLITE_BASE_OFFSET;      tty_port_init(&amp;priv-&gt;port);     priv-&gt;port.ops = &amp;uartlite_port_ops;     INIT_WORK(&amp;priv-&gt;rx_work, uartlite_rx_work);     priv-&gt;running = false;      tty_port_register_device(&amp;priv-&gt;port, uartlite_tty_driver, 0, &amp;pdev-&gt;dev);      pci_set_drvdata(pdev, priv);     dev_info(&amp;pdev-&gt;dev, \"UARTlite over XDMA registered as TTY\");     return 0; }  static void uartlite_remove(struct pci_dev *pdev) {     struct uartlite_priv *priv = pci_get_drvdata(pdev);     tty_unregister_device(uartlite_tty_driver, 0);     tty_port_destroy(&amp;priv-&gt;port); }  static const struct pci_device_id uartlite_pci_tbl[] = {     { PCI_DEVICE(VENDOR_ID, DEVICE_ID) },     { 0, } };  static struct pci_driver uartlite_pci_driver = {       .name = DRIVER_NAME,     .id_table = uartlite_pci_tbl,     .probe = uartlite_probe,     .remove = uartlite_remove, };  \/* Module Initialization *\/ static int __init uartlite_init(void) {     int ret;      uartlite_tty_driver = tty_alloc_driver(1, TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV);     if (IS_ERR(uartlite_tty_driver))         return PTR_ERR(uartlite_tty_driver);      uartlite_tty_driver-&gt;driver_name = DRIVER_NAME;     uartlite_tty_driver-&gt;name = \"ttyUL\";     uartlite_tty_driver-&gt;major = 0;     uartlite_tty_driver-&gt;minor_start = 0;     uartlite_tty_driver-&gt;type = TTY_DRIVER_TYPE_SERIAL;     uartlite_tty_driver-&gt;subtype = SERIAL_TYPE_NORMAL;     uartlite_tty_driver-&gt;init_termios = tty_std_termios;     uartlite_tty_driver-&gt;init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;      tty_set_operations(uartlite_tty_driver, &amp;uartlite_tty_ops);      ret = tty_register_driver(uartlite_tty_driver);     if (ret) {         tty_driver_kref_put(uartlite_tty_driver);         return ret;     }      ret = pci_register_driver(&amp;uartlite_pci_driver);     if (ret) {         tty_unregister_driver(uartlite_tty_driver);         tty_driver_kref_put(uartlite_tty_driver);     }      return ret; }  static void __exit uartlite_exit(void) {     pci_unregister_driver(&amp;uartlite_pci_driver);     tty_unregister_driver(uartlite_tty_driver);     tty_driver_kref_put(uartlite_tty_driver); }  module_init(uartlite_init); module_exit(uartlite_exit);  MODULE_LICENSE(\"GPL v2\"); MODULE_AUTHOR(\"Konstantin\"); MODULE_DESCRIPTION(\"UARTlite TTY driver over XDMA with RX support\");<\/code><\/pre>\n<h4>3.6 \u0421\u0431\u043e\u0440\u043a\u0430, \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0438 \u043e\u0442\u043b\u0430\u0434\u043a\u0430<\/h4>\n<p>\u041f\u0435\u0440\u0435\u0434 \u0441\u0431\u043e\u0440\u043a\u043e\u0439 \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430 \u0443\u0431\u0435\u0434\u0438\u0441\u044c, \u0447\u0442\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u044b \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u0447\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u044b \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u044f\u0434\u0440\u0430:<\/p>\n<pre><code class=\"bash\">sudo apt update sudo apt install -y linux-headers-$(uname -r)<\/code><\/pre>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430:<\/p>\n<pre><code class=\"bash\">ls \/lib\/modules\/$(uname -r)\/build<\/code><\/pre>\n<p>\u0415\u0441\u043b\u0438 \u043a\u0430\u0442\u0430\u043b\u043e\u0433 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442, \u0437\u043d\u0430\u0447\u0438\u0442 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u0447\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u044b \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u044b.<\/p>\n<h3>\u0421\u0431\u043e\u0440\u043a\u0430 \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430<\/h3>\n<p>\u041d\u0438\u0436\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0430 Makefile \u0434\u043b\u044f \u0441\u0431\u043e\u0440\u043a\u0438 \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430<\/p>\n<pre><code class=\"cmake\"># Build the kernel module obj-m += uartlite_xdma.o  # Kernel build directory (default: current running kernel) KDIR ?= \/lib\/modules\/$(shell uname -r)\/build  # Build the module all:     make CC=\/usr\/bin\/gcc-13 -C $(KDIR) M=$(PWD) modules  # Clean up compiled files clean:     make -C $(KDIR) M=$(PWD) clean  # Install the module into the system install:     make -C $(KDIR) M=$(PWD) modules_install  # Enable debugging symbols (-g flag for debugging) EXTRA_CFLAGS += -g  # Define targets that are not actual files .PHONY: all clean install<\/code><\/pre>\n<p>\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u043a\u043e\u043c\u0430\u043d\u0434\u0443:<\/p>\n<pre><code class=\"bash\">make<\/code><\/pre>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0439 \u0441\u0431\u043e\u0440\u043a\u0438 \u043f\u043e\u044f\u0432\u0438\u0442\u0441\u044f \u0444\u0430\u0439\u043b <code><strong>uartlite_xdma.ko<\/strong><\/code> \u2014 \u0433\u043e\u0442\u043e\u0432\u044b\u0439 \u043c\u043e\u0434\u0443\u043b\u044c \u044f\u0434\u0440\u0430.<\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440\u044b \u0432\u044b\u0432\u043e\u0434\u0430 \u043f\u0440\u0438 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u0439 \u0441\u0431\u043e\u0440\u043a\u0435 \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/56b\/584\/2c2\/56b5842c29753978fb19784f2d272103.png\" width=\"954\" height=\"212\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/56b\/584\/2c2\/56b5842c29753978fb19784f2d272103.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/56b\/584\/2c2\/56b5842c29753978fb19784f2d272103.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430:<\/p>\n<pre><code class=\"bash\">ls -l uartlite_xdma.ko<\/code><\/pre>\n<p>\u0432 \u043c\u043e\u0435 \u0441\u043b\u0443\u0447\u0430\u0435 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0432\u044b\u0432\u043e\u0434:<\/p>\n<pre><code class=\"bash\">-rwxr-xr-x 1 nvx root 390152 Mar 13 18:15 uartlite_xdma.ko<\/code><\/pre>\n<h3>\u0417\u0430\u043f\u0443\u0441\u043a \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430<\/h3>\n<p>\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430 \u0432 \u044f\u0434\u0440\u043e \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0447\u0442\u043e \u0434\u0440\u0430\u0439\u0432\u0435\u0440 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d:<\/p>\n<pre><code class=\"bash\">sudo insmod uartlite_xdma.ko lsmod | grep uartlite_xdma<\/code><\/pre>\n<p>\u0415\u0441\u043b\u0438 \u0432\u0441\u0451 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e, \u043c\u043e\u0434\u0443\u043b\u044c \u043f\u043e\u044f\u0432\u0438\u0442\u0441\u044f \u0432 \u0441\u043f\u0438\u0441\u043a\u0435.<\/p>\n<pre><code class=\"bash\">uartlite_xdma          12288  0<\/code><\/pre>\n<p>\u0412\u044b\u0432\u043e\u0434 \u043b\u043e\u0433\u043e\u0432 \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430:<\/p>\n<pre><code class=\"bash\">sudo dmesg | tail -n 20<\/code><\/pre>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u0432\u044b\u0432\u043e\u0434\u0430:<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/ffc\/a6d\/0a6\/ffca6d0a6346334a9984ded0db5875a1.png\" width=\"675\" height=\"25\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/ffc\/a6d\/0a6\/ffca6d0a6346334a9984ded0db5875a1.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/ffc\/a6d\/0a6\/ffca6d0a6346334a9984ded0db5875a1.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f TTY-\u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430:<\/p>\n<pre><code class=\"bash\">ls \/dev\/ttyUL*<\/code><\/pre>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u0432\u044b\u0432\u043e\u0434\u0430:<\/p>\n<pre><code class=\"bash\">\/dev\/ttyUL0<\/code><\/pre>\n<h3>\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0440\u0430\u0431\u043e\u0442\u044b<\/h3>\n<pre><code class=\"bash\">sudo minicom -D \/dev\/ttyUL0 <\/code><\/pre>\n<p>\u041e\u0436\u0438\u0434\u0430\u0435\u043c\u044b\u0439 \u0432\u044b\u0432\u043e\u0434:<\/p>\n<pre><code class=\"bash\">$GPGGA,123456.78,5540.1234,N,03734.5678,E,1,08,0.9,100.0,M,0.0,M,,*47<\/code><\/pre>\n<p>\u041c\u043e\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 \u0432\u044b\u0432\u043e\u0434\u0430 (GPS \u0430\u043d\u0442\u0435\u043d\u043d\u0430 \u043d\u0435 \u043f\u043e\u0434\u043a\u043b\u0447\u0435\u043d\u0430): <\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/4d5\/8c9\/978\/4d58c997832f1222ca65f22075750089.png\" width=\"436\" height=\"469\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/4d5\/8c9\/978\/4d58c997832f1222ca65f22075750089.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/4d5\/8c9\/978\/4d58c997832f1222ca65f22075750089.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0422\u0430\u043a \u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043d\u0430\u0448 tty \u043a <code>gpsd<\/code>:<\/p>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c <code>gpsd<\/code>, \u043f\u0440\u0438\u0432\u044f\u0437\u044b\u0432\u0430\u0435\u043c \u0435\u0433\u043e \u043a <code>ttyUL0<\/code>:<\/p>\n<pre><code class=\"bash\">sudo gpsd \/dev\/ttyUL0 -F \/var\/run\/gpsd.sock<\/code><\/pre>\n<ul>\n<li>\n<p><code>\/dev\/ttyUL0<\/code> \u2014 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e UART, \u043a \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0451\u043d GPS<\/p>\n<\/li>\n<li>\n<p><code>-F \/var\/run\/gpsd.sock<\/code> \u2014 \u0441\u043e\u0437\u0434\u0430\u0451\u0442 <strong>UNIX-\u0441\u043e\u043a\u0435\u0442<\/strong> \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 GPS<\/p>\n<\/li>\n<\/ul>\n<p>\u0438\u043b\u0438:<\/p>\n<pre><code class=\"bash\">sudo gpsd -N -D3 -F \/var\/run\/gpsd.sock \/dev\/ttyUL0<\/code><\/pre>\n<ul>\n<li>\n<p><code><strong>-N<\/strong><\/code> \u2014 \u043d\u0435 \u0443\u0445\u043e\u0434\u0438\u0442 \u0432 \u0444\u043e\u043d (\u043c\u043e\u0436\u043d\u043e \u0441\u0440\u0430\u0437\u0443 \u0432\u0438\u0434\u0435\u0442\u044c \u043e\u0448\u0438\u0431\u043a\u0438).<\/p>\n<\/li>\n<li>\n<p><code><strong>-D3<\/strong><\/code> \u2014 \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u043e\u0442\u043b\u0430\u0434\u043a\u0443.<\/p>\n<\/li>\n<li>\n<p><code><strong>\/dev\/ttyUL0<\/strong><\/code> \u2014 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0439 UART-\u043f\u043e\u0440\u0442 GPS.<\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043b\u0438 <code>gpsd<\/code><\/p>\n<pre><code class=\"bash\">ps aux | grep gpsd<\/code><\/pre>\n<p>\u0415\u0441\u043b\u0438 <code>gpsd<\/code> \u0437\u0430\u043f\u0443\u0449\u0435\u043d, \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u0447\u0442\u043e-\u0442\u043e \u0432\u0440\u043e\u0434\u0435:<\/p>\n<pre><code class=\"bash\">root         7131  0.0  0.0   9084  2432 pts\/3    S+   18:51   0:00 grep --color=auto gpsd<\/code><\/pre>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c <code>cgps<\/code> (\u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u0442 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b, \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c, \u0432\u044b\u0441\u043e\u0442\u0443 \u0438 \u0432\u0440\u0435\u043c\u044f):<\/p>\n<pre><code class=\"bash\">cgps -s<\/code><\/pre>\n<p>\u0415\u0441\u043b\u0438 GPS \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u043f\u043e\u044f\u0432\u0438\u0442\u0441\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440:<\/p>\n<pre><code class=\"yaml\">Time: 2025-03-13T12:34:56Z  Latitude: 55.7558 N  Longitude: 37.6173 E  Speed: 0.5 km\/h  Altitude: 200 m<\/code><\/pre>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u0441\u044b\u0440\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0441 GPS-\u043c\u043e\u0434\u0443\u043b\u044f:<\/p>\n<pre><code class=\"bash\">gpspipe -r<\/code><\/pre>\n<p>\u042d\u0442\u043e \u043f\u043e\u043a\u0430\u0436\u0435\u0442 <strong>\u0441\u044b\u0440\u044b\u0435 NMEA-\u043f\u0430\u043a\u0435\u0442\u044b<\/strong>, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440:<\/p>\n<pre><code class=\"bash\">$GPGGA,123456.00,5537.348,N,03736.882,E,1,08,1.0,200.0,M,0.0,M,,*47  $GPRMC,123456.00,A,5537.348,N,03736.882,E,0.5,45.0,130324,,,A*7C<\/code><\/pre>\n<h3>\u0423\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430<\/h3>\n<p>\u0412\u044b\u0433\u0440\u0443\u0437\u043a\u0430 \u043c\u043e\u0434\u0443\u043b\u044f:<\/p>\n<pre><code class=\"bash\">sudo rmmod uartlite_xdma<\/code><\/pre>\n<p>\u041e\u0447\u0438\u0441\u0442\u043a\u0430 \u0441\u043e\u0431\u0440\u0430\u043d\u043d\u044b\u0445 \u0444\u0430\u0439\u043b\u043e\u0432:<\/p>\n<pre><code class=\"bash\">make clean<\/code><\/pre>\n<h3>5 \u0420\u0430\u0431\u043e\u0442\u0430 \u0441 UARTlite \u0447\u0435\u0440\u0435\u0437 XDMA \u043d\u0430 Python<\/h3>\n<p>\u041f\u043e\u043c\u0438\u043c\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430, \u043c\u043e\u0436\u043d\u043e <strong>\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 UARTlite \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u0447\u0435\u0440\u0435\u0437 XDMA<\/strong> \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <strong>Python<\/strong>. \u042d\u0442\u043e \u043f\u043e\u043b\u0435\u0437\u043d\u043e \u0434\u043b\u044f \u043e\u0442\u043b\u0430\u0434\u043a\u0438 \u0438 \u0431\u044b\u0441\u0442\u0440\u043e\u0433\u043e \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438\u043b\u0438 \u0434\u043b\u044f \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u0442\u043d\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u0430 \u0432 userspace.<\/p>\n<h4>5.1 \u0421\u0431\u043e\u0440\u043a\u0430 \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430 XDMA<\/h4>\n<p>\u041f\u0435\u0440\u0435\u0434 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c <strong>XDMA<\/strong> \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e <strong>\u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0434\u0440\u0430\u0439\u0432\u0435\u0440<\/strong>. \u0414\u0440\u0430\u0439\u0432\u0435\u0440 <strong>XDMA<\/strong> \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f Xilinx \u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 PCIe-\u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430\u043c\u0438, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0438\u043c\u0438 DMA.<br \/><a href=\"https:\/\/github.com\/Xilinx\/dma_ip_drivers\" rel=\"noopener noreferrer nofollow\">XDMA Linux Kernel Drivers GitHub<\/a><\/p>\n<h4>5.2 \u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u043e\u0432 \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430 XDMA<\/h4>\n<p>\u0418\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0438 \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0432 \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u043c \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438 Xilinx:<\/p>\n<pre><code class=\"bash\">git clone https:\/\/github.com\/Xilinx\/dma_ip_drivers.git cd dma_ip_drivers\/XDMA\/linux-kernel###<\/code><\/pre>\n<h4>5.3 \u041a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u044f \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430<\/h4>\n<p>\u041f\u0435\u0440\u0435\u0434 \u0441\u0431\u043e\u0440\u043a\u043e\u0439 \u0443\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e \u0443 \u0432\u0430\u0441 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u044b \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u0447\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u044b \u044f\u0434\u0440\u0430:<\/p>\n<pre><code class=\"bash\">sudo apt-get install linux-headers-$(uname -r)<\/code><\/pre>\n<p>\u041a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u0443\u0435\u043c \u0434\u0440\u0430\u0439\u0432\u0435\u0440 :<\/p>\n<pre><code class=\"bash\">make<\/code><\/pre>\n<p>\u043f\u0440\u0438\u043c\u0435\u0440 \u0432\u044b\u0432\u043e\u0434\u0430: <\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/472\/d38\/d01\/472d38d01c6f9be154d37313e84f82a3.png\" width=\"1043\" height=\"413\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/472\/d38\/d01\/472d38d01c6f9be154d37313e84f82a3.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/472\/d38\/d01\/472d38d01c6f9be154d37313e84f82a3.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<h4>5.4 \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430<\/h4>\n<pre><code class=\"bash\">sudo make install sudo modprobe xdma<\/code><\/pre>\n<p>\u043f\u0440\u0438\u043c\u0435\u0440 \u0432\u044b\u0432\u043e\u0434\u0430: <\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/e46\/9ef\/e2c\/e469efe2c1f1976ff615af41b6628e70.png\" width=\"954\" height=\"212\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/e46\/9ef\/e2c\/e469efe2c1f1976ff615af41b6628e70.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/e46\/9ef\/e2c\/e469efe2c1f1976ff615af41b6628e70.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0415\u0441\u043b\u0438 \u043d\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c , \u0435\u0441\u0442\u044c \u0434\u0440\u0443\u0433\u043e\u0439 \u043f\u0443\u0442\u044c \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430 \u043f\u043e\u0441\u043b\u0435 \u0441\u0431\u043e\u0440\u043a\u0438:<\/p>\n<pre><code class=\"bash\">cd dma_ip_drivers\/XDMA\/linux-kernel\/tests\/ sudo .\/load_driver.sh <\/code><\/pre>\n<p>\u041e\u0436\u0438\u0434\u0430\u0435\u043c\u044b\u0439 \u0432\u044b\u0432\u043e\u0434:<\/p>\n<pre><code class=\"bash\">interrupt_selection . xdma                   24576  0 Loading driver...insmod xdma.ko interrupt_mode=2 ...  The Kernel module installed correctly and the xmda devices were recognized. DONE<\/code><\/pre>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0447\u0442\u043e \u043c\u043e\u0434\u0443\u043b\u044c \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d:<\/p>\n<pre><code class=\"bash\">lsmod | grep xdma<\/code><\/pre>\n<p>\u043e\u0436\u0438\u0434\u0430\u0435\u043c\u044b\u0439 \u0432\u044b\u0432\u043e\u0434:<\/p>\n<pre><code class=\"bash\">xdma                  110592  0<\/code><\/pre>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430 \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0435 \u043f\u043e\u044f\u0432\u044f\u0442\u0441\u044f \u0444\u0430\u0439\u043b\u044b \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432:<\/p>\n<pre><code class=\"bash\">ls \/dev\/xdma*<\/code><\/pre>\n<p>\u041e\u0436\u0438\u0434\u0430\u0435\u043c\u044b\u0439 \u0432\u044b\u0432\u043e\u0434:<\/p>\n<pre><code class=\"bash\">\/dev\/xdma0_c2h_0  \/dev\/xdma0_h2c_0  \/dev\/xdma0_control  \/dev\/xdma0_user<\/code><\/pre>\n<p>\u0412 \u043c\u043e\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435: <\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/fe9\/f2d\/f5c\/fe9f2df5c5c87d0a1f5191ff4d77fe80.png\" width=\"1194\" height=\"56\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/fe9\/f2d\/f5c\/fe9f2df5c5c87d0a1f5191ff4d77fe80.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/fe9\/f2d\/f5c\/fe9f2df5c5c87d0a1f5191ff4d77fe80.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<div>\n<div class=\"table\">\n<table>\n<tbody>\n<tr>\n<th>\n<p align=\"left\">\u0424\u0430\u0439\u043b<\/p>\n<\/th>\n<th>\n<p align=\"left\">\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435<\/p>\n<\/th>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\"><code>\/dev\/xdma0_c2h_0<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\">C2H (Card-to-Host)\u00a0\u2013 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0437 FPGA \u0432 CPU<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\"><code>\/dev\/xdma0_h2c_0<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\">H2C (Host-to-Card) \u2013 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0437 CPU \u0432 FPGA<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\"><code>\/dev\/xdma0_user<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0418\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0434\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0445 \u043a\u043e\u043c\u0430\u043d\u0434 (\u0435\u0441\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0432 FPGA).<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\"><code>\/dev\/xdma0_xvc<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\">**Xilinx Virtual Cable (XVC) \u2013 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c JTAG \u0447\u0435\u0440\u0435\u0437 PCIe.\u00a0\u0415\u0441\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f XVC (JTAG-over-PCIe), \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0441 <code>\u00a0telnet localhost 2542<\/code><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\"><code>\/dev\/xdma0_control<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0420\u0435\u0433\u0438\u0441\u0442\u0440 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f XDMA<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\"><code>\/dev\/xdma0_events_0<\/code> &#8230; <code>\/dev\/xdma0_events_15<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0441\u043e\u0431\u044b\u0442\u0438\u044f \u043e\u0442 FPGA \u043a CPU. \u041c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0441\u043b\u0443\u0448\u0438\u0432\u0430\u0442\u044c \u0441\u043e\u0431\u044b\u0442\u0438\u044f.\u00a0\u0415\u0441\u043b\u0438 XDMA \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d \u043d\u0430 \u043f\u0440\u0435\u0440\u044b\u0432\u0430\u043d\u0438\u044f, \u044d\u0442\u043e\u0442 \u0444\u0430\u0439\u043b \u0432\u044b\u0434\u0430\u0441\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u0440\u0438 \u043a\u0430\u0436\u0434\u043e\u043c \u0441\u043e\u0431\u044b\u0442\u0438\u0438.<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<ul>\n<li>\n<p><strong>DMA-\u0434\u0440\u0430\u0439\u0432\u0435\u0440 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d<\/strong> \u0438 \u0441\u043e\u0437\u0434\u0430\u043b \u0444\u0430\u0439\u043b\u044b \u0432 <code>\/dev\/<\/code>.<\/p>\n<\/li>\n<li>\n<p>\u041c\u043e\u0436\u043d\u043e <strong>\u0447\u0442\u0435\u043d\u0438\u0435\/\u0437\u0430\u043f\u0438\u0441\u044c<\/strong> \u0447\u0435\u0440\u0435\u0437 <code>c2h_0<\/code> (FPGA \u2192 CPU) \u0438 <code>h2c_0<\/code> (CPU \u2192 FPGA).<\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u0435\u0440\u044b\u0432\u0430\u043d\u0438\u044f <strong>\u043c\u043e\u0436\u043d\u043e \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u0442\u044c<\/strong> \u0447\u0435\u0440\u0435\u0437 <code>xdma_events_*<\/code>.<\/p>\n<\/li>\n<li>\n<p><strong>XVC \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 JTAG \u0447\u0435\u0440\u0435\u0437 PCIe<\/strong>.<\/p>\n<\/li>\n<\/ul>\n<p>\u0415\u0441\u043b\u0438 \u0444\u0430\u0439\u043b\u044b \u043f\u043e\u044f\u0432\u0438\u043b\u0438\u0441\u044c, \u0434\u0440\u0430\u0439\u0432\u0435\u0440 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d \u0438 XDMA \u0433\u043e\u0442\u043e\u0432 \u043a \u0440\u0430\u0431\u043e\u0442\u0435, \u0442\u043e \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u0442\u044c \u043a \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044e UARTlite.<\/p>\n<h4>5.6 \u041a\u043e\u0434 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 UARTlite \u0447\u0435\u0440\u0435\u0437 XDMA \u0432 Python (uaxdma.py)<\/h4>\n<p><strong>\u041f\u0440\u0438\u043d\u0446\u0438\u043f \u0440\u0430\u0431\u043e\u0442\u044b:<\/strong><br \/>\u0421\u043a\u0440\u0438\u043f\u0442 \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0442 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e <code>\/dev\/xdma0_user<\/code>, \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u044f \u043f\u0430\u043c\u044f\u0442\u044c <strong>XDMA<\/strong> \u0432 \u0430\u0434\u0440\u0435\u0441\u043d\u043e\u0435 \u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e mmap. \u0417\u0430\u0442\u0435\u043c \u043e\u043d \u043e\u0431\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u043a \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u043c <strong>UARTlite<\/strong> \u043f\u043e \u0441\u043c\u0435\u0449\u0435\u043d\u0438\u044e <code>0x40000<\/code>, \u0447\u0438\u0442\u0430\u044f \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437 <strong>RX <\/strong> \u0438\u043b\u0438 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u044f \u0432 <strong>TX <\/strong>. \u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0441 <strong>UARTlite<\/strong> \u0431\u0435\u0437 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430 \u044f\u0434\u0440\u0430.<\/p>\n<pre><code class=\"python\">import os import time import numpy as np import mmap import asyncio  # ============================ # #  XDMA + UARTLite (\u041e\u0431\u044a\u0435\u0434\u0438\u043d\u0435\u043d\u043e) # ============================ # class XdmaUartLite:     BASE_ADDR = 0x40000  # \u0411\u0430\u0437\u043e\u0432\u044b\u0439 \u0430\u0434\u0440\u0435\u0441 UARTLite \u0432 XDMA      # \u041e\u0444\u0444\u0441\u0435\u0442\u044b \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u043e\u0432 UARTLite     RX_FIFO = 0x00     TX_FIFO = 0x04     STATUS = 0x08     CONTROL = 0x0C      # \u0424\u043b\u0430\u0433\u0438     TX_FULL = 0x08     RX_VALID = 0x01     TX_RESET = 0x01     RX_RESET = 0x02      def __init__(self, device_index=0):         \"\"\"\u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f XDMA \u0438 UARTLite\"\"\"         base = f\"\/dev\/xdma{device_index}\"          # \u041e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u0444\u0430\u0439\u043b\u044b \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 XDMA         self.fd_user = os.open(f\"{base}_user\", os.O_RDWR)          # \u0421\u043e\u0437\u0434\u0430\u0451\u043c \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u043f\u0430\u043c\u044f\u0442\u0438 \u0434\u043b\u044f \u0431\u044b\u0441\u0442\u0440\u043e\u0433\u043e \u0434\u043e\u0441\u0442\u0443\u043f\u0430         self.m_rmap = np.frombuffer(mmap.mmap(self.fd_user, int(1e6)), np.uint32)          # \u0421\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0435\u043c FIFO UARTLite         self.reset_fifos()      def close(self):         \"\"\"\u0417\u0430\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u0444\u0430\u0439\u043b\u044b XDMA \u043f\u0440\u0438 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0438\"\"\"         os.close(self.fd_user)       # ============================ #     #  \u0427\u0442\u0435\u043d\u0438\u0435\/\u0417\u0430\u043f\u0438\u0441\u044c \u0447\u0435\u0440\u0435\u0437 XDMA     # ============================ #     def read_reg(self, addr):         \"\"\"\u0427\u0438\u0442\u0430\u0435\u043c 32-\u0431\u0438\u0442\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438\u0437 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\"\"\"         return self.m_rmap[addr &gt;&gt; 2] &amp; 0xFFFF      def write_reg(self, addr, data):         \"\"\"\u0417\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c 32-\u0431\u0438\u0442\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0432 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\"\"\"         self.m_rmap[addr &gt;&gt; 2] = np.uint32(data)      # ============================ #     #  \u0420\u0430\u0431\u043e\u0442\u0430 \u0441 UARTLite     # ============================ #     def reset_fifos(self):         \"\"\"\u0421\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0435\u043c FIFO \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u0447\u0438\u043a\u0430 \u0438 \u043f\u0440\u0438\u0451\u043c\u043d\u0438\u043a\u0430\"\"\"         self.write_reg(self.BASE_ADDR + self.CONTROL, self.TX_RESET | self.RX_RESET)      def send_byte(self, data):         \"\"\"\u041e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c 1 \u0431\u0430\u0439\u0442 \u0447\u0435\u0440\u0435\u0437 UARTLite\"\"\"         while self.read_reg(self.BASE_ADDR + self.STATUS) &amp; self.TX_FULL:             pass  # \u0416\u0434\u0451\u043c, \u043f\u043e\u043a\u0430 FIFO \u043d\u0435 \u043e\u0441\u0432\u043e\u0431\u043e\u0434\u0438\u0442\u0441\u044f         self.write_reg(self.BASE_ADDR + self.TX_FIFO, data)      def recv_byte(self):         \"\"\"\u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c 1 \u0431\u0430\u0439\u0442 \u0447\u0435\u0440\u0435\u0437 UARTLite\"\"\"         while not (self.read_reg(self.BASE_ADDR + self.STATUS) &amp; self.RX_VALID):             pass  # \u0416\u0434\u0451\u043c, \u043f\u043e\u043a\u0430 \u043f\u043e\u044f\u0432\u044f\u0442\u0441\u044f \u0434\u0430\u043d\u043d\u044b\u0435         return self.read_reg(self.BASE_ADDR + self.RX_FIFO)      def send_data(self, data):         \"\"\"\u041e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u043c\u0430\u0441\u0441\u0438\u0432 \u0431\u0430\u0439\u0442\u043e\u0432 \u0447\u0435\u0440\u0435\u0437 UARTLite\"\"\"         for byte in data:             self.send_byte(byte)      def recv_data(self, size):         \"\"\"\u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043c\u0430\u0441\u0441\u0438\u0432 \u0431\u0430\u0439\u0442\u043e\u0432 \u0447\u0435\u0440\u0435\u0437 UARTLite\"\"\"         return bytearray([self.recv_byte() for _ in range(size)])      async def recv_byte_async(self):         \"\"\"\u0410\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u0435 \u0447\u0442\u0435\u043d\u0438\u0435 1 \u0431\u0430\u0439\u0442\u0430.\"\"\"         while not (self.read_reg(self.BASE_ADDR + self.STATUS) &amp; self.RX_VALID):             await asyncio.sleep(0.001)  # \u0414\u0430\u0434\u0438\u043c CPU \u043e\u0442\u0434\u043e\u0445\u043d\u0443\u0442\u044c, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u043d\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c 100%         return self.read_reg(self.BASE_ADDR + self.RX_FIFO)      async def recv_data_async(self, size):         \"\"\"\u0410\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u0435 \u0447\u0442\u0435\u043d\u0438\u0435 \u043c\u0430\u0441\u0441\u0438\u0432\u0430 \u0431\u0430\u0439\u0442\u043e\u0432.\"\"\"         return bytearray([await self.recv_byte_async() for _ in range(size)])  # ============================ # #  \u0422\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 XDMA + UARTLite # ============================ #    ### \u041f\u0440\u043e\u0441\u0442\u043e\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442  # if __name__ == \"__main__\": #     # \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c XDMA+UARTLite #     xdma_uart = XdmaUartLite(device_index=0)  #     print(\"\u041e\u0436\u0438\u0434\u0430\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u0441 UARTLite...\") #     while True: #         data = xdma_uart.recv_data(128)  # \u0427\u0438\u0442\u0430\u0435\u043c 128 \u0431\u0430\u0439\u0442\u0430 #         if data: #             print(data.decode(errors=\"ignore\").strip())  # \u0423\u0431\u0438\u0440\u0430\u0435\u043c \u043f\u0443\u0441\u0442\u044b\u0435 \u0441\u0442\u0440\u043e\u043a\u0438 \u0438 \u043f\u0440\u043e\u0431\u0435\u043b\u044b   ### \u0412\u0430\u0440\u0438\u0430\u043d\u0442 \u0441 async async def main():     uart = XdmaUartLite()     while True:         data = await uart.recv_data_async(128)         print(data.decode(errors=\"ignore\"))  asyncio.run(main())<\/code><\/pre>\n<p>\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u043c :<\/p>\n<pre><code class=\"bash\">sudo python3 uaxdma.py<\/code><\/pre>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u0432\u044b\u0432\u043e\u0434\u0430:<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/ef8\/a5a\/52c\/ef8a5a52cf4ea4a4e604bbfb126550cf.png\" width=\"427\" height=\"344\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/ef8\/a5a\/52c\/ef8a5a52cf4ea4a4e604bbfb126550cf.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/ef8\/a5a\/52c\/ef8a5a52cf4ea4a4e604bbfb126550cf.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<h4>5.6 \u041f\u0440\u043e\u0444\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435<\/h4>\n<p>\u0410\u043d\u0430\u043b\u0438\u0437 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 <a href=\"http:\/\/uaxdma.py\" rel=\"noopener noreferrer nofollow\"><code>uaxdma.py<\/code><\/a> \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <code>py-spy<\/code>  \u0434\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0441 async:<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/e4a\/311\/f02\/e4a311f020668e6c84866349ce331317.png\" width=\"772\" height=\"359\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/e4a\/311\/f02\/e4a311f020668e6c84866349ce331317.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/e4a\/311\/f02\/e4a311f020668e6c84866349ce331317.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0434\u043b\u044f \u043e\u0431\u044b\u0447\u043d\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438: <\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/514\/90e\/413\/51490e413cb39d4bf8bad261f7718702.png\" width=\"772\" height=\"359\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/514\/90e\/413\/51490e413cb39d4bf8bad261f7718702.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/514\/90e\/413\/51490e413cb39d4bf8bad261f7718702.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p><strong>\u0417\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u043d\u043e\u0441\u0442\u044c \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u0430<\/strong><\/p>\n<ul>\n<li>\n<p><strong>Polling (\u0432\u0442\u043e\u0440\u043e\u0435 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435)<\/strong>: <strong>100% CPU<\/strong>, <code>read_reg<\/code> \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442 <strong>93% \u0432\u0440\u0435\u043c\u0435\u043d\u0438<\/strong>.<\/p>\n<\/li>\n<li>\n<p><strong>Async-\u0432\u0435\u0440\u0441\u0438\u044f (\u043f\u0435\u0440\u0432\u043e\u0435 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435)<\/strong>: <strong>1% CPU<\/strong>, <code>read_reg<\/code> \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043d\u0435 \u043d\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442 \u0441\u0438\u0441\u0442\u0435\u043c\u0443.<\/p>\n<\/li>\n<\/ul>\n<p><strong>\u0412\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u0439<\/strong><\/p>\n<ul>\n<li>\n<p><strong>Polling:<\/strong> <code>read_reg<\/code> \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442 <strong>8.7s \u0438\u0437 8.7s<\/strong> (\u0442\u043e \u0435\u0441\u0442\u044c \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0430 \u043f\u043e\u0447\u0442\u0438 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0437\u0430\u043d\u044f\u0442\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u043e\u0439 \u0434\u0430\u043d\u043d\u044b\u0445).<\/p>\n<\/li>\n<li>\n<p><strong>Async:<\/strong> <code>read_reg<\/code> \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f <strong>\u0432\u0441\u0435\u0433\u043e 0.01s<\/strong>, \u0430 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u0443\u0445\u043e\u0434\u0438\u0442 \u043d\u0430 <code>asyncio.sleep()<\/code>, \u0447\u0442\u043e \u0441\u043d\u0438\u0436\u0430\u0435\u0442 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0443.<\/p>\n<\/li>\n<\/ul>\n<h3>6. \u0412\u044b\u0432\u043e\u0434\u044b<\/h3>\n<p>\u0420\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u043d\u044b\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u044e\u0442 \u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u0443\u044e \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0443 \u0434\u0430\u043d\u043d\u044b\u0445 \u043e\u0442 <strong>GPS<\/strong>-\u043c\u043e\u0434\u0443\u043b\u044f \u0447\u0435\u0440\u0435\u0437 <strong>UARTlite<\/strong> \u043a \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044e, \u0443\u043f\u0440\u043e\u0449\u0430\u044f \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044e \u043f\u0435\u0440\u0438\u0444\u0435\u0440\u0438\u0438 <strong>FPGA<\/strong> \u0432 <strong>SDR<\/strong>-\u0441\u0438\u0441\u0442\u0435\u043c\u044b. \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u0440\u0435\u0440\u044b\u0432\u0430\u043d\u0438\u0439 \u0432\u043c\u0435\u0441\u0442\u043e <code>polling<\/code> \u043c\u043e\u0436\u0435\u0442 \u0441\u043d\u0438\u0437\u0438\u0442\u044c \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u043d\u0430 <strong>CPU<\/strong>, \u0430 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f \u0431\u0443\u0444\u0435\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u2014 \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0442\u044c \u043f\u0440\u043e\u043f\u0443\u0441\u043a\u043d\u0443\u044e \u0441\u043f\u043e\u0441\u043e\u0431\u043d\u043e\u0441\u0442\u044c. \u042d\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u043c \u0434\u043b\u044f \u0448\u0438\u0440\u043e\u043a\u043e\u0433\u043e \u043a\u0440\u0443\u0433\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432, \u043e\u0442 \u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0434\u043e \u043f\u0440\u043e\u043c\u044b\u0448\u043b\u0435\u043d\u043d\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439.<\/p>\n<p>\u0414\u0430\u043d\u043d\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 <strong>\u0434\u0432\u0430 \u043f\u043e\u0434\u0445\u043e\u0434\u0430 \u043a \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 UARTlite \u0447\u0435\u0440\u0435\u0437 XDMA<\/strong>:<\/p>\n<ol>\n<li>\n<p><strong>\u041a\u043b\u0430\u0441\u0441\u0438\u0447\u0435\u0441\u043a\u0438\u0439 Linux-\u0434\u0440\u0430\u0439\u0432\u0435\u0440 \u0441 TTY<\/strong>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e\u043c \u043a\u0430\u043a \u0441 \u043e\u0431\u044b\u0447\u043d\u044b\u043c <code>UART<\/code><\/p>\n<\/li>\n<li>\n<p><strong>\u041f\u0440\u044f\u043c\u0430\u044f \u0440\u0430\u0431\u043e\u0442\u0430 \u0447\u0435\u0440\u0435\u0437 Python<\/strong> \u2013 \u0434\u0430\u0451\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0440\u0430\u0437\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0431\u0435\u0437 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f kernel \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u043e\u0432, \u0430 \u0442\u0430\u043a \u0436\u0435 \u043e\u0442\u043b\u0430\u0436\u0438\u0432\u0430\u0442\u044c \u043a\u043e\u0434 \u0432 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u0442\u043d\u043e\u043c \u0440\u0435\u0436\u0438\u043c\u0435 \u043f\u043e \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044e \u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u043e\u0439 \u0432 kernel.<\/p>\n<\/li>\n<\/ol>\n<h4>\u0414\u043e\u0441\u0442\u043e\u0438\u043d\u0441\u0442\u0432\u0430 \u0440\u0435\u0448\u0435\u043d\u0438\u044f:<\/h4>\n<p>\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0433\u043e Linux TTY<\/p>\n<p>\u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u044b \u0447\u0435\u0440\u0435\u0437 Python \u0431\u0435\u0437 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430<\/p>\n<h4>\u0412\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0435 \u0443\u043b\u0443\u0447\u0448\u0435\u043d\u0438\u044f:<\/h4>\n<p>\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u043f\u0440\u0435\u0440\u044b\u0432\u0430\u043d\u0438\u0439 \u0432\u043c\u0435\u0441\u0442\u043e <strong>polling<\/strong><\/p>\n<hr\/>\n<h3>7. \u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h3>\n<p>\u0420\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430 <strong>Linux-\u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430<\/strong> \u0438 \u0440\u0430\u0431\u043e\u0442\u0430 \u0441 <strong>XDMA \u0447\u0435\u0440\u0435\u0437 Python<\/strong> \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <code>UARTlite<\/code> \u0438 \u0434\u0440\u0443\u0433\u0438\u0435 IP \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445.<\/p>\n<p><strong>\u0422\u0430\u043a \u0436\u0435 \u0441\u0442\u0430\u0442\u044c\u044f \u0435\u0441\u0442\u044c \u043d\u0430 <\/strong><a href=\"https:\/\/medium.com\/@tyutinkonstantin\/developing-a-uartlite-driver-over-xdma-pcie-on-a-custom-sdr-board-bridging-axi-ip-to-linux-via-51fa7479dae3\" rel=\"noopener noreferrer nofollow\"><strong>Medium<\/strong><\/a><strong>!<\/strong><\/p>\n<h3>\ud83d\udcda \u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u044b<\/h3>\n<ul>\n<li>\n<p><a href=\"https:\/\/github.com\/MarsWise\/uartlie_xdma\" rel=\"noopener noreferrer nofollow\">UARTLite XDMA Driver GitHub Repository<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/www.xilinx.com\/support\/documentation\/ip_documentation\/axi_uartlite\/v2_0\/pg142-axi-uartlite.pdf\" rel=\"noopener noreferrer nofollow\">AXI UARTLite Product Guide (PG142)<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/www.xilinx.com\/support\/documentation\/ip_documentation\/xdma\/v4_1\/pg195-pcie-dma.pdf\" rel=\"noopener noreferrer nofollow\">XDMA PCIe DMA Product Guide (PG195)<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/github.com\/Xilinx\/dma_ip_drivers\" rel=\"noopener noreferrer nofollow\">Xilinx dma_ip_drivers GitHub<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/www.kernel.org\/doc\/html\/latest\/driver-api\/tty.html\" rel=\"noopener noreferrer nofollow\">Linux TTY Subsystem Documentation<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/www.simcom.com\/product\/SIM68.html\" rel=\"noopener noreferrer nofollow\">SIM68 GPS Module Datasheet<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/pcisig.com\/specifications\/pciexpress\/specifications\" rel=\"noopener noreferrer nofollow\">PCIe Specification Overview<\/a><\/p>\n<\/li>\n<\/ul>\n<p>\u0415\u0441\u043b\u0438 \u044d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f \u043f\u043e\u043c\u043e\u0433\u043b\u0430 \u0432\u0430\u043c \u043d\u0435 \u0431\u043e\u044f\u0442\u044c\u0441\u044f \u043f\u0438\u0441\u0430\u0442\u044c \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u044b, \u0438\u043b\u0438 \u0445\u043e\u0442\u044f \u0431\u044b \u0441\u044d\u043a\u043e\u043d\u043e\u043c\u0438\u043b\u0430 \u043f\u0430\u0440\u0443 \u0432\u0435\u0447\u0435\u0440\u043e\u0432 \u043d\u0430 \u043e\u0442\u043b\u0430\u0434\u043a\u0435 XDMA \u2014 \u0437\u043d\u0430\u0447\u0438\u0442, \u044f \u0441\u0442\u0430\u0440\u0430\u043b\u0441\u044f \u043d\u0435 \u0437\u0440\u044f. \ud83d\ude09 <\/p>\n<p>\u0412 \u043c\u0438\u0440\u0435 FPGA \u0438 Linux \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u043e\u0432 \u0432\u0441\u0435\u0433\u0434\u0430 \u043d\u0430\u0439\u0434\u0451\u0442\u0441\u044f \u0447\u0442\u043e-\u0442\u043e, \u0447\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043a\u0440\u0430\u0441\u0438\u0432\u0435\u0435. \u0413\u043b\u0430\u0432\u043d\u043e\u0435 \u2014 \u043d\u0435 \u0431\u043e\u044f\u0442\u044c\u0441\u044f \u043b\u0435\u0437\u0442\u044c \u043f\u043e\u0434 \u043a\u0430\u043f\u043e\u0442. \u0412\u0441\u0435\u043c \u043b\u0451\u0433\u043a\u043e\u0439 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438 <br \/>\u0423\u0434\u0430\u0447\u043d\u043e\u0439 \u0441\u0431\u043e\u0440\u043a\u0438, \u043c\u044f\u0433\u043a\u0438\u0445 \u0437\u0430\u0433\u0440\u0443\u0437\u043e\u043a, \u0438 \u0447\u0442\u043e\u0431 <code>dmesg<\/code> \u0432\u0441\u0435\u0433\u0434\u0430 \u0431\u044b\u043b \u043f\u043e\u043b\u043e\u043d \u0442\u043e\u043b\u044c\u043a\u043e \u0445\u043e\u0440\u043e\u0448\u0438\u043c\u0438 \u043d\u043e\u0432\u043e\u0441\u0442\u044f\u043c\u0438, \u0438 \u043c\u0435\u043d\u044c\u0448\u0435 kernel panic!\ud83d\ude4c<\/p>\n<p><strong>\ud83d\udc49 \u041f\u043e\u043d\u0440\u0430\u0432\u0438\u043b\u043e\u0441\u044c? \u0416\u0434\u0443 \u0432\u0430\u0448\u0438 \u0432\u043e\u043f\u0440\u043e\u0441\u044b \u0438 \u043c\u044b\u0441\u043b\u0438 \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445!<\/strong><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/900644\/\"> https:\/\/habr.com\/ru\/articles\/900644\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u0418\u043d\u043e\u0433\u0434\u0430 \u0441\u0430\u043c\u044b\u0435 \u043f\u0440\u043e\u0441\u0442\u044b\u0435 \u0437\u0430\u0434\u0430\u0447\u0438 \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u044e\u0442\u0441\u044f \u0432 \u043c\u0438\u043d\u0438-\u043f\u0440\u0438\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043a\u043e\u0433\u0434\u0430 \u0432\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c UARTLite \u043d\u0430 FPGA \u043a Linux \u0447\u0435\u0440\u0435\u0437 PCIe. \u041a\u0430\u0436\u0435\u0442\u0441\u044f, \u043d\u0443 \u0447\u0442\u043e \u0442\u0430\u043c? \u041f\u0430\u0440\u0443 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u043e\u0432, \u043f\u0430\u0440\u0430 \u043f\u0440\u0435\u0440\u044b\u0432\u0430\u043d\u0438\u0439\u2026 \u0410 \u043d\u0430 \u0434\u0435\u043b\u0435 \u2014 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0434\u043d\u0435\u0439 \u0437\u0430 Vivado, \u043e\u0442\u043b\u0430\u0434\u043a\u0430 XDMA \u0438 \u0431\u043e\u0440\u044c\u0431\u0430 \u0441 \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430\u043c\u0438. \ud83d\ude05 <\/p>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443, \u043a\u0430\u043a \u044f \u0432\u0441\u0451-\u0442\u0430\u043a\u0438 \u043f\u043e\u0431\u0435\u0434\u0438\u043b UARTLite \u0447\u0435\u0440\u0435\u0437 XDMA \u0438 \u043a\u0430\u043a \u0432\u044b \u0441\u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u044c \u044d\u0442\u043e \u0431\u0435\u0437 \u0431\u043e\u043b\u0438. <\/p>\n<figure class=\"\"><\/figure>\n<h4>\u0410\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044f<\/h4>\n<p>\u042d\u0442\u043e\u0442 \u043f\u0440\u043e\u0435\u043a\u0442 \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u0442, \u043a\u0430\u043a \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043f\u0435\u0440\u0438\u0444\u0435\u0440\u0438\u0439\u043d\u043e\u0435 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e UARTLite \u043d\u0430 \u0431\u0430\u0437\u0435 FPGA \u043a \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u043c Linux \u0447\u0435\u0440\u0435\u0437 <strong>PCIe<\/strong> <strong>XDMA<\/strong>.<br \/>\u0420\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c <strong>TTY-\u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441<\/strong> (\u0434\u0440\u0430\u0439\u0432\u0435\u0440 <strong>Linux TTY<\/strong> ) <code>\/dev\/ttyULx<\/code> \u0438 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u0431\u044b\u0441\u0442\u0440\u043e\u0433\u043e \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u0447\u0435\u0440\u0435\u0437 <strong>Python<\/strong> \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c <code>mmap<\/code>.<br \/>\u0418\u0434\u0435\u0430\u043b\u044c\u043d\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u0434\u043b\u044f \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438 \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u044b <strong>SDR<\/strong>, \u0440\u043e\u0431\u043e\u0442\u043e\u0442\u0435\u0445\u043d\u0438\u043a\u0438 \u0438 \u0432\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c\u044b\u0445 \u0441\u0438\u0441\u0442\u0435\u043c!<\/p>\n<ul>\n<li>\n<p><strong>\u0427\u0442\u043e \u0437\u0430 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e?<\/strong><br \/>\u2794 \u041c\u043e\u044f SDR-\u043f\u043b\u0430\u0442\u0430 \u043d\u0430 <strong>FPGA Artix-7<\/strong>, <strong>GPS SIM68<\/strong> \u043c\u043e\u0434\u0443\u043b\u0435\u043c \u0438 <strong>AD9361<\/strong> RF \u0440\u0430\u043d\u0441\u0438\u0432\u0435\u0440\u043e\u043c, \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u043c PCIe \u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c\u044e \u043e\u0431\u043c\u0435\u043d\u0430 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u043c\u0435\u0436\u0434\u0443 <strong>FPGA<\/strong> \u0438 <strong>Linux<\/strong> \u0447\u0435\u0440\u0435\u0437 <strong>XDMA<\/strong>.<\/p>\n<\/li>\n<li>\n<p><strong>\u0427\u0442\u043e \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0434\u0435\u043b\u0430\u0442\u044c?<\/strong><br \/>\u2794 \u0420\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u043c Linux-\u0434\u0440\u0430\u0439\u0432\u0435\u0440 \u0434\u043b\u044f UARTLite \u0447\u0435\u0440\u0435\u0437 XDMA \u0438 \u043f\u0440\u043e\u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u043c \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u043f\u0440\u044f\u043c\u043e\u0433\u043e \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u0447\u0435\u0440\u0435\u0437 Python.<\/p>\n<\/li>\n<li>\n<p><strong>\u041f\u043e\u0447\u0435\u043c\u0443 \u044d\u0442\u043e \u0432\u0430\u0436\u043d\u043e?<\/strong><br \/>\u2794 \u0422\u0430\u043a\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043b\u0435\u0433\u043a\u043e \u0438\u043d\u0442\u0435\u0433\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0435 FPGA-\u043f\u0435\u0440\u0438\u0444\u0435\u0440\u0438\u0438 \u0432 Linux-\u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0431\u0435\u0437 \u0441\u043b\u043e\u0436\u043d\u043e\u0439 \u0440\u0443\u0447\u043d\u043e\u0439 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438, \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0432 SDR-\u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445, \u0440\u043e\u0431\u043e\u0442\u043e\u0442\u0435\u0445\u043d\u0438\u043a\u0435, \u0430\u0432\u0442\u043e\u043d\u043e\u043c\u043d\u044b\u0445 \u0441\u0438\u0441\u0442\u0435\u043c\u0430\u0445 \u0438 IoT.<\/p>\n<hr\/>\n<h3>1. \u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435<\/h3>\n<p>\u0412\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c\u044b\u0435 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u043d\u0430 \u0431\u0430\u0437\u0435 <strong>FPGA<\/strong> \u0448\u0438\u0440\u043e\u043a\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u044e\u0442\u0441\u044f \u0432 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u043e-\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c\u044b\u0445 \u0440\u0430\u0434\u0438\u043e\u0441\u0438\u0441\u0442\u0435\u043c\u0430\u0445 (<strong>SDR<\/strong>, Software-Defined Radio).  \u041f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u043e-\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c\u044b\u0435 \u0440\u0430\u0434\u0438\u043e\u0441\u0438\u0441\u0442\u0435\u043c\u044b (SDR) \u0442\u0440\u0435\u0431\u0443\u044e\u0442 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0433\u043e \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u043c\u0435\u0436\u0434\u0443 FPGA \u0438 CPU, \u0447\u0442\u043e \u043e\u0441\u043b\u043e\u0436\u043d\u044f\u0435\u0442\u0441\u044f \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0435\u0439 \u043f\u0435\u0440\u0438\u0444\u0435\u0440\u0438\u0438 \u0447\u0435\u0440\u0435\u0437 PCIe. \u042d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f \u0440\u0435\u0448\u0430\u0435\u0442 \u0437\u0430\u0434\u0430\u0447\u0443 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430 \u0434\u043b\u044f UARTlite \u0447\u0435\u0440\u0435\u0437 XDMA, \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0438\u0440\u0443\u044f \u0434\u0432\u0430 \u043f\u043e\u0434\u0445\u043e\u0434\u0430: \u0447\u0435\u0440\u0435\u0437 \u044f\u0434\u0440\u043e Linux \u0438 Python. \u0426\u0435\u043b\u044c \u2014 \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0443, \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043d\u0430 \u0431\u0430\u0437\u0435 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0439 SDR-\u043f\u043b\u0430\u0442\u044b. <\/p>\n<p><strong>\u041e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430:<\/strong><\/p>\n<\/li>\n<li>\n<p>\u2705 <strong>\u0420\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u043d\u0430\u044f \u0441 \u043d\u0443\u043b\u044f SDR-\u043f\u043b\u0430\u0442\u0430<\/strong> \u043d\u0430 <strong>FPGA Artix-7 \u0438 AD9361<\/strong><\/p>\n<\/li>\n<li>\n<p>\u2705 <strong>\u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u043e\u0439 \u043f\u043b\u0430\u0442\u044b<\/strong> \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f <a href=\"https:\/\/www.lattepanda.com\/lattepanda-sigma\" rel=\"noopener noreferrer nofollow\"><strong>LattePanda Sigma<\/strong><\/a> <\/p>\n<\/li>\n<li>\n<p>\u2705 <strong>\u0412\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0439 UARTlite<\/strong> \u0434\u043b\u044f \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441 GPS \u043c\u043e\u0434\u0443\u043b\u0435\u043c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u044b\u043c \u043a FPGA  <\/p>\n<\/li>\n<li>\n<p>\u2705 <strong>XDMA \u0447\u0435\u0440\u0435\u0437 PCIe<\/strong> \u0434\u043b\u044f \u0432\u044b\u0441\u043e\u043a\u043e\u0441\u043a\u043e\u0440\u043e\u0441\u0442\u043d\u043e\u0439 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0434\u0430\u043d\u043d\u044b\u0445<\/p>\n<\/li>\n<li>\n<p>\u2705 <strong>\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u0434\u0432\u0443\u0445 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0440\u0430\u0431\u043e\u0442\u044b:<\/strong><\/p>\n<ul>\n<li>\n<p><strong>Linux-\u0434\u0440\u0430\u0439\u0432\u0435\u0440 \u0441 TTY-\u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u043c<\/strong> (<code>\/dev\/ttyULx<\/code>)<\/p>\n<\/li>\n<li>\n<p><strong>\u041f\u0440\u044f\u043c\u0430\u044f \u0440\u0430\u0431\u043e\u0442\u0430 \u0441 UARTlite \u043d\u0430 Python \u0447\u0435\u0440\u0435\u0437 XDMA<\/strong><\/p>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<hr\/>\n<h3>2. \u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 \u0440\u0435\u0448\u0435\u043d\u0438\u044f<\/h3>\n<p>\u041f\u0440\u043e\u0435\u043a\u0442 \u043e\u0441\u043d\u043e\u0432\u0430\u043d \u043d\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u043d\u043e\u0439 \u0441 \u043d\u0443\u043b\u044f SDR-\u043f\u043b\u0430\u0442\u0435 \u0441 FPGA \u0438 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u043c PCIe:  <\/p>\n<figure class=\"full-width\"><\/figure>\n<figure class=\"full-width\"><\/figure>\n<figure class=\"full-width\"><\/figure>\n<p><strong>\u041e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430:<\/strong><\/p>\n<div>\n<div class=\"table\">\n<table>\n<tbody>\n<tr>\n<th>\n<p align=\"left\">\u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442<\/p>\n<\/th>\n<th>\n<p align=\"left\">\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435<\/p>\n<\/th>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\"><strong>FPGA<\/strong><\/p>\n<\/td>\n<td>\n<p align=\"left\">Xilinx Artix-7 (XC7A200T)<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\"><strong>RF-\u0442\u0440\u0430\u043d\u0441\u0438\u0432\u0435\u0440<\/strong><\/p>\n<\/td>\n<td>\n<p align=\"left\">Analog Devices AD9361\u00a0(70 MHz \u2013 6 GHz)<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\"><strong>GPS-\u043c\u043e\u0434\u0443\u043b\u044c<\/strong><\/p>\n<\/td>\n<td>\n<p align=\"left\">SIM68 (NMEA 0183 Output)<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\"><strong>DDR<\/strong><\/p>\n<\/td>\n<td>\n<p align=\"left\">MT41K256M16HA-125 AAT<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\"><strong>\u0425\u043e\u0441\u0442-\u043f\u043b\u0430\u0442\u0430<\/strong><\/p>\n<\/td>\n<td>\n<p align=\"left\"><a href=\"https:\/\/www.lattepanda.com\/lattepanda-sigma\" rel=\"noopener noreferrer nofollow\">LattePanda Sigma<\/a><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\"><strong>\u0418\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438<\/strong><\/p>\n<\/td>\n<td>\n<p align=\"left\">PCIe Gen1 x4\u00a0(10 Gbps \u0447\u0435\u0440\u0435\u0437 \u0440\u0430\u0437\u044a\u0451\u043c M.2)<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\"><strong>\u041f\u0435\u0440\u0435\u0434\u0430\u0447\u0430 \u0434\u0430\u043d\u043d\u044b\u0445<\/strong><\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0427\u0435\u0440\u0435\u0437 XDMA \u0438 AXI \u0448\u0438\u043d\u0443<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\"><strong>UART-\u043f\u0435\u0440\u0438\u0444\u0435\u0440\u0438\u044f<\/strong><\/p>\n<\/td>\n<td>\n<p align=\"left\">AXI UARTLite IP Core (9600 \u0431\u043e\u0434)<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\"><strong>\u0424\u043e\u0440\u043c-\u0444\u0430\u043a\u0442\u043e\u0440<\/strong><\/p>\n<\/td>\n<td>\n<p align=\"left\">M.2 2280 (80mm \u00d7 22mm)<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<h4>\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0441\u0438\u0441\u0442\u0435\u043c\u044b<\/h4>\n<p>\u0421\u0438\u0441\u0442\u0435\u043c\u0430 \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0438 \u0438\u0445 \u0441\u0432\u044f\u0437\u0435\u0439:<\/p>\n<ol>\n<li>\n<p><strong>SIM68 (GPS Module)<\/strong><\/p>\n<ul>\n<li>\n<p>\u042d\u0442\u043e GPS-\u043c\u043e\u0434\u0443\u043b\u044c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u0447\u0435\u0440\u0435\u0437 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 UART.<\/p>\n<\/li>\n<li>\n<p>\u0421\u0432\u044f\u0437\u0430\u043d \u0441 <strong>UartLite (UART Controller)<\/strong> \u0447\u0435\u0440\u0435\u0437 <strong>UART<\/strong>.<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><strong>UartLite (UART Controller)<\/strong><\/p>\n<ul>\n<li>\n<p>\u041a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440 UART, \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u044e\u0449\u0438\u0439 \u0434\u0430\u043d\u043d\u044b\u0435 \u043e\u0442 GPS-\u043c\u043e\u0434\u0443\u043b\u044f.<\/p>\n<\/li>\n<li>\n<p>\u0421\u0432\u044f\u0437\u0430\u043d \u0441 <strong>XDMA (PCIe DMA)<\/strong> \u0447\u0435\u0440\u0435\u0437 \u0448\u0438\u043d\u0443 <strong>AXI<\/strong>.<\/p>\n<p><a href=\"https:\/\/docs.amd.com\/v\/u\/en-US\/pg142-axi-uartlite\" rel=\"noopener noreferrer nofollow\">AXI UARTLite Product Guide (PG142)<\/a><\/p>\n<p><a href=\"https:\/\/docs.amd.com\/r\/en-US\/pg059-axi-interconnect\" rel=\"noopener noreferrer nofollow\">AXI Interconnect Product Guide (PG059)<\/a><\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><strong>XDMA (PCIe DMA)<\/strong><\/p>\n<ul>\n<li>\n<p>\u041a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440 \u043f\u0440\u044f\u043c\u043e\u0433\u043e \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u043f\u0430\u043c\u044f\u0442\u0438 (DMA) \u0447\u0435\u0440\u0435\u0437 PCIe. (<a href=\"https:\/\/docs.amd.com\/r\/en-US\/pg195-pcie-dma\" rel=\"noopener noreferrer nofollow\">AXI PCIe DMA Product Guide (PG195)<\/a>)<\/p>\n<\/li>\n<li>\n<p>\u0421\u0432\u044f\u0437\u0430\u043d \u0441 <strong>CPU (Latte Panda Sigma)<\/strong> \u0447\u0435\u0440\u0435\u0437 <strong>PCIe<\/strong>.<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><strong>CPU (Latte Panda Sigma)<\/strong><\/p>\n<ul>\n<li>\n<p>\u0426\u0435\u043d\u0442\u0440\u0430\u043b\u044c\u043d\u044b\u0439 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u043e\u0442 XDMA.<\/p>\n<\/li>\n<li>\n<p>\u0421\u0432\u044f\u0437\u0430\u043d \u0441 <strong>Linux Kernel<\/strong> \u0447\u0435\u0440\u0435\u0437 \u043e\u0431\u043e\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 <strong>User-space<\/strong> (\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f).<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><strong>Linux Kernel<\/strong><\/p>\n<ul>\n<li>\n<p>\u042f\u0434\u0440\u043e \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b Linux, \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0435\u0435 \u043d\u0430 CPU.<\/p>\n<\/li>\n<li>\n<p>\u0421\u0432\u044f\u0437\u0430\u043d \u0441 <strong>User Application<\/strong> \u0447\u0435\u0440\u0435\u0437 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u044b <strong>TTY \/ Python<\/strong>.<\/p>\n<p><a href=\"https:\/\/docs.kernel.org\/driver-api\/tty\/index.html\" rel=\"noopener noreferrer nofollow\">Linux TTY Documentation<\/a><\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><strong>User Application<\/strong><\/p>\n<ul>\n<li>\n<p>\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0443\u0435\u0442 \u0441 \u044f\u0434\u0440\u043e\u043c Linux \u0434\u043b\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u0434\u0430\u043d\u043d\u044b\u043c, \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u0447\u0435\u0440\u0435\u0437 TTY-\u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 \u0438\u043b\u0438 \u0441\u043a\u0440\u0438\u043f\u0442\u044b \u043d\u0430 Python.<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<h4>2.1 \u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u043d\u0430\u044f \u0441\u0445\u0435\u043c\u0430 \u0441\u0438\u0441\u0442\u0435\u043c\u044b<\/h4>\n<p>\u041d\u0430 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0438 \u043d\u0438\u0436\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0430 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u043d\u0430\u044f \u0441\u0445\u0435\u043c\u0430 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0441 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u043c \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u043e\u043c: <\/p>\n<figure class=\"\"><\/figure>\n<p>\u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u0440\u043e\u0445\u043e\u0434\u044f\u0442 \u043f\u043e \u0446\u0435\u043f\u043e\u0447\u043a\u0435:<\/p>\n<ol>\n<li>\n<p><strong>SIM68<\/strong> \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u0442 <a href=\"https:\/\/receiverhelp.trimble.com\/alloy-gnss\/en-us\/NMEA-0183messages_MessageOverview.html\" rel=\"noopener noreferrer nofollow\">NMEA<\/a>-\u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0432 <strong>UartLite<\/strong> \u043d\u0430 FPGA \u0447\u0435\u0440\u0435\u0437 <strong>UART<\/strong><\/p>\n<\/li>\n<li>\n<p><strong>UartLite<\/strong> \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0443\u0435\u0442 \u0441 <strong>XDMA (PCIe DMA)<\/strong> \u0447\u0435\u0440\u0435\u0437 <strong>AXI<\/strong>.<\/p>\n<\/li>\n<li>\n<p><strong>XDMA<\/strong> \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u0447\u0435\u0440\u0435\u0437 <strong>PCIe<\/strong> \u0432 <strong>CPU (Latte Panda Sigma)<\/strong>.<\/p>\n<\/li>\n<li>\n<p><strong>CPU<\/strong> \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 <strong>user-space<\/strong> \u0438 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0443\u0435\u0442 \u0441 <strong>\u044f\u0434\u0440\u043e\u043c Linux<\/strong>.<\/p>\n<\/li>\n<li>\n<p><strong>Linux Kernel<\/strong> \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 <strong>TTY \/ Python API<\/strong> \u0434\u043b\u044f <strong>\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f<\/strong> (<code>\/dev\/ttyUL0<\/code>).<\/p>\n<\/li>\n<li>\n<p><strong>User Application<\/strong> \u2013 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0443\u0435\u0442 \u0441 UART \u0447\u0435\u0440\u0435\u0437 Python \u0438\u043b\u0438 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b.<\/p>\n<\/li>\n<\/ol>\n<p>\u041d\u0430 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0438 \u043d\u0438\u0436\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0430 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u043d\u0430\u044f \u0441\u0445\u0435\u043c\u0430 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u043f\u0440\u0438 \u043f\u0440\u044f\u043c\u043e\u043c \u0434\u043e\u0441\u0442\u0443\u043f\u0435 \u0447\u0435\u0440\u0435\u0437 Python:<\/p>\n<figure class=\"full-width\">\n<div><figcaption>Screenshot from 20250410 171712png<\/figcaption><\/div>\n<\/figure>\n<p>\u0414\u0430\u043d\u043d\u044b\u0435 \u043f\u0440\u043e\u0445\u043e\u0434\u044f\u0442 \u043f\u043e \u0446\u0435\u043f\u043e\u0447\u043a\u0435:<\/p>\n<ol>\n<li>\n<p><strong>SIM68<\/strong> \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u0442 <a href=\"https:\/\/receiverhelp.trimble.com\/alloy-gnss\/en-us\/NMEA-0183messages_MessageOverview.html\" rel=\"noopener noreferrer nofollow\">NMEA<\/a>-\u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0432 <strong>UartLite<\/strong> \u043d\u0430 FPGA \u0447\u0435\u0440\u0435\u0437 <strong>UART<\/strong>.<\/p>\n<\/li>\n<li>\n<p><strong>UartLite<\/strong> \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0443\u0435\u0442 \u0441 <strong>XDMA (PCIe DMA)<\/strong> \u0447\u0435\u0440\u0435\u0437 <strong>AXI<\/strong>.<\/p>\n<\/li>\n<li>\n<p><strong>XDMA<\/strong> \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u0447\u0435\u0440\u0435\u0437 <strong>PCIe<\/strong> \u0432 <strong>CPU (Latte Panda Sigma)<\/strong>.<\/p>\n<\/li>\n<li>\n<p><strong>CPU<\/strong> \u0447\u0435\u0440\u0435\u0437 <code>\/dev\/xdma0_user<\/code> \u043c\u0430\u043f\u0438\u0442 \u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u043e \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <strong>mmap<\/strong>.<\/p>\n<\/li>\n<li>\n<p><strong>Python Application<\/strong> \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u0447\u0438\u0442\u0430\u0435\u0442 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u044b UARTlite (RX FIFO \/ TX FIFO), \u043c\u0438\u043d\u0443\u044f \u0434\u0440\u0430\u0439\u0432\u0435\u0440 \u044f\u0434\u0440\u0430.<\/p>\n<\/li>\n<\/ol>\n<p><strong>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c<\/strong>, \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0431\u0435\u0437 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0433\u043e Linux TTY-\u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430, \u0447\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442:<\/p>\n<ul>\n<li>\n<p>\u041c\u0438\u043d\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u043a\u043b\u0430\u0434\u043d\u044b\u0435 \u0440\u0430\u0441\u0445\u043e\u0434\u044b \u043d\u0430 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u0435 \u0432\u044b\u0437\u043e\u0432\u044b.<\/p>\n<\/li>\n<li>\n<p>\u0421\u043d\u0438\u0437\u0438\u0442\u044c \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u043d\u0430 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440 \u0437\u0430 \u0441\u0447\u0451\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f <strong>async IO<\/strong>.<\/p>\n<\/li>\n<li>\n<p>\u0411\u044b\u0441\u0442\u0440\u043e \u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438 \u043e\u0442\u043b\u0430\u0436\u0438\u0432\u0430\u0442\u044c \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 FPGA.<\/p>\n<\/li>\n<\/ul>\n<p>\u041d\u0430 \u0434\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u0435 \u043d\u0438\u0436\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u043e, \u043a\u0430\u043a \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043e\u0431\u043c\u0435\u043d \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u043c\u0435\u0436\u0434\u0443 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u043c\u0438 \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0435:<\/p>\n<figure class=\"full-width\"><\/figure>\n<h4>2.2 \u0411\u043b\u043e\u043a-\u0441\u0445\u0435\u043c\u0430 \u0432 Vivado<\/h4>\n<ul>\n<li>\n<p>\u0412 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f <strong>XDMA (PCIe-DMA Bridge)<\/strong><\/p>\n<\/li>\n<li>\n<p>AXI Interconnect \u0441\u0432\u044f\u0437\u044b\u0432\u0430\u0435\u0442 <strong>XDMA<\/strong> \u0441 <strong>AXI Register Slice<\/strong>, <strong>AXI UARTLite<\/strong><\/p>\n<\/li>\n<li>\n<p><strong>AXI UARTLite \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d \u043a \u0441\u0438\u0441\u0442\u0435\u043c\u0435 \u0447\u0435\u0440\u0435\u0437 AXI Interconnect \u0438 \u043a GPS \u043c\u043e\u0434\u0443\u043b\u044e SIM68 <\/strong><\/p>\n<\/li>\n<li>\n<p>\u0415\u0441\u0442\u044c \u0442\u0430\u043a\u0436\u0435 <strong>AXI GPIO<\/strong>, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f*<\/p>\n<\/li>\n<\/ul>\n<p><strong>\u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043f\u043e\u0442\u043e\u043a \u0434\u0430\u043d\u043d\u044b\u0445:<\/strong><br \/><strong>FPGA<\/strong> \u2194 <strong>AXI Interconnect<\/strong> \u2194 <strong>AXI UARTLite<\/strong> \u2194 <strong>PCIe XDMA<\/strong> \u2194 <strong>CPU\/Linux<\/strong><\/p>\n<p>\u041d\u0438\u0436\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u0441\u043a\u0440\u0438\u043d \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0432 Vivado \u0438\u0437 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430:<\/p>\n<figure class=\"full-width\">\n<div><figcaption>\u0421\u043d\u0438\u043c\u043e\u043a \u044d\u043a\u0440\u0430\u043d\u0430 20250313 211436png<\/figcaption><\/div>\n<\/figure>\n<p>\u0438\u043b\u0438 \u043f\u0440\u043e\u0441\u0442\u0430\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f UartLite:<\/p>\n<figure class=\"full-width\">\n<div><figcaption>Screenshot from 20250410 171633png<\/figcaption><\/div>\n<\/figure>\n<h4>2.3 \u0420\u0430\u0437\u0431\u043e\u0440 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 XDMA \u0438 UartLite:<\/h4>\n<figure class=\"full-width\"><\/figure>\n<h3>AXI UARTLite (\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 IP)<\/h3>\n<ul>\n<li>\n<p><strong>\u0427\u0430\u0441\u0442\u043e\u0442\u0430 AXI CLK:<\/strong> <code>62.5 \u041c\u0413\u0446<\/code><\/p>\n<\/li>\n<li>\n<p><strong>\u0421\u043a\u043e\u0440\u043e\u0441\u0442\u044c UART:<\/strong> <code>9600 \u0431\u043e\u0434<\/code><\/p>\n<\/li>\n<li>\n<p><strong>\u0414\u043b\u0438\u043d\u0430 \u0434\u0430\u043d\u043d\u044b\u0445:<\/strong> <code>8 \u0431\u0438\u0442<\/code><\/p>\n<\/li>\n<li>\n<p><strong>\u0427\u0435\u0442\u043d\u043e\u0441\u0442\u044c (Parity):<\/strong> <code>\u041e\u0442\u043a\u043b\u044e\u0447\u0435\u043d\u0430 (No Parity)<\/code><\/p>\n<\/li>\n<\/ul>\n<p>\u042d\u0442\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0435 \u0434\u043b\u044f UARTLite, \u043d\u043e \u0435\u0441\u043b\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e <strong>\u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0442\u044c \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c<\/strong> \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438, \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u0441\u0442\u0430\u0432\u0438\u0442\u044c <code>115200 \u0431\u043e\u0434<\/code>.<\/p>\n<h3>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 DMA (PCIe : DMA)<\/h3>\n<p><a href=\"https:\/\/docs.amd.com\/r\/en-US\/pg195-pcie-dma\" rel=\"noopener noreferrer nofollow\">AXI PCIe DMA Product Guide (PG195)<\/a><\/p>\n<figure class=\"full-width\"><\/figure>\n<figure class=\"full-width\"><\/figure>\n<figure class=\"full-width\"><\/figure>\n<figure class=\"full-width\"><\/figure>\n<figure class=\"full-width\"><\/figure>\n<p><strong>\u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043a\u0430\u043d\u0430\u043b\u043e\u0432<\/strong><\/p>\n<ul>\n<li>\n<p><strong>1 \u043a\u0430\u043d\u0430\u043b \u043d\u0430 \u0447\u0442\u0435\u043d\u0438\u0435 (H2C)<\/strong><\/p>\n<\/li>\n<li>\n<p><strong>1 \u043a\u0430\u043d\u0430\u043b \u043d\u0430 \u0437\u0430\u043f\u0438\u0441\u044c (C2H)<\/strong><\/p>\n<\/li>\n<li>\n<p>\u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e <strong>Request IDs<\/strong>: 32 (\u0447\u0442\u0435\u043d\u0438\u0435), 16 (\u0437\u0430\u043f\u0438\u0441\u044c)<\/p>\n<\/li>\n<li>\n<p><strong>AXI ID Width<\/strong>: 4 (\u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0439 \u0432 AXI)<\/p>\n<p><strong>Descriptor Bypass (\u041e\u0442\u043a\u043b\u044e\u0447\u0435\u043d)<\/strong><\/p>\n<\/li>\n<li>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0435 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0431\u0443\u0444\u0435\u0440\u0430\u043c\u0438 (\u0431\u0435\u0437 \u0431\u0430\u0439\u043f\u0430\u0441\u0430).<\/p>\n<\/li>\n<\/ul>\n<h3>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043f\u0440\u0435\u0440\u044b\u0432\u0430\u043d\u0438\u0439 (PCIe : MISC)<\/h3>\n<p><strong>\u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043f\u0440\u0435\u0440\u044b\u0432\u0430\u043d\u0438\u0439:<\/strong> 16<br \/> <strong>MSI \u0432\u043a\u043b\u044e\u0447\u0435\u043d<\/strong> (Message Signaled Interrupts)<br \/> <strong>\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u044b\u0435 \u0442\u0435\u0433\u0438 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u044b<\/strong> (Extended Tag Field)<\/p>\n<h3>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 BAR (PCIe : BARS)<\/h3>\n<p><strong>PCIe \u2192 AXI Lite Master Interface<\/strong><\/p>\n<ul>\n<li>\n<p><strong>\u0420\u0430\u0437\u043c\u0435\u0440 \u043f\u0430\u043c\u044f\u0442\u0438:<\/strong> 1MB<\/p>\n<\/li>\n<li>\n<p><strong>\u0410\u0434\u0440\u0435\u0441:<\/strong> <code>0x00000000<\/code> <strong>PCIe \u2192 DMA Interface<\/strong> \u0432\u043a\u043b\u044e\u0447\u0435\u043d<\/p>\n<\/li>\n<\/ul>\n<h3>\u0418\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u044b \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 (PCIe ID)<\/h3>\n<p><strong>Vendor ID:<\/strong> <code>10EE<\/code> (Xilinx)<br \/> <strong>Device ID:<\/strong> <code>7011<\/code><br \/> <strong>Class Code:<\/strong> <code>120000<\/code> (\u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e \u043f\u0430\u043c\u044f\u0442\u0438)<\/p>\n<h3>\u0411\u0430\u0437\u043e\u0432\u044b\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 PCIe (Basic)<\/h3>\n<p>[PCIe Base Specification (official summary)](<a href=\"https:\/\/pcisig.com\/specifications\" rel=\"noopener noreferrer nofollow\">Specifications | PCI-SIG<\/a>)<\/p>\n<p><strong>PCIe x1, 2.5 GT\/s<\/strong><br \/> <strong>AXI Address Width: 64-bit<\/strong><br \/> <strong>AXI Data Width: 64-bit<\/strong><br \/> <strong>AXI Clock: 125 MHz<\/strong><br \/> <strong>\u0420\u0435\u0436\u0438\u043c: AXI Memory Mapped<\/strong><\/p>\n<p>\u0410\u0434\u0440\u0435\u0441\u0441 UartLite: <\/p>\n<figure class=\"full-width\"><\/figure>\n<h4>2.2 \u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 SDR \u043a \u043c\u0430\u0442\u0435\u0440\u0438\u043d\u0441\u043a\u043e\u0439 \u043f\u043b\u0430\u0442\u0435<\/h4>\n<figure class=\"full-width\">\n<div><figcaption>1696959565663 1jpeg<\/figcaption><\/div>\n<\/figure>\n<hr\/>\n<h3>3. \u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430<\/h3>\n<h4>3.1 \u041f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0430 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f<\/h4>\n<p><strong>\u0410\u043f\u043f\u0430\u0440\u0430\u0442\u043d\u0430\u044f \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430:<\/strong><\/p>\n<ul>\n<li>\n<p><strong>SDR-\u043f\u043b\u0430\u0442\u0430:<\/strong> \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u043d\u0430\u044f \u043c\u043d\u043e\u0439, FPGA Artix-7 200T<\/p>\n<\/li>\n<li>\n<p><strong>GPS-\u043c\u043e\u0434\u0443\u043b\u044c:<\/strong> SIM68<\/p>\n<\/li>\n<li>\n<p><strong>\u0418\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u044b:<\/strong> PCIe, UART<\/p>\n<\/li>\n<li>\n<p><strong>\u041c\u0430\u0442\u0435\u0440\u0438\u043d\u0441\u043a\u0430\u044f \u043f\u043b\u0430\u0442\u0430<\/strong>: Latte Panda Sigma<\/p>\n<\/li>\n<\/ul>\n<p><strong>\u041f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u043e\u0435 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0435\u043d\u0438\u0435:<\/strong><\/p>\n<ul>\n<li>\n<p><strong>\u041e\u0421:<\/strong> Linux Kernel 6.x+<\/p>\n<\/li>\n<li>\n<p><strong>\u0418\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b:<\/strong> Vivado, Python, GCC<\/p>\n<\/li>\n<li>\n<p><strong>\u041e\u0442\u043b\u0430\u0434\u043a\u0430:<\/strong> <code>dmesg<\/code>, <code>minicom<\/code><\/p>\n<\/li>\n<\/ul>\n<hr\/>\n<h4>3.2 \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439<\/h4>\n<pre><code class=\"bash\">sudo apt update sudo apt install -y build-essential dkms linux-headers-$(uname -r) git sudo apt install -y pciutils lshw sudo apt install -y gcc-13 g++-13  sudo apt install -y gpsd gpsd-clients<\/code><\/pre>\n<p><strong>\u0427\u0442\u043e \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c?<\/strong><\/p>\n<ul>\n<li>\n<p><code>build-essential<\/code> \u2014 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u0441\u0431\u043e\u0440\u043a\u0438 (<code>gcc<\/code>, <code>make<\/code>, <code>binutils<\/code>)<\/p>\n<\/li>\n<li>\n<p><code>dkms<\/code> \u2014 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043c\u043e\u0434\u0443\u043b\u044f\u043c\u0438 \u044f\u0434\u0440\u0430<\/p>\n<\/li>\n<li>\n<p><code>linux-headers-$(uname -r)<\/code> \u2014 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u0447\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u044b \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u044f\u0434\u0440\u0430<\/p>\n<\/li>\n<li>\n<p><code>git<\/code> \u2014 \u0434\u043b\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u043e\u0432 \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430 XDMA<\/p>\n<\/li>\n<li>\n<p><code>pciutils<\/code> (<code>lspci<\/code>) \u2014 \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440 PCIe-\u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432<\/p>\n<\/li>\n<li>\n<p><code>lshw<\/code> \u2014 \u0434\u0435\u0442\u0430\u043b\u044c\u043d\u0430\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e\u0431 \u043e\u0431\u043e\u0440\u0443\u0434\u043e\u0432\u0430\u043d\u0438\u0438<\/p>\n<\/li>\n<li>\n<p><code>gcc-13<\/code>, <code>g++-13<\/code> \u2014 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440\u044b C \u0438 C++ \u0432\u0435\u0440\u0441\u0438\u0438 13<\/p>\n<\/li>\n<li>\n<p><code>gpsd<\/code>, <code>gpsd-clients<\/code> \u2014 \u0434\u0435\u043c\u043e\u043d\u044b \u0438 \u0443\u0442\u0438\u043b\u0438\u0442\u044b \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 GPS-\u043f\u0440\u0438\u0451\u043c\u043d\u0438\u043a\u0430\u043c\u0438<\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0432\u0435\u0440\u0441\u0438\u0438:<\/p>\n<pre><code class=\"bash\">gcc-13 --version<\/code><\/pre>\n<h4>3.3 \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043e\u0431\u043e\u0440\u0443\u0434\u043e\u0432\u0430\u043d\u0438\u044f<\/h4>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0443\u0431\u0435\u0434\u0438\u043c\u0441\u044f, \u0447\u0442\u043e <strong>PCIe-\u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e (FPGA)<\/strong> \u0440\u0430\u0441\u043f\u043e\u0437\u043d\u0430\u0451\u0442\u0441\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u043e\u0439:<\/p>\n<pre><code class=\"bash\">lspci -d 10ee:<\/code><\/pre>\n<p>\u0415\u0441\u043b\u0438 <strong>XDMA-\u043a\u0430\u0440\u0442\u0430 \u0432\u0438\u0434\u043d\u0430<\/strong>, \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0432\u043e\u0434 \u0442\u0438\u043f\u0430:<\/p>\n<pre><code class=\"bash\">59:00.0 Memory controller: Xilinx Corporation Device 7011<\/code><\/pre>\n<p>\u0412\u043e\u0442 \u0447\u0442\u043e \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u0443 \u043c\u0435\u043d\u044f:<\/p>\n<h4>3.4 \u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430<\/h4>\n<h3>\u041f\u0440\u0438\u043d\u0446\u0438\u043f \u0440\u0430\u0431\u043e\u0442\u044b \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430<\/h3>\n<p>\u041f\u0440\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0435 \u043c\u043e\u0434\u0443\u043b\u044f \u0434\u0440\u0430\u0439\u0432\u0435\u0440 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u0442 <strong>PCIe<\/strong>-\u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e \u0441 <strong>Vendor ID<\/strong> <code>0x10EE<\/code> \u0438 <strong>Device ID<\/strong> <code>0x7011<\/code>. \u041f\u043e\u0441\u043b\u0435 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043e\u043d \u0441\u043e\u0437\u0434\u0430\u0451\u0442 <strong>TTY<\/strong>-\u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e <code>\/dev\/ttyUL0<\/code>. \u0412\u0445\u043e\u0434\u044f\u0449\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437 <strong>UARTlite<\/strong> \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c workqueue, \u043f\u0435\u0440\u0435\u0434\u0430\u044e\u0442\u0441\u044f \u0432 \u0431\u0443\u0444\u0435\u0440 <strong>TTY<\/strong> \u0438 \u0441\u0442\u0430\u043d\u043e\u0432\u044f\u0442\u0441\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u0447\u0435\u0440\u0435\u0437 \u0444\u0443\u043d\u043a\u0446\u0438\u044e <code>tty_flip_buffer_push<\/code> (\u043e\u043d\u0430 \u0441\u043e\u043e\u0431\u0449\u0430\u0435\u0442 \u044f\u0434\u0440\u0443 Linux, \u0447\u0442\u043e <strong>\u0432 \u043f\u0440\u0438\u0451\u043c\u043d\u043e\u043c \u0431\u0443\u0444\u0435\u0440\u0435<\/strong> \u043f\u043e\u044f\u0432\u0438\u043b\u0438\u0441\u044c \u043d\u043e\u0432\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435, \u0438 \u044d\u0442\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u043d\u0443\u0436\u043d\u043e <strong>\u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u0432 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0435 \u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u043e<\/strong> \u0438 \u0431\u0435\u0437 \u0435\u0451 \u0432\u044b\u0437\u043e\u0432\u0430 \u0434\u0430\u043d\u043d\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u0432\u0438\u0441\u0435\u0442\u044c \u0432\u043d\u0443\u0442\u0440\u0438 \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430 \u0438 <strong>\u043d\u0435 \u0434\u043e\u0439\u0434\u0443\u0442<\/strong> \u0434\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f).<\/p>\n<p><a href=\"https:\/\/docs.kernel.org\/driver-api\/tty\/index.html\" rel=\"noopener noreferrer nofollow\">Linux TTY Documentation<\/a><\/p>\n<h3>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442<\/h3>\n<pre><code class=\"cpp\">#define DRIVER_NAME \"uartlite_xdma\" \/\/ \u0418\u043c\u044f \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430 #define VENDOR_ID 0x10EE  \/\/ Xilinx Vendor ID #define DEVICE_ID 0x7011  \/\/ Device ID \u0434\u043b\u044f FPGA Hard PCIe block #define UARTLITE_BASE_OFFSET 0x40000 \/\/ \u0411\u0430\u0437\u043e\u0432\u044b\u0439 \u0430\u0434\u0440\u0435\u0441 AXI**<\/code><\/pre>\n<ul>\n<li>\n<p><code>VENDOR_ID = 0x10EE<\/code> \u2014 \u044d\u0442\u043e <strong>Xilinx<\/strong> (\u0437\u0430\u0434\u0430\u0435\u0442\u0441\u044f \u0432 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 IP \u044f\u0434\u0440\u0430 \u0432 Vivado, \u043a\u0430\u0436\u0434\u044b\u0439 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c PCIe-\u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432 \u0438\u043c\u0435\u0435\u0442 \u0441\u0432\u043e\u0439 ID).<\/p>\n<\/li>\n<li>\n<p><code>DEVICE_ID = 0x7011<\/code> \u2014 <strong>\u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430<\/strong> (\u0437\u0430\u0434\u0430\u0435\u0442\u0441\u044f \u0432 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 IP \u044f\u0434\u0440\u0430 \u0432 Vivado).<\/p>\n<\/li>\n<li>\n<p><code>UARTLITE_BASE_OFFSET = 0x40000<\/code> \u2014 <strong>\u0441\u043c\u0435\u0449\u0435\u043d\u0438\u0435 \u0432 \u043f\u0430\u043c\u044f\u0442\u0438<\/strong>, \u0433\u0434\u0435 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f UARTlite \u0432 \u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u0435 XDMA (\u0432 \u043c\u043e\u0435\u043c \u043f\u0440\u043c\u0435\u0440\u0435 <code>0x40000<\/code> , \u043e\u0440\u043f\u0435\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u043c \u0432 Vivado)<\/p>\n<\/li>\n<\/ul>\n<h3>\u0410\u0434\u0440\u0435\u0441\u0430 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u043e\u0432 \u0432 \u043f\u0430\u043c\u044f\u0442\u0438:<\/h3>\n<p>\u0412 \u0441\u043e\u043e\u0442\u0432\u0435\u0441\u0442\u0432\u0438\u0438 \u0441 <a href=\"https:\/\/docs.amd.com\/v\/u\/en-US\/pg142-axi-uartlite\" rel=\"noopener noreferrer nofollow\">datashhet AXI UartLite<\/a><\/p>\n<pre><code class=\"cpp\">#define UARTLITE_RX_FIFO  0x00  \/\/ FIFO \u043f\u0440\u0438\u0451\u043c\u0430 #define UARTLITE_TX_FIFO  0x04  \/\/ FIFO \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 #define UARTLITE_STATUS   0x08  \/\/ \u0420\u0435\u0433\u0438\u0441\u0442\u0440 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f #define UARTLITE_CONTROL  0x0C  \/\/ \u0420\u0435\u0433\u0438\u0441\u0442\u0440 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f<\/code><\/pre>\n<ul>\n<li>\n<p><strong>RX_FIFO (0x00)<\/strong> \u2014 \u0447\u0438\u0442\u0430\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0435, \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0435 \u043e\u0442 UART.<\/p>\n<\/li>\n<li>\n<p><strong>TX_FIFO (0x04)<\/strong> \u2014 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438.<\/p>\n<\/li>\n<li>\n<p><strong>STATUS (0x08)<\/strong> \u2014 \u0444\u043b\u0430\u0433\u0438 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f (\u0434\u0430\u043d\u043d\u044b\u0435 \u0435\u0441\u0442\u044c? FIFO \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d?).<\/p>\n<\/li>\n<li>\n<p><strong>CONTROL (0x0C)<\/strong> \u2014 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 UARTlite.<\/p>\n<\/li>\n<\/ul>\n<h3>\u0424\u043b\u0430\u0433\u0438 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f<\/h3>\n<pre><code class=\"cpp\">#define STATUS_RXVALID    BIT(0) \/\/ \u0414\u0430\u043d\u043d\u044b\u0435 \u0435\u0441\u0442\u044c \u0432 RX FIFO #define STATUS_TXFULL     BIT(3) \/\/ TX FIFO \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d<\/code><\/pre>\n<ul>\n<li>\n<p><strong>RXVALID (\u0431\u0438\u0442 0)<\/strong> \u2014 <code>1<\/code>, \u0435\u0441\u043b\u0438 \u0432 RX FIFO \u0435\u0441\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435.<\/p>\n<\/li>\n<li>\n<p><strong>TXFULL (\u0431\u0438\u0442 3)<\/strong> \u2014 <code>1<\/code>, \u0435\u0441\u043b\u0438 TX FIFO \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d.<\/p>\n<\/li>\n<\/ul>\n<h3>\u041e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0434\u0430\u043d\u043d\u044b\u0445<\/h3>\n<pre><code class=\"cpp\">struct uartlite_priv {     void __iomem <\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-456029","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/456029","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=456029"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/456029\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=456029"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=456029"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=456029"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}