📄 main_lpcusbboot.c
字号:
/*
LPC ISP protocol on a Serial Interface implemented on USB CDC class.
This file is rewrited from main_serial.c
*/
#include <string.h> // memcpy
#include "type.h"
#include "usbdebug.h"
#include "iap.h"
#include "console.h"
#include "usbapi.h"
#include "startup.h"
#include "serial_fifo.h"
#include "lpcisp.h"
#include "uu_codec.h"
#ifdef DEBUG
#define DBG_LEVEL 2
#else
#define DBG_LEVEL 0
#endif
// Chip related
#define LPCARM_MaxSect 26
#define LPCARM_MemTop 0x40008000
#define LPCARM_FlashSize (512 * 1024)
// Bootloader related
#define Boot_Position_TOP 0 // bootloader located in the top of Flash(from 0x00000000)
#define Boot_Position_BOTTOM 1 // bootloader located in the bottom of Flash
#define Boot_Position Boot_Position_TOP
#define Boot_Sect_Begin 0
#define Boot_Sect_Num 4
#define BOOT_START 0x00000000
#define APP_START 0x00004000
#define BAUD_RATE 115200
#define INT_IN_EP 0x81
#define BULK_OUT_EP 0x02
#define BULK_IN_EP 0x82
#define MAX_PACKET_SIZE MAX_PACKET_SIZE0
#define CMD_LINE_LEN MAX_PACKET_SIZE0
#define LE_WORD(x) ((x)&0xFF),((x)>>8)
// CDC definitions
#define CS_INTERFACE 0x24
#define CS_ENDPOINT 0x25
#define SET_LINE_CODING 0x20
#define GET_LINE_CODING 0x21
#define SET_CONTROL_LINE_STATE 0x22
#define LPCARM_Unlock_Code 0x5A5A
// Boot Sector, MUST be protected
#define Boot_Sect_End (Boot_Sect_Begin + Boot_Sect_Num - 1)
#if Boot_Position == Boot_Position_TOP
# define APP_END LPCARM_FlashSize
# undef Boot_Sect_Begin
# define Boot_Sect_Begin 0
#elif Boot_Position == Boot_Position_BOTTOM
# define APP_END BOOT_START
#else
#error "Boot_Position MUST be either Boot_Position_TOP or Boot_Position_BOTTOM"
#endif
// check
#if Boot_Sect_Num < 1
#error "Please give me some Flash for the Bootloader"
#endif
#if (Boot_Sect_End > LPCARM_MaxSect) || (APP_START >= LPCARM_FlashSize)
#error "R U kidding?"
#endif
// data structure for GET_LINE_CODING / SET_LINE_CODING class requests
typedef struct {
U32 dwDTERate;
U8 bCharFormat;
U8 bParityType;
U8 bDataBits;
} TLineCoding;
static TLineCoding LineCoding = {115200, 0, 0, 8};
static U8 abBulkBuf[MAX_PACKET_SIZE];
static U8 abClassReqData[8];
static U8 txdata[VCOM_FIFO_SIZE];
static U8 rxdata[VCOM_FIFO_SIZE];
static fifo_t txfifo;
static fifo_t rxfifo;
#define Sync_Mode_WaitSync 0
#define Sync_Mode_SendSync 1
#define Sync_Mode_WaitOSC 2
#define Sync_Mode_ReadOSC 3
#define Sync_Mode_Synced 4
static int Sync_Mode;
static int bUnlocked;
static int bChipEncrypted;
static int CDC_enable_echo = 0;
static const U8 abDescriptors[] = {
// device descriptor
0x12,
DESC_DEVICE,
LE_WORD(0x0101), // bcdUSB
0x02, // bDeviceClass
0x00, // bDeviceSubClass
0x00, // bDeviceProtocol
MAX_PACKET_SIZE0, // bMaxPacketSize
LE_WORD(0xFFFF), // idVendor
LE_WORD(0x0005), // idProduct
LE_WORD(0x0100), // bcdDevice
0x01, // iManufacturer
0x02, // iProduct
0x03, // iSerialNumber
0x01, // bNumConfigurations
// configuration descriptor
0x09,
DESC_CONFIGURATION,
LE_WORD(67), // wTotalLength
0x02, // bNumInterfaces
0x01, // bConfigurationValue
0x00, // iConfiguration
0xC0, // bmAttributes
0x32, // bMaxPower
// control class interface
0x09,
DESC_INTERFACE,
0x00, // bInterfaceNumber
0x00, // bAlternateSetting
0x01, // bNumEndPoints
0x02, // bInterfaceClass
0x02, // bInterfaceSubClass
0x01, // bInterfaceProtocol, linux requires value of 1 for the cdc_acm module
0x00, // iInterface
// header functional descriptor
0x05,
CS_INTERFACE,
0x00,
LE_WORD(0x0110),
// call management functional descriptor
0x05,
CS_INTERFACE,
0x01,
0x01, // bmCapabilities = device handles call management
0x01, // bDataInterface
// ACM functional descriptor
0x04,
CS_INTERFACE,
0x02,
0x02, // bmCapabilities
// union functional descriptor
0x05,
CS_INTERFACE,
0x06,
0x00, // bMasterInterface
0x01, // bSlaveInterface0
// notification EP
0x07,
DESC_ENDPOINT,
INT_IN_EP, // bEndpointAddress
0x03, // bmAttributes = intr
LE_WORD(8), // wMaxPacketSize
0x0A, // bInterval
// data class interface descriptor
0x09,
DESC_INTERFACE,
0x01, // bInterfaceNumber
0x00, // bAlternateSetting
0x02, // bNumEndPoints
0x0A, // bInterfaceClass = data
0x00, // bInterfaceSubClass
0x00, // bInterfaceProtocol
0x00, // iInterface
// data EP OUT
0x07,
DESC_ENDPOINT,
BULK_OUT_EP, // bEndpointAddress
0x02, // bmAttributes = bulk
LE_WORD(MAX_PACKET_SIZE), // wMaxPacketSize
0x00, // bInterval
// data EP in
0x07,
DESC_ENDPOINT,
BULK_IN_EP, // bEndpointAddress
0x02, // bmAttributes = bulk
LE_WORD(MAX_PACKET_SIZE), // wMaxPacketSize
0x00, // bInterval
// string descriptors
0x04,
DESC_STRING,
LE_WORD(0x0409),
0x0E,
DESC_STRING,
'L', 0, 'P', 0, 'C', 0, 'U', 0, 'S', 0, 'B', 0,
0x14,
DESC_STRING,
'U', 0, 'S', 0, 'B', 0, 'S', 0, 'e', 0, 'r', 0, 'i', 0, 'a', 0, 'l', 0,
0x12,
DESC_STRING,
'D', 0, 'E', 0, 'A', 0, 'D', 0, 'C', 0, '0', 0, 'D', 0, 'E', 0,
// terminating zero
0
};
/**
Local function to handle bulk data
@param [in] bEP
@param [in] bEPStatus
*/
static void BulkIO(U8 bEP, U8 bEPStatus)
{
int i, iLen;
bEPStatus = bEPStatus;
if(bEP & 0x80)
{
// Bulk IN
if (fifo_avail(&txfifo) == 0) {
// no more data, disable further NAK interrupts until next USB frame
USBHwNakIntEnable(0);
return;
}
// get bytes from transmit FIFO into intermediate buffer
for (i = 0; i < MAX_PACKET_SIZE; i++) {
if (!fifo_get(&txfifo, &abBulkBuf[i])) {
break;
}
}
iLen = i;
// send over USB
if (iLen > 0) {
USBHwEPWrite(bEP, abBulkBuf, iLen);
}
}
else
{
// Bulk OUT
if (fifo_free(&rxfifo) < MAX_PACKET_SIZE) {
// may not fit into fifo
return;
}
// get data from USB into intermediate buffer
iLen = USBHwEPRead(bEP, abBulkBuf, sizeof(abBulkBuf));
for (i = 0; i < iLen; i++) {
// put into FIFO
if (!fifo_put(&rxfifo, abBulkBuf[i])) {
// overflow... :(
ASSERT(FALSE);
break;
}
}
}
}
/**
Local function to handle the USB-CDC class requests
@param [in] pSetup
@param [out] piLen
@param [out] ppbData
*/
static BOOL HandleClassRequest(TSetupPacket *pSetup, int *piLen, U8 **ppbData)
{
switch (pSetup->bRequest) {
// set line coding
case SET_LINE_CODING:
#if DBG_LEVEL >= 3
DBG("SET_LINE_CODING\n");
#endif
memcpy((U8 *)&LineCoding, *ppbData, 7);
*piLen = 7;
#if DBG_LEVEL >= 3
DBG("dwDTERate=%u, bCharFormat=%u, bParityType=%u, bDataBits=%u\n",
LineCoding.dwDTERate,
LineCoding.bCharFormat,
LineCoding.bParityType,
LineCoding.bDataBits);
#endif
Sync_Mode = Sync_Mode_WaitSync;
CDC_enable_echo = 0;
break;
// get line coding
case GET_LINE_CODING:
#if DBG_LEVEL >= 3
DBG("GET_LINE_CODING\n");
#endif
*ppbData = (U8 *)&LineCoding;
*piLen = 7;
break;
// set control line state
case SET_CONTROL_LINE_STATE:
// bit0 = DTR, bit = RTS
#if DBG_LEVEL >= 3
DBG("SET_CONTROL_LINE_STATE %X\n", pSetup->wValue);
#endif
break;
default:
return FALSE;
}
return TRUE;
}
/**
Initialises the VCOM port.
Call this function before using VCOM_putchar or VCOM_getchar
*/
void VCOM_init(void)
{
fifo_init(&txfifo, txdata);
fifo_init(&rxfifo, rxdata);
}
/**
Writes one character to VCOM port
@param [in] c character to write
@returns character written
*/
void VCOM_putchar(int c)
{
while(!fifo_put(&txfifo, c))
USBHwISR();
#if DBG_LEVEL >= 3
DBG("putchar: 0x%02X\n", c);
#endif
}
/**
Writes one string to VCOM port
@param [in] s string to write
*/
void VCOM_putstr(char *s)
{
while(*s)
VCOM_putchar(*s++);
}
/**
Writes one line to VCOM port
@param [in] s string to write
*/
void VCOM_putln(char *s)
{
#if DBG_LEVEL >= 2
DBG("putln: %s\n", s);
#endif
VCOM_putstr(s);
VCOM_putstr("\r\n");
}
/**
Reads one character from VCOM port
@returns character read
*/
int VCOM_getchar(void)
{
U8 c;
while (!fifo_get(&rxfifo, &c))
USBHwISR();
#if DBG_LEVEL >= 3
DBG("getchar: 0x%02X\n", c);
#endif
if (CDC_enable_echo)
VCOM_putchar(c);
return c;
}
/**
Reads one line from VCOM port
@param [in] s buff to store data
@param [in] iLen max length of data
@returns length of string(\r\n is not included)
*/
int VCOM_getln(char *s, int iLen)
{
int idx = 0;
while ((*(s + idx) = VCOM_getchar()) != '\r') {
if(Sync_Mode == Sync_Mode_WaitSync) {
if (*(s + idx) == '?')
Sync_Mode = Sync_Mode_SendSync;
return 0;
}
if (*(s + idx) == 0x1B) {
idx = 0;
#if DBG_LEVEL >= 2
DBG("Aborted\n");
#endif
continue;
}
if (idx < (iLen - 1))
idx++;
else
return 0;
}
if (VCOM_getchar() != '\n') {
return 0;
}
*(s + idx) = 0;
#if DBG_LEVEL >= 2
DBG("getln: %s\n", s);
#endif
return idx;
}
static void USBFrameHandler(U16 wFrame)
{
wFrame = wFrame;
if (fifo_avail(&txfifo) > 0) {
// data available, enable NAK interrupt on bulk in
USBHwNakIntEnable(INACK_BI);
}
}
static int getNum(const char *s, U32 *num, char cEnd) {
int i, ret = 0;
U32 r = 1;
*num = 0;
while ((s[ret] != cEnd) && (s[ret] != '\0')) {
ret++;
}
if (s[ret] != cEnd) {
return 0;
}
i = ret - 1;
while (i >= 0) {
if ((s[i] < '0') || (s[i] > '9')) {
return 0;
}
*num += (s[i] - '0') * r;
r *= 10;
i--;
}
return ret;
}
static int getPara(const char *s, U32 *Para, char cEnd) {
if (s[0] != ' ') {
return 0;
}
return getNum(s + 1, Para, cEnd) + 1;
}
static int parseParas(const char *s, int num, U32 *para, char cEnd) {
int i, tmp, p = 0;
for (i=0 ; i<num; i++) {
if (i == (num - 1))
tmp = getPara(&s[p], ¶[i], cEnd);
else
tmp = getPara(&s[p], ¶[i], ' ');
p += tmp;
if (!tmp)
return 0;
}
return p;
}
int sprintf(char *out, const char *format, ...);
static U32 UU_chksum_val;
static int UU_getdata(int iLen, char *buf) {
int i = 0, j, k,l = 0, n, resend_addr = 0;
U32 chk_sum;
char tmp[11], tmp_code[3];
UU_chksum_val = 0;
while(i < iLen) {
n = (VCOM_getchar() - 0x20) & 0x3F;
if((n < 1) || (n > 45))
return 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -