📄 usb_new_uc_handler_rtl.vhdl
字号:
for i in 0 to (N_ENDPOINTS-1) loop
if EndpointInfo(ConfigNr)(i).EndpointType /= ISOCHRONOUS then
UCToggle(i) := 0;
USBToggle(i) := 0;
end if;
end loop;
Stall := (others => FALSE);
Setup := (others => FALSE);
Naked := (others => FALSE);
Overwritten := (others => FALSE);
Disable := (others => FALSE);
RateFeedback := (others => FALSE);
Full:= (others => (others => FALSE));
Sie_Write <= '0';
Sie_Read_i <= '0';
start_in_transfer <= '0';
elsif (FsClk'event and FsClk = '1') then
-- rama
-- Doublebuffered endpoints are allways toggled on the frameclock
for i in 0 to (N_ENDPOINTS-1) loop
if EndpointInfo(ConfigNr)(i).EndpointType = ISOCHRONOUS then
UCToggle(i) := TM_IsoToggle;
USBToggle(i) := 1 - TM_IsoToggle;
end if;
end loop;
-- Send bufferinfo to PI_Handler
EPBufferInfo.UCToggle <= UCToggle;
EPBufferInfo.USBToggle <= USBToggle;
EPBufferInfo.Full <= Full;
Selected_int := Selected;
ConfigNr := GetConfiguration(ConfigArray);
-- DOC_BEGIN: Device Address Table
-- Bit 7 in the Device Address Table
-- indicates whether a function is active (1) or not (0).
-- Rows with addresses 0 to 7 are contained in DevAddrTable()().
-- The row with address equal to 8 is the EndpointEnables register.
-- Each device has its own bit. If the bit is set, all endpoints
-- of that device are enabled. If the bit is reset, only the default
-- endpoint is enabled. (USB Control Endpoint 0)
-- __________________________________________________________________
-- |Addr.| bit 7 | bit 6| bit 5| bit 4| bit 3| bit 2| bit 1| bit 0|
-- |__________________________________________________________________|
-- | 0 | F0 enable | Function 0 Address |
-- | 1 | F1 enable | Function 1 Address |
-- | 2 | F2 enable | Function 2 Address |
-- | 3 | F3 enable | Function 3 Address |
-- | 4 | F4 enable | Function 4 Address |
-- | 5 | F5 enable | Function 5 Address |
-- | 6 | F6 enable | Function 6 Address |
-- | 7 | F7 enable | Function 7 Address |
-- |__________________________________________________________________|
-- | 8 | F7 En. |F6 En.|F5 En.|F4 En.|F3 En.|F2 En.|F1 En.|F0 En.|
-- |__________________________________________________________________|
-- DOC_END
if (EndpointInfo(ConfigNr)
(DataToHandlers.Endpoint).EndpointType = BULK_OR_INTERRUPT and
EndpointInfo(ConfigNr)
(DataToHandlers.Endpoint).USBDirection = DIR_IN) then
IntMode <= RateFeedback(DataToHandlers.Endpoint);
else
IntMode <= FALSE;
end if;
if EndpointInfo(ConfigNr)(DataToHandlers.Endpoint).EndpointType =
ISOCHRONOUS then
PID <= 0;
Stalled <= FALSE;
else
PID <= DataPID(DataToHandlers.Endpoint);
Stalled <= Stall(DataToHandlers.Endpoint);
end if;
if EndpointInfo(ConfigNr)(DataToHandlers.Endpoint).EndpointType /=
CONTROL then
Disabled <= Disable(DataToHandlers.Endpoint);
else
Disabled <= FALSE;
end if;
-- default assignments
NeedClock <= FALSE;
-- DOC_BEGIN: uC Commands processing
-- GIF clears or validates buffers:
-- (note: if this is also implemented for other endpoints: take care of
-- command_disabled)
--if (ValidateEP1 = '1') then
-- if not overwritten(0)then
-- Full(1)(0) := TRUE;
-- end if;
--end if;
--if (ValidateEP3 = '1') then
-- Full(3)(0) := TRUE;
--end if;
--if (ValidateEP5 = '1') then
-- Full(5)(0) := TRUE;
--end if;
--if (ClearEP6 = '1') then
-- if EndpointInfo(ConfigNr)(6).N_Buffers > 1 then
-- Full(6)(UCToggle(6)) := FALSE;
-- UCToggle(6) := 1-UCToggle(6);
-- else
-- Full(6)(0) := FALSE;
-- end if;
--end if;
--if (ValidateEP7 = '1') then
-- if EndpointInfo(ConfigNr)(7).N_Buffers > 1 then
-- Full(7)(UCToggle(7)) := TRUE;
-- UCToggle(7) := 1-UCToggle(7);
-- else
-- Full(7)(0) := TRUE;
-- end if;
-- end if;
-- if (ClearEP8 = '1') then
-- if EndpointInfo(ConfigNr)(8).N_Buffers > 1 then
-- Full(8)(UCToggle(8)) := FALSE;
-- else
-- Full(8)(0) := FALSE;
-- end if;
-- end if;
-- if (ValidateEP9 = '1') then
-- if EndpointInfo(ConfigNr)(9).N_Buffers > 1 then
-- Full(9)(UCToggle(9)) := TRUE;
-- else
-- Full(9)(0) := TRUE;
-- end if;
-- end if;
-- External controller writes a command :
if (DataFromUC.Write and DataFromUC.Address = 1) then
NeedClock <= TRUE;
-- Split input DataFromUC.Data in Command and argument
DecodeCommand(DataFromUC.Data, Command, CmdArgument, Selected_int);
DataToUC.Ready <= FALSE;
case command is
-- The Select Endpoint command initializes an internal
-- pointer to the start of the Selected buffer.
-- It also returns a byte with bit 2 indicating that the
-- packet in the buffer was preceeded by a Setup token,
-- bit 1 indicates a stall state and bit 0 indicates if
-- the buffer is full.
when SELECT_EP | SET_EP_STATUS =>
-- in case of SET_EP_STATUS, the selecting of the
-- of the endpoint and the resetting of the buffer are
-- done when reading a byte
if command = SELECT_EP then
EndpointNr := CmdArgument;
end if;
EndpointNr_tmp := CmdArgument;
DataToUC.Data <= "00000000";
if EndpointInfo(ConfigNr)(CmdArgument).N_Buffers > 1 then
DataToUC.Data(SEL_FULL) <=
conv_active_high(Full(CmdArgument)(UCToggle(CmdArgument)));
else
DataToUC.Data(SEL_FULL) <= conv_active_high(Full(CmdArgument)(0));
end if;
if EndpointInfo(ConfigNr)(EndpointNr_tmp).EndpointType /= CONTROL or
EndpointInfo(ConfigNr)(EndpointNr_tmp).USBDirection /= DIR_OUT then
DataToUC.Data(SEL_SETUP) <= '0';
DataToUC.data(SEL_OVERWRITTEN) <= '0';
else
DataToUC.Data(SEL_SETUP) <= conv_active_high(Setup(EndpointNr_tmp));
DataToUC.Data(SEL_OVERWRITTEN) <=
conv_active_high(Overwritten(EndpointNr_tmp));
end if;
if EndpointInfo(ConfigNr)(EndpointNr_tmp).EndpointType /= CONTROL then
DataToUC.Data(SEL_NAKED) <= '0';
elsif EndpointInfo(ConfigNr)(EndpointNr_tmp).EndpointType = CONTROL then
DataToUC.Data(SEL_NAKED) <= conv_active_high(Naked(EndpointNr_tmp));
end if;
if EndpointInfo(ConfigNr)(EndpointNr_tmp).EndpointType =
ISOCHRONOUS then
DataToUC.Data(SEL_STALL) <= '0';
else
DataToUC.Data(SEL_STALL) <= conv_active_high(Stall(EndpointNr_tmp));
end if;
-- The following command implements both the 'Clear Buffer' and
-- the 'Validate Buffer' commands of the uC. It controls
-- the Buffer Full bit in the endpoint status register.
-- CmdArgument = 1 sets the Buffer Full bit.
-- CmdArgument = 0 resets the Buffer Full bit.
when SET_BUFFER_FE =>
if CmdArgument = 0 then
DataToUC.Data <= "00000000";
if EndpointInfo(ConfigNr)(EndpointNr).EndpointType /= CONTROL or
EndpointInfo(ConfigNr)(EndpointNr).USBDirection /= DIR_OUT then
DataToUC.data(CLB_OVERWRITTEN) <= '0';
else
DataToUC.Data(CLB_OVERWRITTEN) <=
conv_active_high(Overwritten(EndpointNr));
end if;
-- UCClearBuffer
CommandDisabled := FALSE;
if EndpointInfo(ConfigNr)(EndpointNr).EndpointType = CONTROL then
CorrespEP := EndpointInfo(ConfigNr)(EndpointNr).CorrespondingEP;
if EndpointInfo(ConfigNr)(EndpointNr).USBDirection =DIR_OUT then
CommandDisabled := Overwritten(EndpointNr);
else
CommandDisabled := Overwritten(CorrespEP);
end if;
end if;
if not CommandDisabled then
if EndpointInfo(ConfigNr)(EndpointNr).N_Buffers > 1 then
Full(EndpointNr)(UCToggle(EndpointNr)) := FALSE;
if EndpointInfo(ConfigNr)(EndpointNr).EndpointType /= ISOCHRONOUS then
UCToggle(EndpointNr) := 1-UCToggle(EndpointNr);
end if;
else
Full(EndpointNr)(0) := FALSE;
end if;
end if;
-- end UCClearBuffer
if IsFull(EndpointNr, UCToggle, Full, ConfigNr) then
DataToSIE.Interrupts(EndpointNr) <= TRUE;
end if;
else
-- UCValidateBuffer
CommandDisabled := FALSE;
if EndpointInfo(ConfigNr)(EndpointNr).EndpointType = CONTROL then
CorrespEP := EndpointInfo(ConfigNr)(EndpointNr).CorrespondingEP;
if EndpointInfo(ConfigNr)(EndpointNr).USBDirection = DIR_OUT then
CommandDisabled := Overwritten(EndpointNr);
else
CommandDisabled := Overwritten(CorrespEP);
end if;
end if;
if not CommandDisabled then
if EndpointInfo(ConfigNr)(EndpointNr).N_Buffers > 1 then
Full(EndpointNr)(UCToggle(EndpointNr)) := TRUE;
if EndpointInfo(ConfigNr)(EndpointNr).EndpointType /= ISOCHRONOUS then
UCToggle(EndpointNr) := 1-UCToggle(EndpointNr);
end if;
else
Full(EndpointNr)(0) := TRUE;
end if;
end if;
-- end UCValidateBuffer
end if;
-- The command Read data reads data from the Endpoint Data Buffer
-- Each read pulse, the data is red from the buffer.
-- The pointer is incremented to the next position in the
-- buffer.
-- The first byte in the buffer is the most significant byte of
-- the number of bytes in the buffer. Only bits 1 and 0 are used
-- for the number of bytes. Bit 7 in this byte indicates that
-- the last transaction was successfull.
-- Bit 6 indicates that it was a setup packet.
-- This byte is cleared when it has been sent to the the external
-- controller.
when SET_ADDRESS | SET_EP_ENABLE =>
null;
-- Invalid States
when others =>
DataToUC.Ready <= TRUE;
end case;
-- External controller writes data
elsif (DataFromUC.Write and Selected_int)then
Data := DataFromUC.Data;
NeedClock <= TRUE;
DataToUC.Ready <= FALSE;
case command is
-- The Set Address command sets the address and the enable bit
-- of a function
when SET_ADDRESS =>
Data := DataFromUC.Data;
DevAddrTable(CmdArgument)(7) <= Data(7);
if loaded(CmdArgument) then
DevAddrTable(CmdArgument) <= Data;
Loaded(CmdArgument) := FALSE;
else
DevAddrTable_tmp(CmdArgument):= Data(6 downto 0);
Loaded(CmdArgument) := TRUE;
end if;
-- Enables/disables endpoints
when SET_EP_ENABLE =>
EndpointEnables <= Data(N_HANDLER_DEVICES(ID)-1 downto 0);
-- The command Set Endpoint Status followed by writing one byte
-- will stall or unstall the selected endpoint, set or reset the
-- DataPID, mark the buffer full or empty, indicate if the buffer
-- contains a setup packet and set the status of the buffer to
-- overwritten or not.
-- Writing 01h will stall the endpoint, writing 00h will unstall
-- the endpoint. Stalling the endpoint will also reset the
-- endpoint status.
when SET_EP_STATUS =>
-- InitializeEndpoint
CommandDisabled := FALSE;
if EndpointInfo(ConfigNr)(CmdArgument).EndpointType = CONTROL then
CorrespEP := EndpointInfo(ConfigNr)(CmdArgument).CorrespondingEP;
if EndpointInfo(ConfigNr)(CmdArgument).USBDirection = DIR_OUT then
CommandDisabled := Overwritten(CmdArgument);
if conv_active_high(DataFromUC.Data(C_CONDSTALL))
and (Setup(CmdArgument) = TRUE) then
CommandDisabled := TRUE;
end if;
else
CommandDisabled := Overwritten(CorrespEP);
end if;
end if;
if not CommandDisabled THEN
-- only clear buffers etc when unstalling
IF DataFromUC.Data(C_STALL)='0' THEN
if (EndpointInfo(ConfigNr)(CmdArgument).N_Buffers > 1) then
Full(CmdArgument) :=
(others => FALSE);
UCToggle(CmdArgument) := 0;
USBToggle(CmdArgument) := 0;
else
Full(CmdArgument)(0) := FALSE;
end if;
END IF;
if EndpointInfo(ConfigNr)(CmdArgument).EndpointType /=
ISOCHRONOUS then
Stall(CmdArgument) := conv_active_high(DataFromUC.Data(C_STALL));
DataPID(CmdArgument) := 0;
end if;
if EndpointInfo(ConfigNr)(CmdArgument).EndpointType = CONTROL
and EndpointInfo(ConfigNr)(CmdArgument).USBDirection =
DIR_OUT then
if conv_active_high(DataFromUC.Data(C_CONDSTALL)) then
CorrespEP := EndpointInfo(ConfigNr)(CmdArgument).CorrespondingEP;
Stall(CmdArgument) := TRUE;
Stall(CorrespEP) := TRUE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -