📄 main.c
字号:
uchar index;
// If this is data coming in (not a new command) ...
if (rcvReport.u.cmd == 0)
{
// Process the incoming data based on the current command
switch (currentCmd.u.cmd)
{
case CMD_WRITE:
// Skip over command byte in first packet
if (rcvIndex == 0)
{
if (cbReceived <= 1)
{
// Error
return;
}
cbData = min(currentCmd.u.rw.nBytes, cbReceived - 1);
index = rcvIndex + 1;
}
else
{
cbData = min(currentCmd.u.rw.nBytes, cbReceived);
index = rcvIndex;
}
WriteBufferToFlash(
currentCmd.u.rw.flash,
currentCmd.u.rw.address,
rcvReport.u.buffer + index,
cbData);
currentCmd.u.rw.address += cbData;
currentCmd.u.rw.nBytes -= cbData;
if (currentCmd.u.rw.nBytes == 0)
{
// All done
currentCmd.u.cmd = 0;
if (currentCmd.u.rw.flash == PRIMARY_FLASH)
{
flash_reset();
}
else
{
flash_boot_reset();
}
}
break;
default:
break;
}
}
}
/////////////////// OnReportReceived()
//
// Called after all segments of a report have been received.
static void OnReportReceived()
{
// If this is a new command coming in ...
if (rcvReport.u.cmd)
{
if (rcvReport.u.cmd == CMD_STATUS)
{
// For CMD_GET_STATUS, don't overwrite current cmd we're working on
returnStatus = TRUE;
}
else
{
// Copy into 'current command' global variable
memcpy(currentCmd.u.buffer, rcvReport.u.buffer, sizeof(rcvReport));
memset((uchar*)&status, 0, sizeof(status));
g_debug1 = currentCmd.u.cmd;
}
// Some commands are processed at this point
switch (rcvReport.u.cmd)
{
case CMD_RESET:
WDKEY=0; // watchdog will trigger reset in a second
currentCmd.u.cmd = 0;
break;
case CMD_SET_PAGE:
UPSD_xreg.PAGE = rcvReport.u.setRegs.page;
currentCmd.u.cmd = 0;
break;
case CMD_SET_VM:
UPSD_xreg.VM = rcvReport.u.setRegs.vm;
currentCmd.u.cmd = 0;
break;
case CMD_SET_REGS:
UPSD_xreg.PAGE = rcvReport.u.setRegs.page;
UPSD_xreg.VM = rcvReport.u.setRegs.vm;
currentCmd.u.cmd = 0;
break;
default:
// Prepare first segment of any response to go back to host
PrepareTransmitSegment(0);
break;
}
}
}
/////////////////// OnReportTransmitted()
//
// A complete feature report has been successfully transmitted.
static void OnReportTransmitted()
{
if (returnStatus)
{
returnStatus = FALSE;
}
// If there's more data to go ...
if (currentCmd.u.cmd)
{
// Prepare first segment of next report
PrepareTransmitSegment(0);
}
}
/////////////////// HandleReport()
//
// Handles HID Get_Report and Set_Report SETUP packets.
//
// Returns TRUE if the SETUP packet is a Get_Report or Set_Report
// request; else returns FALSE.
static BOOL HandleReport()
{
// If it is a HID Set_Report request...
if ((setupPacket.bmRequestType == CLASS_INTERFACE_TO_DEVICE)
&& (setupPacket.bRequest == HID_SET_REPORT))
{
// Prepare to receive report
rcvIndex = 0;
return TRUE;
}
// Else if it is a HID Get_Report request ...
else if ((setupPacket.bmRequestType == CLASS_INTERFACE_TO_HOST)
&& (setupPacket.bRequest == HID_GET_REPORT))
{
// Transmit first segment of response (should be already prepared)
UCON0 &= ~uTSEQ0;
TransmitDataEP0(txReport.u.buffer, EP0_SIZE);
// Prepare next segment while first one is going out
txIndex = EP0_SIZE;
PrepareTransmitSegment(txIndex);
return TRUE;
}
return FALSE;
}
/////////////////// UsbIsr()
//
// USB interrupt service routine.
static void UsbIsr() interrupt USB_VECTOR
{
uchar cb;
uchar i;
volatile uchar x;
BOOL ret;
// If data successfully transmitted on EP0 IN ...
if (UISTA & uTXD0F)
{
// Reset transmit FIFO and clear transmit enable bit
UCON0 |= (uRX0E | uTX0E | 8);
UCON0 &= ~uTX0E;
// If in the middle of transmitting a report ...
if (txIndex < FEATURE_REPORT_SIZE)
{
// Transmit next segment of outgoing report
cb = min(FEATURE_REPORT_SIZE - txIndex, EP0_SIZE);
TransmitDataEP0(txReport.u.buffer + txIndex, cb);
// Clear the interrupt and let the packet go out
UISTA &= ~uTXD0F;
if ((txIndex += cb) >= FEATURE_REPORT_SIZE)
{
OnReportTransmitted();
}
else
{
// Prepare the next segment while that last one is going out
PrepareTransmitSegment(txIndex);
}
}
else
{
// Handle standard control requests
BaseEp0TxHandler();
// Clear the interrupt
UISTA &= ~uTXD0F;
}
}
// If data received on EP0 OUT ...
if (UISTA & uRXD0F)
{
// If it's a SETUP packet ...
if (USTA & uSETUP)
{
// Read the SETUP packet
ret = ReadSetupPacket();
// Clear interrupt so next packet can come in now
UISTA &= ~uRXD0F;
if (ret)
{
// If this is not a HID report ...
if (!HandleReport())
{
// ... pass it on to the basic SETUP packet handler
OnSetupPacket();
}
}
}
else
{
// If in the middle of receiving a report ...
if ((USTA & 0x0F) && (rcvIndex < OUTPUT_REPORT_SIZE))
{
// Read the next segment
cb = USTA & 0x0F;
for (i = 0; i < cb; i++)
{
rcvReport.u.buffer[rcvIndex + i] = UDR0;
}
// Toggle data toggle bit
USTA ^= uRSEQ;
// Next packet can come in now
UISTA &= ~uRXD0F;
// Handle report as it comes in and/or when all done
OnReportSegmentReceived(cb);
if ((rcvIndex += cb) >= OUTPUT_REPORT_SIZE)
{
OnReportReceived();
// Transmit 0 length ack packet
UCON0 = uTSEQ0 | uRX0E | uTX0E;
}
}
else
{
// Toggle data toggle bit
USTA ^= uRSEQ;
// Next packet can come in now
UISTA &= ~uRXD0F;
}
}
}
// If data transmitted on EP1 ...
if (UISTA & uTXD1F)
{
// Load up next input report with LCD display data
OnTransmitEP1();
// Clear the interrupt
UISTA &= ~uTXD1F;
}
// If there is a resume bus condition ...
if (UISTA & uRESUMEF)
{
// Handle bus activity while in suspended state
UISTA &= ~uRESUMEF;
}
// Handle suspend interrupt
if (UISTA & uSUSPENDF)
{
UISTA &= ~uSUSPENDF;
// Delay (from Hynix code)
for (i = 10; i; i--)
{
x = i;
}
UCON1 |= uFRESUM;
// Delay (from Hynix code)
for (i = 6; i; i--)
{
x = i;
}
UCON1 &= ~uFRESUM;
}
// Handle USB bus reset
if (UISTA & uRSTF)
{
UISTA &= ~uRSTF;
UsbInitialize();
}
// Just clear EOP interrupts
UISTA &= ~(uEOPF);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -