Продолжим.
Описываю по шагам ход пробы работы с DMA.
1. Создаю в ISE проект на Zynq XC7Z020 CLG484. Головной файл в schematic. В него добавляю Embedded Processor. Запускается XPS, где я импортирую xml файл тестовой платы HW-Z7-ZC702 (рис.1)
2. Создаем своё ядро с названием my_dma(рис.2), интерфейсом AXI4-Stream(рис.3), оставляем размерность без изменений(рис.4), не генерим лишних файлов(рис.5).
3. Меняем код в VHDL файле ядра на прикрепленный
4. Вставляем наше ядро в процессор (рис.6)
5. Вставляем ядро AXI DMA Engine. Снимаем галку со строки Include Scatter Gather Engine (рис. 7). Все остальные параметры по умолчанию. Окончание настройки - добавляем ядро (рис.8)
6. Подключаем наше ядро к DMA через AXI4-Stream.(рис.9). Модули axi_intercoonect добавились и подключились автоматически.
Настройки не менял
7. Подключаем сигнал ACLK нашего ядра к тому же клоку что используют axi_intercoonect(рис.10)
8. Запускаем Generate Netlist
9. По окончании генерации возвращаемся в ISE. Вставляем символ проца. Подключаем все его выводы. Компилим проект. Создаем bit файл. Импортируем и запускаем SDK
10. В SDK создаем новый Application Project с шаблоном Hello World(рис. 11)
11. Копируем в него прикрепленный код
12. Грузим плис и запускаем проект(рис.12)
13. Получаем неизменное зависание на первой строке запрета прерываний(рис.13)
14. Еще можно перед запуском Generate Netlist открыть mhs файл проекта и в ручную прописать порт ARESETN нашего ядра(рис. 14), ибо не понятно подключился ли он автоматически (рис. 15).
На результат это никак не влияет. Зависание в том же месте.
Вопрос тот же. Что я делаю не так? Где ошибка?
VHDL Код ядра
Код
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity dma_axis is
port
(
-- DO NOT EDIT BELOW THIS LINE ---------------------
-- Bus protocol ports, do not add or delete.
ACLK : in std_logic;
ARESETN : in std_logic;
S_AXIS_TREADY : out std_logic;
S_AXIS_TDATA : in std_logic_vector(31 downto 0);
S_AXIS_TLAST : in std_logic;
S_AXIS_TVALID : in std_logic;
M_AXIS_TVALID : out std_logic;
M_AXIS_TDATA : out std_logic_vector(31 downto 0);
M_AXIS_TLAST : out std_logic;
M_AXIS_TREADY : in std_logic
-- DO NOT EDIT ABOVE THIS LINE ---------------------
);
attribute SIGIS : string;
attribute SIGIS of ACLK : signal is "Clk";
end dma_axis;
architecture EXAMPLE of dma_axis is
-- Total number of input data.
constant NUMBER_OF_INPUT_WORDS : natural := 8;
-- Total number of output data
constant NUMBER_OF_OUTPUT_WORDS : natural := 8;
type STATE_TYPE is (Idle, Read_Inputs, Write_Outputs);
signal state : STATE_TYPE;
-- Accumulator to hold sum of inputs read at any point in time
signal sum : std_logic_vector(31 downto 0);
-- Counters to store the number inputs read & outputs written
signal nr_of_reads : natural range 0 to NUMBER_OF_INPUT_WORDS - 1;
signal nr_of_writes : natural range 0 to NUMBER_OF_OUTPUT_WORDS - 1;
-- TLAST signal
signal tlast : std_logic;
begin
-- CAUTION:
-- The sequence in which data are read in and written out should be
-- consistent with the sequence they are written and read in the
-- driver's axi_stream_generator.c file
-- S_AXIS_TREADY <= '1' when state = Read_Inputs else '0';
S_AXIS_TREADY <= '0' when state = Write_Outputs else '1';
M_AXIS_TVALID <= '1' when state = Write_Outputs else '0';
M_AXIS_TDATA <= sum;
M_AXIS_TLAST <= tlast;
The_SW_accelerator : process (ACLK) is
begin -- process The_SW_accelerator
if ACLK'event and ACLK = '1' then -- Rising clock edge
if ARESETN = '0' then -- Synchronous reset (active low)
-- CAUTION: make sure your reset polarity is consistent with the
-- system reset polarity
state <= Idle;
nr_of_reads <= 0;
nr_of_writes <= 0;
sum <= (others => '0');
tlast <= '0';
else
case state is
when Idle =>
if (S_AXIS_TVALID = '1') then
state <= Read_Inputs;
nr_of_reads <= NUMBER_OF_INPUT_WORDS - 1;
sum <= (others => '0');
end if;
when Read_Inputs =>
if (S_AXIS_TVALID = '1') then
-- Coprocessor function (Adding) happens here
sum <= std_logic_vector(unsigned(sum) + unsigned(S_AXIS_TDATA));
if (S_AXIS_TLAST = '1') then
state <= Write_Outputs;
nr_of_writes <= NUMBER_OF_OUTPUT_WORDS - 1;
else
nr_of_reads <= nr_of_reads - 1;
end if;
end if;
when Write_Outputs =>
if (M_AXIS_TREADY = '1') then
if (nr_of_writes = 0) then
state <= Idle;
tlast <= '0';
else
-- assert TLAST on last transmitted word
if (nr_of_writes = 1) then
tlast <= '1';
end if;
nr_of_writes <= nr_of_writes - 1;
end if;
end if;
end case;
end if;
end if;
end process The_SW_accelerator;
end architecture EXAMPLE;
СИ код прикладного проекта
Код
#include <stdio.h>
#include "platform.h"
#include "xaxidma.h"
#include "xparameters.h"
/*
* Device hardware build related constants.
*/
#define DMA_DEV_ID XPAR_AXIDMA_0_DEVICE_ID
//#define MEM_BASE_ADDR (XPAR_PS7_DDR_0_S_AXI_BASEADDR + 0x1000000)
#define MEM_BASE_ADDR (XPAR_PS7_DDR_0_S_AXI_BASEADDR + 0x10000000)
#define TX_BUFFER_BASE (MEM_BASE_ADDR + 0x00100000)
#define RX_BUFFER_BASE (MEM_BASE_ADDR + 0x00300000)
#define RX_BUFFER_HIGH (MEM_BASE_ADDR + 0x004FFFFF)
#define MAX_PKT_LEN_WORDS 8
#define MAX_PKT_LEN MAX_PKT_LEN_WORDS*4
#define TEST_START_VALUE 0xC
#define NUMBER_OF_TRANSFERS 10
/************************** Function Prototypes ******************************/
int XAxiDma_SimplePollExample(u16 DeviceId);
static int CheckData(void);
/************************** Variable Definitions *****************************/
/*
* Device instance definitions
*/
XAxiDma AxiDma;
int main()
{
int Status;
init_platform();
xil_printf("\r\n--- Entering main() --- \r\n");
/* Run the poll example for simple transfer */
Status = XAxiDma_SimplePollExample(DMA_DEV_ID);
if (Status != XST_SUCCESS) {
xil_printf("XAxiDma_SimplePollExample: Failed\r\n");
return XST_FAILURE;
}
xil_printf("XAxiDma_SimplePollExample: Passed\r\n");
xil_printf("--- Exiting main() --- \r\n");
return XST_SUCCESS;
}
/*****************************************************************************/
/**
* The example to do the simple transfer through polling. The constant
* NUMBER_OF_TRANSFERS defines how many times a simple transfer is repeated.
*
* @param DeviceId is the Device Id of the XAxiDma instance
*
* @return
* - XST_SUCCESS if example finishes successfully
* - XST_FAILURE if error occurs
*
* @note None
*
*
******************************************************************************/
int XAxiDma_SimplePollExample(u16 DeviceId)
{
XAxiDma_Config *CfgPtr;
int Status;
int Tries = NUMBER_OF_TRANSFERS;
int Index;
u32 *TxBufferPtr;
u32 *RxBufferPtr;
u32 Value;
TxBufferPtr = (u32 *)TX_BUFFER_BASE;
RxBufferPtr = (u32 *)RX_BUFFER_BASE;
/* Initialize the XAxiDma device.
*/
CfgPtr = XAxiDma_LookupConfig(DeviceId);
if (!CfgPtr) {
xil_printf("No config found for %d\r\n", DeviceId);
return XST_FAILURE;
}
Status = XAxiDma_CfgInitialize(&AxiDma, CfgPtr);
if (Status != XST_SUCCESS) {
xil_printf("Initialization failed %d\r\n", Status);
return XST_FAILURE;
}
if(XAxiDma_HasSg(&AxiDma)){
xil_printf("Device configured as SG mode \r\n");
return XST_FAILURE;
}
xil_printf("1");
/* Disable interrupts, we use polling mode
*/
XAxiDma_IntrDisable(&AxiDma, XAXIDMA_IRQ_ALL_MASK,
XAXIDMA_DEVICE_TO_DMA);
xil_printf("2");
XAxiDma_IntrDisable(&AxiDma, XAXIDMA_IRQ_ALL_MASK,
XAXIDMA_DMA_TO_DEVICE);
Value = 0;
for(Index = 0; Index < MAX_PKT_LEN_WORDS; Index ++) {
TxBufferPtr[Index] = Value;
Value++;
}
/* Flush the SrcBuffer before the DMA transfer, in case the Data Cache
* is enabled
*/
Xil_DCacheFlushRange((u32)TxBufferPtr, MAX_PKT_LEN);
for(Index = 0; Index < Tries; Index ++) {
Status = XAxiDma_SimpleTransfer(&AxiDma,(u32) RxBufferPtr,
MAX_PKT_LEN, XAXIDMA_DEVICE_TO_DMA);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
Status = XAxiDma_SimpleTransfer(&AxiDma,(u32) TxBufferPtr,
MAX_PKT_LEN, XAXIDMA_DMA_TO_DEVICE);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
while (XAxiDma_Busy(&AxiDma,XAXIDMA_DMA_TO_DEVICE)) {
/* Wait */
}
while (XAxiDma_Busy(&AxiDma,XAXIDMA_DEVICE_TO_DMA)) {
/* Wait */
}
Status = CheckData();
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
}
/* Test finishes successfully
*/
return XST_SUCCESS;
}
/*****************************************************************************/
/*
*
* This function checks data buffer after the DMA transfer is finished.
*
* @param None
*
* @return
* - XST_SUCCESS if validation is successful.
* - XST_FAILURE otherwise.
*
* @note None.
*
******************************************************************************/
static int CheckData(void)
{
u32 *RxPacket;
int Index = 0;
RxPacket = (u32 *) RX_BUFFER_BASE;
/* Invalidate the DestBuffer before receiving the data, in case the
* Data Cache is enabled
*/
Xil_DCacheInvalidateRange((u32)RxPacket, MAX_PKT_LEN);
xil_printf("Data received: ");
for(Index = 0; Index < MAX_PKT_LEN_WORDS; Index++) {
xil_printf("0x%X ", (unsigned int)RxPacket[Index]);
}
xil_printf("\r\n");
return XST_SUCCESS;
}