Browse Source

update:bl下载达到峰值
add:读卡器功能,支持SDHC的TF卡,但是PC机上U盘初始化需要较长时间,16GTF卡约13秒,读取速度约700KB,写入速度约350KB,格式化太漫长不建议使用

alienwalker 4 năm trước cách đây
mục cha
commit
1513f882d3

+ 26 - 0
application/src/luat_lib_usbapp.c

@@ -125,7 +125,31 @@ static int l_usb_vhid_cancel_upload(lua_State* L) {
     return 0;
 }
 
+/*
+USB U盘设备挂载SDHC,TF卡
+@api usbapp.udisk_attach_sdhc(id)
+@int 设备id,默认为0
+@return nil 无返回值
+@usage
+usbapp.udisk_attach_sdhc(0)
+*/
+static int l_usb_udisk_attach_sdhc(lua_State* L) {
+    luat_usb_app_vhid_cancel_upload(USB_ID0);
+    return 0;
+}
 
+/*
+USB U盘设备去除挂载SDHC,TF卡
+@api usbapp.udisk_detach_sdhc(id)
+@int 设备id,默认为0
+@return nil 无返回值
+@usage
+usbapp.udisk_detach_sdhc(0)
+*/
+static int l_usb_udisk_detach_sdhc(lua_State* L) {
+    luat_usb_app_vhid_cancel_upload(USB_ID0);
+    return 0;
+}
 #include "rotable.h"
 static const rotable_Reg reg_usbapp[] =
 {
@@ -133,6 +157,8 @@ static const rotable_Reg reg_usbapp[] =
     { "stop",               l_usb_stop,                 0},
     { "vhid_upload",        l_usb_vhid_upload,          0},
     { "vhid_cancel_upload", l_usb_vhid_cancel_upload,   0},
+	{ "udisk_attach_sdhc", l_usb_udisk_attach_sdhc,   0},
+	{ "udisk_detach_sdhc", l_usb_udisk_detach_sdhc,   0},
 
     { "HID_NOT_READY",      NULL,   USB_HID_NOT_READY},
     { "HID_READY",          NULL,   USB_HID_READY},

+ 5 - 0
application/src/luat_spi_air105.c

@@ -382,3 +382,8 @@ void luat_spi_set_sdhc_ctrl(block_disk_t *disk)
 {
 	disk->opts = &sdhc_spi_disk_opts;
 }
+
+void *luat_spi_get_sdhc_ctrl(void)
+{
+	return luat_fatfs_spi_ctrl;
+}

+ 11 - 0
application/src/luat_usb_app_air105.c

@@ -26,6 +26,7 @@
 
 #define LUAT_LOG_TAG "luat.usbapp"
 #include "luat_log.h"
+extern void *luat_spi_get_sdhc_ctrl(void);
 
 int32_t luat_usb_app_vhid_cb(void *pData, void *pParam);
 
@@ -51,3 +52,13 @@ void luat_usb_app_vhid_cancel_upload(uint8_t usb_id)
 {
 	Core_VHIDUploadStop(usb_id);
 }
+
+void luat_usb_udisk_attach_sdhc(uint8_t usb_id)
+{
+	Core_UDiskAttachSDHC(usb_id, luat_spi_get_sdhc_ctrl());
+}
+
+void luat_usb_udisk_detach_sdhc(uint8_t usb_id)
+{
+	Core_UDiskDetachSDHC(usb_id);
+}

+ 5 - 1
bsp/air105/hal/core_debug.c

@@ -35,7 +35,7 @@
 #define DBG_BUF_SIZE (4090)
 #define DBG_TXBUF_SIZE DBG_BUF_SIZE
 #define DBG_RXBUF_SIZE DBG_BUF_SIZE
-#define DBG_RXBUF_BAND (10)
+#define DBG_RXBUF_BAND (3)
 #endif
 
 typedef struct
@@ -51,7 +51,11 @@ typedef struct
 #else
 	uint8_t CacheData[DBG_BUF_SIZE * 2];
 #endif
+#ifdef __RUN_IN_RAM__
+	uint8_t RxData[__FLASH_BLOCK_SIZE__];
+#else
 	uint8_t RxData[DBG_BUF_SIZE * 2];
+#endif
 	uint8_t TxBuf[DBG_TXBUF_SIZE];
 	uint8_t RxDMABuf[DBG_RXBUF_BAND][DBG_RXBUF_SIZE + 16];
 	uint8_t AppMode;

+ 27 - 46
bsp/air105/hal/core_flash.c

@@ -35,7 +35,7 @@ void __FUNC_IN_RAM__ CACHE_CleanAll(CACHE_TypeDef *Cache)
 	Cache->CACHE_REF |= CACHE_REFRESH;
 	while ((Cache->CACHE_REF & CACHE_REFRESH));
 }
-#if 0 //没什么用,没有ROM里的API好用
+#ifdef __RUN_IN_RAM__
 typedef struct
 {
     uint8_t Instruction;
@@ -48,12 +48,11 @@ typedef struct
 
 }FLASH_CommandTypeDef;
 #define QSPI_FIFO_NUM	32
-#define __FLASH_DISABLE_IRQ__
 
 #define FLASH_QSPI_TIMEOUT_DEFAULT_CNT	(19000) //18944
 #define FLASH_QSPI_ACCESS_REQ_ENABLE	(0x00000001U)
 #define FLASH_QSPI_FLASH_READY_ENABLE	(0x0000006BU)
-static int32_t __FUNC_IN_RAM__ prvQSPI_Command(FLASH_CommandTypeDef *cmd, int32_t timeout)
+static int32_t prvQSPI_Command(FLASH_CommandTypeDef *cmd, int32_t timeout)
 {
 	int32_t i;
 	int32_t status = -ERROR_OPERATION_FAILED;
@@ -74,7 +73,7 @@ static int32_t __FUNC_IN_RAM__ prvQSPI_Command(FLASH_CommandTypeDef *cmd, int32_
 	return status;
 }
 
-static int32_t __FUNC_IN_RAM__ prvQSPI_WriteEnable(QSPI_BusModeTypeDef bus_mode)
+static int32_t prvQSPI_WriteEnable(QSPI_BusModeTypeDef bus_mode)
 {
 	FLASH_CommandTypeDef sCommand;
 
@@ -99,7 +98,7 @@ static int32_t __FUNC_IN_RAM__ prvQSPI_WriteEnable(QSPI_BusModeTypeDef bus_mode)
 }
 
 //PP,QPP,Sector Erase,Block Erase, Chip Erase, Write Status Reg, Erase Security Reg
-static int32_t __FUNC_IN_RAM__ prvQSPI_IsBusy(QSPI_BusModeTypeDef bus_mode)
+int32_t prvQSPI_IsBusy(QSPI_BusModeTypeDef bus_mode)
 {
 	FLASH_CommandTypeDef sCommand;
 
@@ -127,58 +126,40 @@ static int32_t __FUNC_IN_RAM__ prvQSPI_IsBusy(QSPI_BusModeTypeDef bus_mode)
 	return ERROR_NONE;
 }
 
-int32_t __FUNC_IN_RAM__ Flash_Erase(uint32_t Address, uint32_t Length)
+int32_t Flash_EraseStart(uint32_t Address, uint8_t IsBlock)
 {
 	FLASH_CommandTypeDef sCommand;
-	uint32_t TotalLen = 0;
-	uint32_t FlashAddress, DummyLen;
 	Address &= (uint32_t)(0x00FFFFFF);
 	while (CACHE->CACHE_CS & CACHE_IS_BUSY);
 	sCommand.BusMode = QSPI_BUSMODE_111;
 	sCommand.CmdFormat = QSPI_CMDFORMAT_CMD8_ADDR24;
-	while (TotalLen < Length)
-	{
-		if (prvQSPI_WriteEnable(sCommand.BusMode) != 0)
-		{
-			return -ERROR_OPERATION_FAILED;
-		}
-		FlashAddress = Address + TotalLen;
-		DummyLen = Length - TotalLen;
-		if (!(FlashAddress & SPI_FLASH_BLOCK_MASK) && (DummyLen >= SPI_FLASH_BLOCK_SIZE))
-		{
-			sCommand.Instruction = SPIFLASH_CMD_BE;
-			TotalLen += SPI_FLASH_BLOCK_SIZE;
-		}
-		else
-		{
-			sCommand.Instruction = SPIFLASH_CMD_SE;
-			TotalLen += SPI_FLASH_SECTOR_SIZE;
-		}
-		sCommand.Address = FlashAddress;
-#if (defined __FLASH_DISABLE_IRQ__)
-		__disable_irq();
-#endif
-		if (prvQSPI_Command(&sCommand, FLASH_QSPI_TIMEOUT_DEFAULT_CNT))
-		{
-#if (defined __FLASH_DISABLE_IRQ__)
-			CACHE_CleanAll(CACHE);
-			__enable_irq();
-#endif
-			return -ERROR_OPERATION_FAILED;
-		}
-
-		while(prvQSPI_IsBusy(sCommand.BusMode));
-#if (defined __FLASH_DISABLE_IRQ__)
-		__enable_irq();
-#endif
 
+	if (prvQSPI_WriteEnable(sCommand.BusMode) != 0)
+	{
+		return -ERROR_OPERATION_FAILED;
+	}
+	if (IsBlock)
+	{
+		sCommand.Instruction = SPIFLASH_CMD_BE;
+	}
+	else
+	{
+		sCommand.Instruction = SPIFLASH_CMD_SE;
+	}
+	sCommand.Address = Address;
+	if (prvQSPI_Command(&sCommand, FLASH_QSPI_TIMEOUT_DEFAULT_CNT))
+	{
+		return -ERROR_OPERATION_FAILED;
 	}
-#if (defined __FLASH_DISABLE_IRQ__)
-	CACHE_CleanAll(CACHE);
-#endif
 	return ERROR_NONE;
 }
 
+int32_t Flash_CheckBusy(void)
+{
+	return prvQSPI_IsBusy(QSPI_BUSMODE_111);
+}
+#endif
+#if 0
 int32_t __FUNC_IN_RAM__ Flash_Program(uint32_t Address, const uint8_t *pBuf, uint32_t Len)
 {
 	FLASH_CommandTypeDef sCommand;

+ 5 - 3
bsp/air105/hal/core_usb_ll_driver.c

@@ -1668,9 +1668,8 @@ void USB_DeviceXfer(HANDLE hUSB, uint8_t EpIndex)
 	USB_EndpointCtrlStruct *pEpCtrl = &hwUSB->EpCtrl[EpIndex];
 	USB_EndpointDataStruct EpData;
 	uint16_t TxLen, i;
-	EpData.USB_ID = USB_ID0;
-	EpData.EpIndex = EpIndex;
-	EpData.IsToDevice = 0;
+
+
 	if (pEpCtrl->TxBuf.Data)
 	{
 		if (pEpCtrl->TxBuf.Pos >= pEpCtrl->TxBuf.MaxLen)
@@ -1743,6 +1742,9 @@ XFER_DONE:
 	memset(&pEpCtrl->TxBuf, 0, sizeof(Buffer_Struct));
 	if (EpIndex)
 	{
+		memset(&EpData, 0, sizeof(EpData));
+		EpData.USB_ID = USB_ID0;
+		EpData.EpIndex = EpIndex;
 		pEpCtrl->CB(&EpData, pEpCtrl->pData);
 	}
 	else

+ 5 - 0
bsp/air105/include/core_flash.h

@@ -53,4 +53,9 @@ int32_t Flash_Erase(uint32_t Address, uint32_t Length);
   * @retval 0成功,其他失败
   */
 int32_t Flash_Program(uint32_t Address, const uint8_t *pBuf, uint32_t Len);
+
+#ifdef __RUN_IN_RAM__
+int32_t Flash_EraseStart(uint32_t Address, uint8_t IsBlock);
+int32_t Flash_CheckBusy(void);
+#endif
 #endif

+ 68 - 25
bsp/air105/platform/bl_main.c

@@ -28,7 +28,7 @@ uint32_t SystemCoreClock;
 #define FW_UPGRADE_START_TIME	300
 #define FW_UPGRADE_ALL_TIME	2000
 #define FW_UPGRADE_DATA_TIME 50
-#define FW_OTA_FLASH_BUF_LEN	4096
+#define FW_OTA_FLASH_BUF_LEN	SPI_FLASH_BLOCK_SIZE
 enum
 {
 	FW_UPGRADE_STATE_IDLE,
@@ -67,8 +67,6 @@ static uint32_t CRC32_Table[256];
 static BL_CtrlStuct prvBL;
 static SPIFlash_CtrlStruct prvSPIFlash;
 
-
-
 void Jump_AppRun(uint32_t Address)
 {
   /* Jump to user application */
@@ -113,14 +111,6 @@ void BL_LockFlash(void)
 
 }
 
-void BL_EraseSector(uint32_t address)
-{
-	Flash_EraseSector(address, 0);
-//	BL_DBG("%x", address);
-//	FLASH_EraseSector(address);
-//	CACHE_CleanAll(CACHE);
-}
-
 static void BL_OTAErase(uint32_t Address, uint32_t Len)
 {
 	Flash_Erase(Address, Len);
@@ -200,7 +190,7 @@ uint8_t BL_RunLzmaBlock(uint8_t *Head, uint8_t HeadLen)
 		prvBL.NextLzmaHeaderSize = HeadLen;
 		prvBL.NextLzmaData = prvBL.FWDataBuffer.Data;
 		prvBL.NextLzmaDataLen = prvBL.FWDataBuffer.Pos;
-		OS_InitBuffer(&prvBL.FWDataBuffer, SPI_FLASH_BLOCK_SIZE);
+		OS_InitBuffer(&prvBL.FWDataBuffer, __FLASH_BLOCK_SIZE__);
 		prvBL.NextLzmaAddress = 0;
 		return ERROR_NONE;
 	}
@@ -212,7 +202,7 @@ uint8_t BL_RunLzmaBlock(uint8_t *Head, uint8_t HeadLen)
 
 void Local_Upgrade(void)
 {
-	uint8_t *FullData = malloc(SPI_FLASH_BLOCK_SIZE);
+	DBuffer_Struct DBuf;
 	uint32_t FinishLen = 0;
 	uint32_t ProgramLen, CRC32, i;
 	uint64_t AllToTick = GetSysTick() + FW_UPGRADE_START_TIME * CORE_TICK_1MS;
@@ -223,6 +213,7 @@ void Local_Upgrade(void)
 	uint32_t CurLzmaDataLen;
 	uint8_t CurLzmaHead[LZMA_PROPS_SIZE + 8];
 	uint8_t CurLzmaHeadLen;
+	DBuffer_Init(&DBuf, __FLASH_BLOCK_SIZE__);
 	DBG_Response(DBG_DEVICE_FW_UPGRADE_READY, ERROR_NONE, &ConnectCnt, 1);
 	while(!prvBL.ForceOut)
 	{
@@ -248,25 +239,72 @@ void Local_Upgrade(void)
 			break;
 		case FW_UPGRADE_STATE_RUN:
 		case FW_UPGRADE_STATE_WAIT_END:
+			if (DBuffer_GetDataLen(&DBuf, 0))
+			{
+				DBuffer_SwapCache(&DBuf);
+				DBuffer_SetDataLen(&DBuf, 0, 0);
+				goto PROGRAM_BLOCK;
+			}
 			if (prvBL.NextLzmaData)
 			{
-				WDT_Feed();
 				CurLzmaData = prvBL.NextLzmaData;
 				CurLzmaDataLen = prvBL.NextLzmaDataLen;
 				memcpy(CurLzmaHead, prvBL.NextLzmaHeader, prvBL.NextLzmaHeaderSize);
 				CurLzmaHeadLen = prvBL.NextLzmaHeaderSize;
 				prvBL.NextLzmaData = NULL;
-				ProgramLen = __FLASH_BLOCK_SIZE__;
-				LzmaUncompress(FullData, &ProgramLen, CurLzmaData, &CurLzmaDataLen, CurLzmaHead, CurLzmaHeadLen);
-				Flash_Erase(prvBL.FWStartAddress + FinishLen, __FLASH_BLOCK_SIZE__);
-				Flash_Program(prvBL.FWStartAddress + FinishLen, FullData, ProgramLen);
+				if (!CurLzmaHead[0])
+				{
+					memcpy(DBuffer_GetCache(&DBuf, 1), CurLzmaData, CurLzmaDataLen);
+					DBuffer_SetDataLen(&DBuf, CurLzmaDataLen, 1);
+				}
+				else
+				{
+					ProgramLen = __FLASH_BLOCK_SIZE__;
+					LzmaUncompress(DBuffer_GetCache(&DBuf, 1), &ProgramLen, CurLzmaData, &CurLzmaDataLen, CurLzmaHead, CurLzmaHeadLen);
+					DBuffer_SetDataLen(&DBuf, ProgramLen, 1);
+				}
 				free(CurLzmaData);
 				CurLzmaData = NULL;
-				FinishLen += ProgramLen;
-				DataToTick = GetSysTick() + FW_UPGRADE_DATA_TIME * CORE_TICK_1MS;
-				AllToTick = GetSysTick() + FW_UPGRADE_ALL_TIME * CORE_TICK_1MS;
-			}
 
+				goto PROGRAM_BLOCK;
+			}
+			goto PROGRAM_CHECK;
+PROGRAM_BLOCK:
+			WDT_Feed();
+			if (memcmp(prvBL.FWStartAddress + FinishLen, DBuffer_GetCache(&DBuf, 1), DBuffer_GetDataLen(&DBuf, 1)))
+			{
+				Flash_EraseStart(prvBL.FWStartAddress + FinishLen, 1);
+				while(Flash_CheckBusy())
+				{
+					if (prvBL.NextLzmaData && !DBuffer_GetDataLen(&DBuf, 0))
+					{
+						CurLzmaData = prvBL.NextLzmaData;
+						CurLzmaDataLen = prvBL.NextLzmaDataLen;
+						memcpy(CurLzmaHead, prvBL.NextLzmaHeader, prvBL.NextLzmaHeaderSize);
+						CurLzmaHeadLen = prvBL.NextLzmaHeaderSize;
+						prvBL.NextLzmaData = NULL;
+						if (!CurLzmaHead[0])
+						{
+							memcpy(DBuffer_GetCache(&DBuf, 0), CurLzmaData, CurLzmaDataLen);
+							DBuffer_SetDataLen(&DBuf, CurLzmaDataLen, 0);
+						}
+						else
+						{
+							ProgramLen = __FLASH_BLOCK_SIZE__;
+							LzmaUncompress(DBuffer_GetCache(&DBuf, 0), &ProgramLen, CurLzmaData, &CurLzmaDataLen, CurLzmaHead, CurLzmaHeadLen);
+							DBuffer_SetDataLen(&DBuf, ProgramLen, 0);
+						}
+						free(CurLzmaData);
+						CurLzmaData = NULL;
+					}
+				}
+				CACHE_CleanAll(CACHE);
+				Flash_Program(prvBL.FWStartAddress + FinishLen, DBuffer_GetCache(&DBuf, 1), DBuffer_GetDataLen(&DBuf, 1));
+			}
+			FinishLen += DBuffer_GetDataLen(&DBuf, 1);
+			DataToTick = GetSysTick() + FW_UPGRADE_DATA_TIME * CORE_TICK_1MS;
+			AllToTick = GetSysTick() + FW_UPGRADE_ALL_TIME * CORE_TICK_1MS;
+PROGRAM_CHECK:
 			if (FinishLen >= prvBL.FWTotalLen)
 			{
 				CACHE_CleanAll(CACHE);
@@ -295,9 +333,9 @@ void Local_Upgrade(void)
 	}
 	if (ConnectOK)
 	{
-		BL_EraseSector(__FLASH_OTA_INFO_ADDR__);
+		BL_OTAErase(__FLASH_OTA_INFO_ADDR__, __FLASH_SECTOR_SIZE__);
 	}
-	free(FullData);
+	DBuffer_DeInit(&DBuf);
 }
 
 static int32_t BL_OTAReadDataInFlash(void *pData, void *pParam)
@@ -545,7 +583,7 @@ OTA_END:
 	}
 	else
 	{
-		BL_EraseSector(__FLASH_OTA_INFO_ADDR__);
+		BL_OTAErase(__FLASH_OTA_INFO_ADDR__, __FLASH_SECTOR_SIZE__);
 	}
 
 }
@@ -553,7 +591,12 @@ OTA_END:
 void SystemInit(void)
 {
 	SYSCTRL->LDO25_CR = (1 << 5);
+#ifdef __RUN_IN_RAM__
+	memcpy(__SRAM_BASE_ADDR__, &__isr_start_address, 1024);
+	SCB->VTOR = __SRAM_BASE_ADDR__;
+#else
 	SCB->VTOR = (uint32_t)(&__isr_start_address);
+#endif
 #ifdef __USE_XTL__
 	SYSCTRL->FREQ_SEL = 0x20000000 | SYSCTRL_FREQ_SEL_HCLK_DIV_1_2 | (1 << 13) | SYSCTRL_FREQ_SEL_CLOCK_SOURCE_EXT | SYSCTRL_FREQ_SEL_XTAL_192Mhz;
 #else

+ 311 - 0
bsp/air105/platform/startup_run_in_ram.s

@@ -0,0 +1,311 @@
+/*
+ * Copyright (c) 2022 OpenLuat & AirM2M
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+  .syntax unified
+  .cpu cortex-m4
+  .fpu softvfp
+  .thumb
+
+.global  g_pfnVectors
+.global HardFault_Handler
+/* start address for the initialization values of the .data section. 
+defined in linker script */
+.word  _sidata
+/* start address for the .data section. defined in linker script */  
+.word  _sdata
+/* end address for the .data section. defined in linker script */
+.word  _edata
+/* start address for the .bss section. defined in linker script */
+.word  _sbss
+/* end address for the .bss section. defined in linker script */
+.word  _ebss
+/* stack used for SystemInit_ExtMemCtl; always internal RAM used */
+.word  _sitext
+.word  _sstext
+.word  _setext
+/**
+ * @brief  This is the code that gets called when the processor first
+ *          starts execution following a reset event. Only the absolutely
+ *          necessary set is performed, after which the application
+ *          supplied main() routine is called. 
+ * @param  None
+ * @retval : None
+*/
+
+    .section  .text.Reset_Handler
+  .weak  Reset_Handler
+  .type  Reset_Handler, %function
+Reset_Handler:  
+	movs r0, #0
+	movs r1, #0
+	movs r2, #0
+	movs r3, #0
+	movs r4, #0
+	movs r5, #0
+	movs r6, #0
+	movs r7, #0
+
+	LDR R0, =g_pfnVectors
+	LDR R1, =0xE000ED08
+	STR R0,[R1]
+  ldr   sp, =_estack     /* set stack pointer */
+
+/* Copy the data segment initializers from flash to SRAM */  
+  movs  r1, #0
+  b  LoopCopyTextInit
+
+CopyTextInit:
+  ldr  r3, =_sitext
+  ldr  r3, [r3, r1]
+  str  r3, [r0, r1]
+  adds  r1, r1, #4
+
+LoopCopyTextInit:
+  ldr  r0, =_sstext
+  ldr  r3, =_setext
+  adds  r2, r0, r1
+  cmp  r2, r3
+  bcc  CopyTextInit
+  movs  r1, #0
+  b  LoopCopyDataInit
+
+CopyDataInit:
+  ldr  r3, =_sidata
+  ldr  r3, [r3, r1]
+  str  r3, [r0, r1]
+  adds  r1, r1, #4
+    
+LoopCopyDataInit:
+  ldr  r0, =_sdata
+  ldr  r3, =_edata
+  adds  r2, r0, r1
+  cmp  r2, r3
+  bcc  CopyDataInit
+  ldr  r2, =_sbss
+  b  LoopFillZerobss
+/* Zero fill the bss segment. */  
+FillZerobss:
+  movs  r3, #0
+  str  r3, [r2], #4
+    
+LoopFillZerobss:
+  ldr  r3, = _ebss
+  cmp  r2, r3
+  bcc  FillZerobss
+
+/* Call the clock system intitialization function.*/
+  bl  SystemInit   
+/* Call static constructors */
+  bl __libc_init_array /*目前看来这个没什么用,如果代码量有超可以去掉*/
+/* Call the application's entry point.*/
+  bl  main
+  bx  lr    
+.size  Reset_Handler, .-Reset_Handler
+
+/**
+ * @brief  This is the code that gets called when the processor receives an 
+ *         unexpected interrupt.  This simply enters an infinite loop, preserving
+ *         the system state for examination by a debugger.
+ * @param  None     
+ * @retval None       
+*/
+    .section  .text.Default_Handler,"ax",%progbits
+Default_Handler:
+Infinite_Loop:
+  b  Infinite_Loop
+  .size  Default_Handler, .-Default_Handler
+/******************************************************************************
+*
+* The minimal vector table for a Cortex M3. Note that the proper constructs
+* must be placed on this to ensure that it ends up at physical address
+* 0x0000.0000.
+* 
+*******************************************************************************/
+   .section  .isr_vector,"a",%progbits
+  .type  g_pfnVectors, %object
+  .size  g_pfnVectors, .-g_pfnVectors
+    
+    
+g_pfnVectors:
+  .word  _estack
+  .word  Reset_Handler
+  .word  NMI_Handler
+  .word  HardFault_Handler
+  .word  MemManage_Handler
+  .word  BusFault_Handler
+  .word  UsageFault_Handler
+  .word  0
+  .word  0
+  .word  0
+  .word  0
+  .word  SVC_Handler
+  .word  DebugMon_Handler
+  .word  0
+  .word  PendSV_Handler
+  .word  SysTick_Handler
+  
+  /* External Interrupts */
+  .word     ISR_GlobalHandler                   /* Window WatchDog              */                                        
+  .word     ISR_GlobalHandler                    /* PVD through EXTI Line detection */                        
+  .word     ISR_GlobalHandler             /* Tamper and TimeStamps through the EXTI line */            
+  .word     ISR_GlobalHandler               /* RTC Wakeup through the EXTI line */                      
+  .word     ISR_GlobalHandler                  /* FLASH                        */                                          
+  .word     ISR_GlobalHandler                    /* RCC                          */                                            
+  .word     ISR_GlobalHandler                  /* EXTI Line0                   */                        
+  .word     ISR_GlobalHandler                  /* EXTI Line1                   */                          
+  .word     ISR_GlobalHandler                  /* EXTI Line2                   */                          
+  .word     ISR_GlobalHandler                  /* EXTI Line3                   */                          
+  .word     ISR_GlobalHandler                  /* EXTI Line4                   */                          
+  .word     ISR_GlobalHandler           /* DMA1 Stream 0                */                  
+  .word     ISR_GlobalHandler           /* DMA1 Stream 1                */                   
+  .word     ISR_GlobalHandler           /* DMA1 Stream 2                */                   
+  .word     ISR_GlobalHandler           /* DMA1 Stream 3                */                   
+  .word     ISR_GlobalHandler           /* DMA1 Stream 4                */                   
+  .word     ISR_GlobalHandler           /* DMA1 Stream 5                */                   
+  .word     ISR_GlobalHandler           /* DMA1 Stream 6                */                   
+  .word     ISR_GlobalHandler                    /* ADC1, ADC2 and ADC3s         */                   
+  .word     ISR_GlobalHandler                /* CAN1 TX                      */                         
+  .word     ISR_GlobalHandler               /* CAN1 RX0                     */                          
+  .word     ISR_GlobalHandler               /* CAN1 RX1                     */                          
+  .word     ISR_GlobalHandler               /* CAN1 SCE                     */                          
+  .word     ISR_GlobalHandler                /* External Line[9:5]s          */                          
+  .word     ISR_GlobalHandler          /* TIM1 Break and TIM9          */         
+  .word     ISR_GlobalHandler          /* TIM1 Update and TIM10        */         
+  .word     ISR_GlobalHandler     /* TIM1 Trigger and Commutation and TIM11 */
+  .word     ISR_GlobalHandler                /* TIM1 Capture Compare         */                          
+  .word     ISR_GlobalHandler                   /* TIM2                         */                   
+  .word     ISR_GlobalHandler                   /* TIM3                         */                   
+  .word     ISR_GlobalHandler                   /* TIM4                         */                   
+  .word     ISR_GlobalHandler                /* I2C1 Event                   */                          
+  .word     ISR_GlobalHandler                /* I2C1 Error                   */                          
+  .word     ISR_GlobalHandler                /* I2C2 Event                   */                          
+  .word     ISR_GlobalHandler                /* I2C2 Error                   */                            
+  .word     ISR_GlobalHandler                   /* SPI1                         */                   
+  .word     ISR_GlobalHandler                   /* SPI2                         */                   
+  .word     ISR_GlobalHandler                 /* USART1                       */                   
+  .word     ISR_GlobalHandler                 /* USART2                       */                   
+  .word     ISR_GlobalHandler                 /* USART3                       */                   
+  .word     ISR_GlobalHandler              /* External Line[15:10]s        */                          
+  .word     ISR_GlobalHandler              /* RTC Alarm (A and B) through EXTI Line */                 
+  .word     ISR_GlobalHandler            /* USB OTG FS Wakeup through EXTI line */                       
+  .word     ISR_GlobalHandler         /* TIM8 Break and TIM12         */         
+  .word     ISR_GlobalHandler          /* TIM8 Update and TIM13        */         
+  .word     ISR_GlobalHandler     /* TIM8 Trigger and Commutation and TIM14 */
+  .word     ISR_GlobalHandler                /* TIM8 Capture Compare         */                          
+  .word     ISR_GlobalHandler           /* DMA1 Stream7                 */                          
+  .word     ISR_GlobalHandler                   /* FSMC                         */                   
+  .word     ISR_GlobalHandler                   /* SDIO                         */                   
+  .word     ISR_GlobalHandler                   /* TIM5                         */                   
+  .word     ISR_GlobalHandler                   /* SPI3                         */                   
+  .word     ISR_GlobalHandler                  /* UART4                        */                   
+  .word     ISR_GlobalHandler                  /* UART5                        */                   
+  .word     ISR_GlobalHandler               /* TIM6 and DAC1&2 underrun errors */                   
+  .word     ISR_GlobalHandler                   /* TIM7                         */
+  .word     ISR_GlobalHandler           /* DMA2 Stream 0                */                   
+  .word     ISR_GlobalHandler           /* DMA2 Stream 1                */                   
+  .word     ISR_GlobalHandler           /* DMA2 Stream 2                */                   
+  .word     ISR_GlobalHandler           /* DMA2 Stream 3                */                   
+  .word     ISR_GlobalHandler           /* DMA2 Stream 4                */                   
+  .word     ISR_GlobalHandler                    /* Ethernet                     */                   
+  .word     ISR_GlobalHandler               /* Ethernet Wakeup through EXTI line */                     
+  .word     ISR_GlobalHandler                /* CAN2 TX                      */                          
+  .word     ISR_GlobalHandler               /* CAN2 RX0                     */                          
+  .word     ISR_GlobalHandler               /* CAN2 RX1                     */                          
+  .word     ISR_GlobalHandler               /* CAN2 SCE                     */                          
+  .word     ISR_GlobalHandler                 /* USB OTG FS                   */                   
+  .word     ISR_GlobalHandler           /* DMA2 Stream 5                */                   
+  .word     ISR_GlobalHandler           /* DMA2 Stream 6                */                   
+  .word     ISR_GlobalHandler           /* DMA2 Stream 7                */                   
+  .word     ISR_GlobalHandler                 /* USART6                       */                    
+  .word     ISR_GlobalHandler                /* I2C3 event                   */                          
+  .word     ISR_GlobalHandler                /* I2C3 error                   */                          
+  .word     ISR_GlobalHandler         /* USB OTG HS End Point 1 Out   */                   
+  .word     ISR_GlobalHandler          /* USB OTG HS End Point 1 In    */                   
+  .word     ISR_GlobalHandler            /* USB OTG HS Wakeup through EXTI */                         
+  .word     ISR_GlobalHandler                 /* USB OTG HS                   */                   
+  .word     ISR_GlobalHandler                   /* DCMI                         */                   
+  .word     ISR_GlobalHandler                                /* CRYP crypto                  */                   
+  .word     ISR_GlobalHandler               /* Hash and Rng                 */
+  .word     ISR_GlobalHandler                    /* FPU                          */
+  .word     ISR_GlobalHandler                  /* UART7                        */      
+  .word     ISR_GlobalHandler                  /* UART8                        */
+  .word     ISR_GlobalHandler                   /* SPI4                         */
+  .word     ISR_GlobalHandler                   /* SPI5 						  */
+  .word     ISR_GlobalHandler                   /* SPI6						  */
+  .word     ISR_GlobalHandler                   /* SAI1						  */
+  .word     ISR_GlobalHandler                   /* LTDC_IRQHandler			  */
+  .word     ISR_GlobalHandler                /* LTDC_ER_IRQHandler			  */
+  .word     ISR_GlobalHandler                  /* DMA2D                   
+                         
+/*******************************************************************************
+*
+* Provide weak aliases for each Exception handler to the Default_Handler. 
+* As they are weak aliases, any function with the same name will override 
+* this definition.
+* 
+*******************************************************************************/
+   .weak      NMI_Handler
+   .thumb_set NMI_Handler,Default_Handler
+
+
+
+	.section  .text.CmTrace_Handler
+ 	.type CmTrace_Handler, %function
+CmTrace_Handler:
+ 	MOV     r0, lr                  /* get lr */
+    MOV     r1, sp                  /* get stack pointer (current is MSP) */
+    BL      cm_backtrace_fault
+Fault_Loop:
+    BL      Fault_Loop              /* while(1) */
+    
+   .weak      NMI_Handler
+   .thumb_set NMI_Handler,CmTrace_Handler
+  
+   .weak      HardFault_Handler
+   .thumb_set HardFault_Handler,CmTrace_Handler
+  
+   .weak      MemManage_Handler
+   .thumb_set MemManage_Handler,CmTrace_Handler
+  
+   .weak      BusFault_Handler
+   .thumb_set BusFault_Handler,CmTrace_Handler
+
+   .weak      UsageFault_Handler
+   .thumb_set UsageFault_Handler,CmTrace_Handler
+
+   .weak      SVC_Handler
+   .thumb_set SVC_Handler,Default_Handler
+
+   .weak      DebugMon_Handler
+   .thumb_set DebugMon_Handler,Default_Handler
+
+   .weak      PendSV_Handler
+   .thumb_set PendSV_Handler,Default_Handler
+
+   .weak      SysTick_Handler
+   .thumb_set SysTick_Handler,Default_Handler              
+  
+   .weak      ISR_GlobalHandler                   
+   .thumb_set ISR_GlobalHandler,Default_Handler      
+                  
+
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

+ 70 - 0
bsp/air105/test/test_sdcard.c

@@ -0,0 +1,70 @@
+#include "user.h"
+
+static int32_t prvEventCB(void *pData, void *pParam)
+{
+	DBG("!");
+	return 0;
+}
+
+void prvSDHC_Test(void *p)
+{
+	int i, ok;
+	uint32_t *Buf = malloc(65536);
+	uint32_t *Buf2 = malloc(65536);
+	SDHC_SPICtrlStruct SDHC;
+	memset(&SDHC, 0, sizeof(SDHC));
+	SDHC.SpiID = SPI_ID0;
+	SDHC.CSPin = GPIOC_13;
+	SDHC.IsSpiDMAMode = 0;
+//	SDHC.NotifyTask = Task_GetCurrent();
+//	SDHC.TaskCB = prvEventCB;
+    SDHC.SDHCReadBlockTo = 5 * CORE_TICK_1MS;
+    SDHC.SDHCWriteBlockTo = 25 * CORE_TICK_1MS;
+    SDHC.IsPrintData = 0;
+    GPIO_Iomux(GPIOC_12,2);
+    GPIO_Iomux(GPIOC_14,2);
+    GPIO_Iomux(GPIOC_15,2);
+    GPIO_Config(SDHC.CSPin, 0, 1);
+    SPI_MasterInit(SDHC.SpiID, 8, SPI_MODE_0, 400000, NULL, NULL);
+
+    SDHC_SpiInitCard(&SDHC);
+    if (SDHC.IsInitDone)
+    {
+    	ok = 1;
+    	SPI_SetNewConfig(SDHC.SpiID, 24000000, SPI_MODE_0);
+    	SDHC_SpiReadCardConfig(&SDHC);
+    	DBG("卡容量 %ublock", SDHC.Info.LogBlockNbr);
+    	for(i = 0; i < 16384; i++)
+    	{
+    		Buf[i] = i;
+    	}
+    	SDHC_SpiWriteBlocks(&SDHC, Buf, 0x1000, 128);
+    	SDHC_SpiReadBlocks(&SDHC, Buf2, 0x1000, 128);
+    	for(i = 0; i < 16384; i++)
+    	{
+    		if (Buf[i] != Buf2[i])
+    		{
+    			DBG("error %u,%u,%u", i, Buf[i], Buf2[i]);
+    			ok = 0;
+    			break;
+    		}
+    	}
+    	if (ok)
+    	{
+    		DBG("TEST OK!");
+    	}
+    }
+
+	while(1)
+	{
+		Task_DelayMS(1000);
+
+	}
+}
+
+void SDHC_TestInit(void)
+{
+	Task_Create(prvSDHC_Test, NULL, 1024, SERVICE_TASK_PRO, "sdhc task");
+}
+
+//INIT_TASK_EXPORT(SDHC_TestInit, "3");

+ 42 - 0
bsp/air105/test/test_usb_device.c

@@ -55,3 +55,45 @@ void Test_USBStart(void)
 	Core_VUartInit(VIRTUAL_UART0, 0, 1, 0, 0, 0, prvTest_USBCB);
 //	Core_VUartSetRxTimeout(VIRTUAL_UART0, 200);
 }
+
+void prvUSB_Test(void *p)
+{
+	SDHC_SPICtrlStruct SDHC;
+	memset(&SDHC, 0, sizeof(SDHC));
+	SDHC.SpiID = SPI_ID0;
+	SDHC.CSPin = GPIOC_13;
+	SDHC.IsSpiDMAMode = 0;
+//	SDHC.NotifyTask = Task_GetCurrent();
+//	SDHC.TaskCB = prvEventCB;
+    SDHC.SDHCReadBlockTo = 5 * CORE_TICK_1MS;
+    SDHC.SDHCWriteBlockTo = 25 * CORE_TICK_1MS;
+    SDHC.IsPrintData = 0;
+    GPIO_Iomux(GPIOC_12,2);
+    GPIO_Iomux(GPIOC_14,2);
+    GPIO_Iomux(GPIOC_15,2);
+    GPIO_Config(SDHC.CSPin, 0, 1);
+    SPI_MasterInit(SDHC.SpiID, 8, SPI_MODE_0, 400000, NULL, NULL);
+
+    SDHC_SpiInitCard(&SDHC);
+    if (SDHC.IsInitDone)
+    {
+    	SPI_SetNewConfig(SDHC.SpiID, 24000000, SPI_MODE_0);
+    	SDHC_SpiReadCardConfig(&SDHC);
+    	DBG("卡容量 %ublock", SDHC.Info.LogBlockNbr);
+    	Test_USBStart();
+    	Core_UDiskAttachSDHC(0, &SDHC);
+    	Core_USBDefaultDeviceStart(0);
+    }
+    else
+    {
+    	Test_USBStart();
+    	Core_USBDefaultDeviceStart(0);
+    }
+	Task_Exit();
+}
+void USB_TestInit(void)
+{
+	Task_Create(prvUSB_Test, NULL, 2 * 1024, SERVICE_TASK_PRO, "usb task");
+}
+
+//INIT_TASK_EXPORT(USB_TestInit, "3");

+ 18 - 0
bsp/common/include/bsp_common.h

@@ -91,6 +91,15 @@ typedef struct
 	uint32_t MaxLen;
 }Buffer_Struct;
 
+
+typedef struct
+{
+	uint8_t *pCache[2];
+	uint32_t pCacheLen[2];
+	uint32_t MaxLen;
+	uint8_t CurCacheSn;
+}DBuffer_Struct;
+
 typedef union
 {
 	void *p;
@@ -148,6 +157,7 @@ enum
 	DEV_EVENT_ID_START = 0xf0200000,
 	DEV_SPIFLASH_SPI_DONE,
 	DEV_SDHC_SPI_DONE,
+	USB_APP_EVENT_ID_START = 0xf0300000,
 	USER_EVENT_ID_START = 0xf1000000,
 	INVALID_EVENT_ID = 0xffffffff,
 };
@@ -239,6 +249,14 @@ int32_t OS_ReSizeBuffer(Buffer_Struct *Buf, uint32_t Size);
 int32_t OS_BufferWrite(Buffer_Struct *Buf, void *Data, uint32_t Len);
 int32_t OS_BufferWriteLimit(Buffer_Struct *Buf, void *Data, uint32_t Len);
 void OS_BufferRemove(Buffer_Struct *Buf, uint32_t Len);
+void DBuffer_Init(DBuffer_Struct *DBuf, uint32_t Size);
+void DBuffer_ReInit(DBuffer_Struct *DBuf, uint32_t Size);
+void DBuffer_DeInit(DBuffer_Struct *DBuf);
+void *DBuffer_GetCache(DBuffer_Struct *DBuf, uint8_t IsCurrent);
+void DBuffer_SwapCache(DBuffer_Struct *DBuf);
+void DBuffer_SetDataLen(DBuffer_Struct *DBuf, uint32_t Len, uint8_t IsCurrent);
+uint32_t DBuffer_GetDataLen(DBuffer_Struct *DBuf, uint8_t IsCurrent);
+
 
 void Buffer_StaticInit(Buffer_Struct *Buf, void *Src, uint32_t MaxLen);
 int32_t Buffer_StaticWrite(Buffer_Struct *Buf, void *Data, uint32_t Len);

+ 2 - 0
bsp/common/include/core_service.h

@@ -74,4 +74,6 @@ void Core_VUartBufferTxStop(uint8_t UartID);
 void Core_VHIDInit(uint8_t USB_ID, CBFuncEx_t CB);
 void Core_VHIDUploadData(uint8_t USB_ID, uint8_t *Data, uint16_t Len);
 void Core_VHIDUploadStop(uint8_t USB_ID);
+
+void Core_UDiskAttachSDHC(uint8_t USB_ID, void *pCtrl);
 #endif

+ 44 - 0
bsp/common/src/bsp_common.c

@@ -191,6 +191,50 @@ int32_t Buffer_StaticWrite(Buffer_Struct *Buf, void *Data, uint32_t Len)
 	return Len;
 }
 
+void DBuffer_Init(DBuffer_Struct *DBuf, uint32_t Size)
+{
+	memset(DBuf, 0, sizeof(DBuffer_Struct));
+	DBuf->pCache[0] = malloc(Size);
+	DBuf->pCache[1] = malloc(Size);
+	DBuf->MaxLen = Size;
+}
+
+void DBuffer_ReInit(DBuffer_Struct *DBuf, uint32_t Size)
+{
+	if (DBuf->pCache[0]) free(DBuf->pCache[0]);
+	if (DBuf->pCache[1]) free(DBuf->pCache[1]);
+	DBuffer_Init(DBuf, Size);
+}
+
+void DBuffer_DeInit(DBuffer_Struct *DBuf)
+{
+	free(DBuf->pCache[0]);
+	free(DBuf->pCache[1]);
+	DBuf->pCache[0] = NULL;
+	DBuf->pCache[1] = NULL;
+	DBuf->MaxLen = 0;
+}
+
+void *DBuffer_GetCache(DBuffer_Struct *DBuf, uint8_t IsCurrent)
+{
+	return DBuf->pCache[IsCurrent?DBuf->CurCacheSn:!DBuf->CurCacheSn];
+}
+
+void DBuffer_SwapCache(DBuffer_Struct *DBuf)
+{
+	DBuf->CurCacheSn = !DBuf->CurCacheSn;
+}
+
+void DBuffer_SetDataLen(DBuffer_Struct *DBuf, uint32_t Len, uint8_t IsCurrent)
+{
+	DBuf->pCacheLen[IsCurrent?DBuf->CurCacheSn:!DBuf->CurCacheSn] = Len;
+}
+
+uint32_t DBuffer_GetDataLen(DBuffer_Struct *DBuf, uint8_t IsCurrent)
+{
+	return DBuf->pCacheLen[IsCurrent?DBuf->CurCacheSn:!DBuf->CurCacheSn];
+}
+
 //void Buffer_Remove(Buffer_Struct *Buf, uint32_t Len)
 //{
 //	uint32_t RestLen;

+ 2 - 26
bsp/common/src/core_service.c

@@ -41,7 +41,6 @@ enum
 {
 	SERVICE_LCD_DRAW = SERVICE_EVENT_ID_START + 1,
 	SERVICE_CAMERA_DRAW,
-	SERVICE_USB_ACTION,
 	SERVICE_DECODE_QR,
 	SERVICE_SCAN_KEYBOARD,
 	SERVICE_ENCODE_JPEG_START,
@@ -235,25 +234,7 @@ static void prvService_Task(void* params)
 		case SERVICE_SCAN_KEYBOARD:
 			SoftKB_ScanOnce();
 			break;
-		case SERVICE_USB_ACTION:
-			switch (Event.Param2)
-			{
-			case SERV_USB_RESET_END:
-				DBG("USB%d reset", Event.Param1);
-				Task_DelayMS(1);
-				USB_StackDeviceAfterDisconnect(Event.Param1);
-				break;
-			case SERV_USB_RESUME_END:
-				Task_DelayMS(20);
-				USB_ResumeEnd(Event.Param3);
-				break;
-			case SERV_USB_SUSPEND:
-				DBG("USB%d suspend", Event.Param1);
-				break;
-			case SERV_USB_RESUME:
-				break;
-			}
-			break;
+
 		case SERVICE_DECODE_QR:
 			if (Event.Param3)
 			{
@@ -451,11 +432,6 @@ void Core_DecodeQR(uint8_t *ImageData, uint16_t ImageW, uint16_t ImageH,  CBData
 	Task_SendEvent(prvService.ServiceHandle, SERVICE_DECODE_QR, ImageData, uPV.u32, CB);
 }
 
-void Core_USBAction(uint8_t USB_ID, uint8_t Action, void *pParam)
-{
-	Task_SendEvent(prvService.ServiceHandle, SERVICE_USB_ACTION, USB_ID, Action, pParam);
-}
-
 void Core_ScanKeyBoard(void)
 {
 	Task_SendEvent(prvService.ServiceHandle, SERVICE_SCAN_KEYBOARD, 0, 0, 0);
@@ -593,5 +569,5 @@ void Core_UserTaskInit(void)
 
 INIT_TASK_EXPORT(Core_HWTaskInit, "0");
 INIT_TASK_EXPORT(Core_ServiceInit, "1");
-INIT_TASK_EXPORT(Core_UserTaskInit, "2");
+INIT_TASK_EXPORT(Core_UserTaskInit, "5");
 #endif

+ 272 - 125
bsp/common/src/core_usb_app.c

@@ -20,14 +20,16 @@
  */
 
 #include "user.h"
-
 enum
 {
 	DEVICE_INTERFACE_HID_SN,
 	DEVICE_INTERFACE_MSC_SN,
 	DEVICE_INTERFACE_SERIAL_SN,
 	DEVICE_INTERFACE_MAX,
+	USB_HW_ACTION = USB_APP_EVENT_ID_START + 1,
+	USBD_MSC_CB,
 };
+
 #define DEVICE_HID_KEYBOARD_EP_IN		(0x01)
 #define DEVICE_HID_KEYBOARD_EP_OUT		(0x01)
 #define DEVICE_MASS_STORAGE_EP_IN		(0x02)
@@ -77,9 +79,116 @@ typedef struct
 	uint8_t ToDeviceEpIndex;
 }Virtual_UartCtrlStruct;
 
-static MSC_SCSICtrlStruct prvLuatOS_SCSI;
+typedef struct
+{
+	MSC_SCSICtrlStruct tSCSI;
+	Virtual_UDiskCtrlStruct tUDisk;
+	DBuffer_Struct DataBuf;
+	SDHC_SPICtrlStruct *pSDHC;
+	HANDLE hTaskHandle;
+}USB_AppCtrlStruct;
+
+static const uint8_t prvCore_StandardInquiryData[STANDARD_INQUIRY_DATA_LEN] =
+{
+		0x00, //磁盘设备
+		0x00, //其中最高位D7为RMB。RMB=0,表示不可移除设备。如果RMB=1,则为可移除设备。
+		0x02, //各种版本号
+		0x02, //数据响应格式 0x02
+		0x1F, //附加数据长度,为31字节
+		0x00, //保留
+		0x00, //保留
+		0x00, //保留
+		'A','I','R','M','2','M',' ',' ',
+		'L','U','A','T','O','S','-','S','O','C',' ','U','S','B',' ',' ',
+		'1','.','0','0'
+};
+
+const uint8_t prvCore_MSCPage00InquiryData[LENGTH_INQUIRY_PAGE00] =
+{
+	0x00,
+	0x00,
+	0x00,
+	(LENGTH_INQUIRY_PAGE00 - 4U),
+	0x00,
+	0x80
+};
+
+/* USB Mass storage VPD Page 0x80 Inquiry Data for Unit Serial Number */
+const uint8_t prvCore_MSCPage80InquiryData[LENGTH_INQUIRY_PAGE80] =
+{
+	0x00,
+	0x80,
+	0x00,
+	LENGTH_INQUIRY_PAGE80,
+	0x20,     /* Put Product Serial number */
+	0x20,
+	0x20,
+	0x20
+};
+
+/* USB Mass storage sense 6 Data */
+const uint8_t prvCore_MSCModeSense6data[MODE_SENSE6_LEN] =
+{
+	0x22,
+	0x00,
+	0x00,
+	0x00,
+	0x08,
+	0x12,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00
+};
+
+
+/* USB Mass storage sense 10  Data */
+const uint8_t prvCore_MSCModeSense10data[MODE_SENSE10_LEN] =
+{
+	0x00,
+	0x26,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x08,
+	0x12,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00
+};
+
+static USB_AppCtrlStruct prvUSBApp;
 static Virtual_HIDCtrlStruct prvLuatOS_VirtualHID;
-static Virtual_UDiskCtrlStruct prvLuatOS_VirtualUDisk;
 static Virtual_UartCtrlStruct prvLuatOS_VirtualUart[VIRTUAL_UART_MAX];
 
 /* LangID = 0x0409: U.S. English */
@@ -349,104 +458,7 @@ static const USB_FullConfigStruct prvCore_FullConfig =
 		.pFullConfig = {&prvCore_Config, NULL, NULL},
 };
 
-static const uint8_t prvCore_StandardInquiryData[STANDARD_INQUIRY_DATA_LEN] =
-{
-		0x00, //磁盘设备
-		0x00, //其中最高位D7为RMB。RMB=0,表示不可移除设备。如果RMB=1,则为可移除设备。
-		0x02, //各种版本号
-		0x02, //数据响应格式 0x02
-		0x1F, //附加数据长度,为31字节
-		0x00, //保留
-		0x00, //保留
-		0x00, //保留
-		'A','I','R','M','2','M',' ',' ',
-		'L','U','A','T','O','S','-','S','O','C',' ','U','S','B',' ',' ',
-		'1','.','0','0'
-};
 
-static const uint8_t prvCore_MSCPage00InquiryData[LENGTH_INQUIRY_PAGE00] =
-{
-	0x00,
-	0x00,
-	0x00,
-	(LENGTH_INQUIRY_PAGE00 - 4U),
-	0x00,
-	0x80
-};
-
-/* USB Mass storage VPD Page 0x80 Inquiry Data for Unit Serial Number */
-static const uint8_t prvCore_MSCPage80InquiryData[LENGTH_INQUIRY_PAGE80] =
-{
-	0x00,
-	0x80,
-	0x00,
-	LENGTH_INQUIRY_PAGE80,
-	0x20,     /* Put Product Serial number */
-	0x20,
-	0x20,
-	0x20
-};
-
-/* USB Mass storage sense 6 Data */
-static const uint8_t prvCore_MSCModeSense6data[MODE_SENSE6_LEN] =
-{
-	0x22,
-	0x00,
-	0x00,
-	0x00,
-	0x08,
-	0x12,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00
-};
-
-
-/* USB Mass storage sense 10  Data */
-static const uint8_t prvCore_MSCModeSense10data[MODE_SENSE10_LEN] =
-{
-	0x00,
-	0x26,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x08,
-	0x12,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00
-};
 
 static int32_t prvCore_SCSIInit(uint8_t LUN, void *pUserData)
 {
@@ -455,8 +467,8 @@ static int32_t prvCore_SCSIInit(uint8_t LUN, void *pUserData)
 
 static int32_t prvCore_SCSIGetCapacity(uint8_t LUN, uint32_t *BlockNum, uint32_t *BlockSize, void *pUserData)
 {
-	*BlockNum = prvLuatOS_VirtualUDisk.BlockTotalNums;
-	*BlockSize = prvLuatOS_VirtualUDisk.BlockSize;
+	*BlockNum = prvUSBApp.tUDisk.BlockTotalNums;
+	*BlockSize = prvUSBApp.tUDisk.BlockSize;
 	return 0;
 }
 
@@ -472,46 +484,57 @@ static int32_t prvCore_SCSIIsWriteProtected(uint8_t LUN, void *pUserData)
 
 static int32_t prvCore_SCSIPreRead(uint8_t LUN, uint32_t BlockAddress, uint32_t BlockNums, void *pUserData)
 {
-	if ((BlockAddress + BlockNums) * prvLuatOS_VirtualUDisk.BlockSize > VIRTUAL_UDISK_LEN)
+	if ((BlockAddress + BlockNums) * prvUSBApp.tUDisk.BlockSize > VIRTUAL_UDISK_LEN)
 	{
 		return -1;
 	}
-	prvLuatOS_VirtualUDisk.CurAddress = BlockAddress * prvLuatOS_VirtualUDisk.BlockSize;
+	prvUSBApp.tUDisk.CurAddress = BlockAddress * prvUSBApp.tUDisk.BlockSize;
 	return 0;
 }
 
 static int32_t prvCore_SCSIRead(uint8_t LUN, uint32_t Len, uint8_t **pOutData, uint32_t *OutLen, void *pUserData)
 {
-	if (Len + prvLuatOS_VirtualUDisk.CurAddress > VIRTUAL_UDISK_LEN)
+	if (Len + prvUSBApp.tUDisk.CurAddress > VIRTUAL_UDISK_LEN)
 	{
 		return -1;
 	}
-	*pOutData = &prvLuatOS_VirtualUDisk.VirtualData[prvLuatOS_VirtualUDisk.CurAddress];
+	*pOutData = &prvUSBApp.tUDisk.VirtualData[prvUSBApp.tUDisk.CurAddress];
 	*OutLen = Len;
-	prvLuatOS_VirtualUDisk.CurAddress += Len;
+	prvUSBApp.tUDisk.CurAddress += Len;
+	return 0;
+}
+
+static int32_t prvCore_SCSIReadNext(uint8_t LUN, void *pUserData)
+{
 	return 0;
 }
 
 static int32_t prvCore_SCSIPreWrite(uint8_t LUN, uint32_t BlockAddress, uint32_t BlockNums, void *pUserData)
 {
-	if ((BlockAddress + BlockNums) * prvLuatOS_VirtualUDisk.BlockSize > VIRTUAL_UDISK_LEN)
+	if ((BlockAddress + BlockNums) * prvUSBApp.tUDisk.BlockSize > VIRTUAL_UDISK_LEN)
 	{
 		return -1;
 	}
-	prvLuatOS_VirtualUDisk.CurAddress = BlockAddress * prvLuatOS_VirtualUDisk.BlockSize;
+	prvUSBApp.tUDisk.CurAddress = BlockAddress * prvUSBApp.tUDisk.BlockSize;
 	return 0;
 }
 
 static int32_t prvCore_SCSIWrite(uint8_t LUN, uint8_t *Data, uint32_t Len, void *pUserData)
 {
-	if (Len + prvLuatOS_VirtualUDisk.CurAddress > VIRTUAL_UDISK_LEN)
+	if (Len + prvUSBApp.tUDisk.CurAddress > VIRTUAL_UDISK_LEN)
 	{
 		return -1;
 	}
-	memcpy(&prvLuatOS_VirtualUDisk.VirtualData[prvLuatOS_VirtualUDisk.CurAddress], Data, Len);
-	prvLuatOS_VirtualUDisk.CurAddress += Len;
+	memcpy(&prvUSBApp.tUDisk.VirtualData[prvUSBApp.tUDisk.CurAddress], Data, Len);
+	prvUSBApp.tUDisk.CurAddress += Len;
+	return 0;
+}
+
+static int32_t prvCore_SCSIDoWrite(uint8_t LUN, void *pUserData)
+{
 	return 0;
 }
+
 static int32_t prvCore_SCSIUserCmd(USB_EndpointDataStruct *pEpData, MSC_SCSICtrlStruct *pMSC)
 {
 	return -1;
@@ -521,6 +544,7 @@ static int32_t prvCore_SCSIGetMaxLUN(uint8_t *LUN, void *pUserData)
 {
 	*LUN = 0;
 }
+
 static const USB_StorageSCSITypeDef prvCore_SCSIFun =
 {
 		prvCore_SCSIGetMaxLUN,
@@ -530,8 +554,10 @@ static const USB_StorageSCSITypeDef prvCore_SCSIFun =
 		prvCore_SCSIIsWriteProtected,
 		prvCore_SCSIPreRead,
 		prvCore_SCSIRead,
+		prvCore_SCSIReadNext,
 		prvCore_SCSIPreWrite,
 		prvCore_SCSIWrite,
+		prvCore_SCSIDoWrite,
 		prvCore_SCSIUserCmd,
 		&prvCore_StandardInquiryData,
 		&prvCore_MSCPage00InquiryData,
@@ -592,7 +618,7 @@ static int32_t prvCore_USBEp0CB(void *pData, void *pParam)
 {
 	int32_t Result = -ERROR_CMD_NOT_SUPPORT;
 	USB_EndpointDataStruct *pEpData = (USB_EndpointDataStruct *)pData;
-	USB_StorageSCSITypeDef *pUserFun = (USB_StorageSCSITypeDef *)prvLuatOS_SCSI.pSCSIUserFunList;
+	USB_StorageSCSITypeDef *pUserFun = (USB_StorageSCSITypeDef *)prvUSBApp.tSCSI.pSCSIUserFunList;
 	uint16_t wLength, wValue;
 	Virtual_UartCtrlStruct *pVUart;
 //	DBG("%d,%d,%d,%d", pEpData->USB_ID, pEpData->EpIndex, pEpData->IsToDevice, pEpData->Len);
@@ -635,8 +661,8 @@ static int32_t prvCore_USBEp0CB(void *pData, void *pParam)
 				}
 				break;
 			case MSC_GET_MAX_LUN:
-				pUserFun->GetMaxLUN(&prvLuatOS_SCSI.LogicalUnitNum, prvLuatOS_SCSI.pUserData);
-				USB_StackTxEpData(pEpData->USB_ID, pEpData->EpIndex, &prvLuatOS_SCSI.LogicalUnitNum, 1, wLength, 1);
+				pUserFun->GetMaxLUN(&prvUSBApp.tSCSI.LogicalUnitNum, prvUSBApp.tSCSI.pUserData);
+				USB_StackTxEpData(pEpData->USB_ID, pEpData->EpIndex, &prvUSBApp.tSCSI.LogicalUnitNum, 1, wLength, 1);
 
 				Result = ERROR_NONE;
 				break;
@@ -652,7 +678,45 @@ static int32_t prvCore_USBEp0CB(void *pData, void *pParam)
 static int32_t prvCore_MSCCB(void *pData, void *pParam)
 {
 	USB_EndpointDataStruct *pEpData = (USB_EndpointDataStruct *)pData;
-	USB_MSCHandle(pEpData, &prvLuatOS_SCSI);
+	USB_EndpointDataStruct *pEpDataSave;
+	switch(prvUSBApp.tSCSI.BotState)
+	{
+	case USB_MSC_BOT_STATE_DATA_OUT_TO_DEVICE:
+	case USB_MSC_BOT_STATE_DATA_IN_TO_HOST:
+		goto MSC_RUN_IN_TASK;
+		break;
+	default:
+		if (pEpData->IsToDevice && pEpData->Data)
+		{
+			switch(pEpData->Data[15])
+			{
+			case SCSI_READ10:
+			case SCSI_READ12:
+			case SCSI_READ16:
+				goto MSC_RUN_IN_TASK;
+				break;
+			}
+
+		}
+		break;
+	}
+	USB_MSCHandle(pEpData, &prvUSBApp.tSCSI);
+	return ERROR_NONE;
+MSC_RUN_IN_TASK:
+	pEpDataSave = malloc(sizeof(USB_EndpointDataStruct));
+	memcpy(pEpDataSave, pEpData, sizeof(USB_EndpointDataStruct));
+	if (pEpData->Data && pEpData->Len)
+	{
+		pEpDataSave->Data = malloc(pEpData->Len);
+		memcpy(pEpDataSave->Data, pEpData->Data, pEpData->Len);
+	}
+	else
+	{
+		pEpDataSave->Data = NULL;
+		pEpDataSave->Len = 0;
+	}
+	Task_SendEvent(prvUSBApp.hTaskHandle, USBD_MSC_CB, pEpDataSave, &prvUSBApp.tSCSI, pParam);
+
 	return ERROR_NONE;
 }
 
@@ -738,7 +802,7 @@ static int32_t prvCore_USBStateCB(void *pData, void *pParam)
 	{
 	case USBD_BUS_TYPE_DISCONNECT:
 		prvCore_VHIDSetReady(0);
-		USB_MSCReset(&prvLuatOS_SCSI);
+		USB_MSCReset(&prvUSBApp.tSCSI);
 		for(i = 0; i < VIRTUAL_UART_MAX; i++)
 		{
 			prvLuatOS_VirtualUart[i].USBOnOff = 0;
@@ -758,12 +822,15 @@ void Core_USBDefaultDeviceStart(uint8_t USB_ID)
 	prvLuatOS_VirtualHID.USB_ID = USB_ID;
 	prvLuatOS_VirtualHID.IsReady = 0;
 	prvLuatOS_VirtualHID.ToHostEpIndex = DEVICE_HID_KEYBOARD_EP_IN;
-	prvLuatOS_VirtualUDisk.BlockTotalNums = VIRTUAL_UDISK_BLOCKS_NUMS;
-	prvLuatOS_VirtualUDisk.BlockSize = VIRTUAL_UDISK_BLOCKS_LEN;
-	prvLuatOS_SCSI.LogicalUnitNum = 0;
-	prvLuatOS_SCSI.ToHostEpIndex = DEVICE_MASS_STORAGE_EP_IN;
-	prvLuatOS_SCSI.ToDeviceEpIndex = DEVICE_MASS_STORAGE_EP_OUT;
-	prvLuatOS_SCSI.pSCSIUserFunList = &prvCore_SCSIFun;
+	prvUSBApp.tUDisk.BlockTotalNums = VIRTUAL_UDISK_BLOCKS_NUMS;
+	prvUSBApp.tUDisk.BlockSize = VIRTUAL_UDISK_BLOCKS_LEN;
+	prvUSBApp.tSCSI.LogicalUnitNum = 0;
+	prvUSBApp.tSCSI.ToHostEpIndex = DEVICE_MASS_STORAGE_EP_IN;
+	prvUSBApp.tSCSI.ToDeviceEpIndex = DEVICE_MASS_STORAGE_EP_OUT;
+	if (!prvUSBApp.tSCSI.pSCSIUserFunList)
+	{
+		prvUSBApp.tSCSI.pSCSIUserFunList = &prvCore_SCSIFun;
+	}
 	if (!prvLuatOS_VirtualHID.CB)
 	{
 		prvLuatOS_VirtualHID.CB = prvCore_VHIDDummyCB;
@@ -808,8 +875,8 @@ void Core_USBDefaultDeviceStart(uint8_t USB_ID)
 	}
 	prvLuatOS_VirtualUart[VIRTUAL_UART0].ToDeviceEpIndex = DEVICE_GENERIC_SERIAL_EP_IN;
 	prvLuatOS_VirtualUart[VIRTUAL_UART0].ToHostEpIndex = DEVICE_GENERIC_SERIAL_EP_OUT;
-	prvLuatOS_VirtualUDisk.VirtualData = prvLuatOS_VirtualUart[VIRTUAL_UART0].TxCacheBuf.Data;
-	USB_MSCReset(&prvLuatOS_SCSI);
+	prvUSBApp.tUDisk.VirtualData = prvLuatOS_VirtualUart[0].TxCacheBuf.Data;
+	USB_MSCReset(&prvUSBApp.tSCSI);
 
 	USB_StackStartDevice(USB_ID);
 }
@@ -1086,3 +1153,83 @@ void Core_VHIDUploadStop(uint8_t USB_ID)
 	USB_StackStopDeviceTx(pVHID->USB_ID, pVHID->ToHostEpIndex, 0);
 	USB_StackEpIntOnOff(pVHID->USB_ID, pVHID->ToHostEpIndex, 0, 1);
 }
+
+#ifdef __BUILD_OS__
+
+static void prvCore_USBAppTask(void *pParam)
+{
+	OS_EVENT Event;
+	USB_EndpointDataStruct *pEpData;
+	while(1)
+	{
+		Task_GetEventByMS(prvUSBApp.hTaskHandle, CORE_EVENT_ID_ANY, &Event, NULL, 0);
+		switch(Event.ID)
+		{
+		case USB_HW_ACTION:
+			switch (Event.Param2)
+			{
+			case SERV_USB_RESET_END:
+				DBG("USB%d reset", Event.Param1);
+				Task_DelayMS(1);
+				USB_StackDeviceAfterDisconnect(Event.Param1);
+				break;
+			case SERV_USB_RESUME_END:
+				Task_DelayMS(20);
+				USB_ResumeEnd(Event.Param3);
+				break;
+			case SERV_USB_SUSPEND:
+				DBG("USB%d suspend", Event.Param1);
+				break;
+			case SERV_USB_RESUME:
+				break;
+			}
+			break;
+		case USBD_MSC_CB:
+			pEpData = (USB_EndpointDataStruct *)Event.Param1;
+//			DBG("%d,%d,%d,%d", pEpData->USB_ID, pEpData->EpIndex, pEpData->IsToDevice, pEpData->Len);
+			USB_MSCHandle(pEpData, Event.Param2);
+			free(pEpData->Data);
+			free(Event.Param1);
+			WDT_Feed();
+			break;
+		}
+	}
+}
+
+
+void Core_USBAction(uint8_t USB_ID, uint8_t Action, void *pParam)
+{
+	Task_SendEvent(prvUSBApp.hTaskHandle, USB_HW_ACTION, USB_ID, Action, pParam);
+}
+
+extern const USB_StorageSCSITypeDef prvSDHC_SCSIFun;
+void Core_UDiskAttachSDHC(uint8_t USB_ID, void *pCtrl)
+{
+	if (!prvUSBApp.pSDHC)
+	{
+		prvUSBApp.pSDHC = malloc(sizeof(SDHC_SPICtrlStruct));
+	}
+	memcpy(prvUSBApp.pSDHC, pCtrl, sizeof(SDHC_SPICtrlStruct));
+	prvUSBApp.tSCSI.pSCSIUserFunList = &prvSDHC_SCSIFun;
+	prvUSBApp.tSCSI.pUserData = prvUSBApp.pSDHC;
+	DBuffer_ReInit(&prvUSBApp.DataBuf, 8 * 1024);
+	prvUSBApp.pSDHC->SCSIDataBuf = &prvUSBApp.DataBuf;
+
+}
+
+void Core_UDiskDetachSDHC(uint8_t USB_ID)
+{
+	prvUSBApp.tSCSI.pSCSIUserFunList = &prvCore_SCSIFun;
+	prvUSBApp.tSCSI.pUserData = NULL;
+	free(prvUSBApp.pSDHC);
+	prvUSBApp.pSDHC = NULL;
+	DBuffer_DeInit(&prvUSBApp.DataBuf);
+}
+
+void Core_USBAppGlobalInit(void)
+{
+	prvUSBApp.hTaskHandle = Task_Create(prvCore_USBAppTask, NULL,2 * 1024, USB_TASK_PRO, "usb app");
+}
+
+INIT_TASK_EXPORT(Core_USBAppGlobalInit, "2");
+#endif

+ 3 - 0
bsp/device/include/dev_sdhc_spi.h

@@ -106,6 +106,9 @@ typedef struct
 	CBFuncEx_t TaskCB;
 	uint32_t Size;							//flash的大小KB
 	uint32_t OCR;
+	DBuffer_Struct *SCSIDataBuf;
+	uint32_t CurBlock;
+	uint32_t EndBlock;
 	uint16_t WriteWaitCnt;
 	uint8_t CSPin;
 	uint8_t SpiID;

+ 199 - 0
bsp/device/src/dev_sdhc_spi.c

@@ -61,6 +61,205 @@ enum
 	SDCARD_STATE_WRITE,
 };
 
+static const uint8_t prvSDHC_StandardInquiryData[STANDARD_INQUIRY_DATA_LEN] =
+{
+		0x00, //磁盘设备
+		0x80, //其中最高位D7为RMB。RMB=0,表示不可移除设备。如果RMB=1,则为可移除设备。
+		0x02, //各种版本号
+		0x02, //数据响应格式 0x02
+		0x1F, //附加数据长度,为31字节
+		0x00, //保留
+		0x00, //保留
+		0x00, //保留
+		'A','I','R','M','2','M',' ',' ',
+		'L','U','A','T','O','S','-','S','O','C',' ','U','S','B',' ',' ',
+		'1','.','0','0'
+};
+
+extern const uint8_t prvCore_MSCPage00InquiryData[LENGTH_INQUIRY_PAGE00];
+/* USB Mass storage VPD Page 0x80 Inquiry Data for Unit Serial Number */
+extern const uint8_t prvCore_MSCPage80InquiryData[LENGTH_INQUIRY_PAGE80];
+/* USB Mass storage sense 6 Data */
+extern const uint8_t prvCore_MSCModeSense6data[MODE_SENSE6_LEN];
+/* USB Mass storage sense 10  Data */
+extern const uint8_t prvCore_MSCModeSense10data[MODE_SENSE10_LEN];
+
+
+
+static int32_t prvSDHC_SCSIInit(uint8_t LUN, void *pUserData)
+{
+	SDHC_SPICtrlStruct *pSDHC = pUserData;
+	if (!SDHC_IsReady(pSDHC))
+	{
+		SDHC_SpiInitCard(pSDHC);
+	}
+	return SDHC_IsReady(pSDHC)?ERROR_NONE:-ERROR_OPERATION_FAILED;
+}
+
+static int32_t prvSDHC_SCSIGetCapacity(uint8_t LUN, uint32_t *BlockNum, uint32_t *BlockSize, void *pUserData)
+{
+	SDHC_SPICtrlStruct *pSDHC = pUserData;
+	*BlockSize = pSDHC->Info.LogBlockSize;
+	*BlockNum = pSDHC->Info.LogBlockNbr;
+	return 0;
+}
+
+static int32_t prvSDHC_SCSIIsReady(uint8_t LUN, void *pUserData)
+{
+	SDHC_SPICtrlStruct *pSDHC = pUserData;
+	return SDHC_IsReady(pSDHC)?ERROR_NONE:-ERROR_OPERATION_FAILED;
+}
+
+static int32_t prvSDHC_SCSIIsWriteProtected(uint8_t LUN, void *pUserData)
+{
+	return 0;
+}
+
+static int32_t prvSDHC_SCSIReadNext(uint8_t LUN, void *pUserData);
+static int32_t prvSDHC_SCSIPreRead(uint8_t LUN, uint32_t BlockAddress, uint32_t BlockNums, void *pUserData)
+{
+	SDHC_SPICtrlStruct *pSDHC = pUserData;
+	if ((BlockAddress + BlockNums) > pSDHC->Info.LogBlockNbr)
+	{
+		return -1;
+	}
+	pSDHC->CurBlock = BlockAddress;
+	pSDHC->EndBlock = BlockAddress + BlockNums;
+
+	prvSDHC_SCSIReadNext(LUN, pUserData);
+	return 0;
+}
+
+static int32_t prvSDHC_SCSIRead(uint8_t LUN, uint32_t Len, uint8_t **pOutData, uint32_t *OutLen, void *pUserData)
+{
+	SDHC_SPICtrlStruct *pSDHC = pUserData;
+#if 1
+	*pOutData = DBuffer_GetCache(pSDHC->SCSIDataBuf, 1);
+	*OutLen = DBuffer_GetDataLen(pSDHC->SCSIDataBuf, 1);
+	if (*OutLen > Len)
+	{
+		*OutLen = Len;
+	}
+	DBuffer_SetDataLen(pSDHC->SCSIDataBuf, 0, 1);
+	DBuffer_SwapCache(pSDHC->SCSIDataBuf);
+//	Task_DelayMS(1);
+#else
+	uint32_t ReadBlocks;
+	if (pSDHC->EndBlock <= pSDHC->CurBlock) return -1;
+
+	if ( ((pSDHC->EndBlock - pSDHC->CurBlock) << 9) > pSDHC->SCSIDataBuf->MaxLen)
+	{
+		ReadBlocks = pSDHC->SCSIDataBuf->MaxLen >> 9;
+	}
+	else
+	{
+		ReadBlocks = pSDHC->EndBlock - pSDHC->CurBlock;
+	}
+	SDHC_SpiReadBlocks(pSDHC, DBuffer_GetCache(pSDHC->SCSIDataBuf, 1), pSDHC->CurBlock, ReadBlocks);
+	pSDHC->CurBlock += ReadBlocks;
+	*pOutData = DBuffer_GetCache(pSDHC->SCSIDataBuf, 1);
+	*OutLen = ReadBlocks << 9;
+#endif
+	return SDHC_IsReady(pSDHC)?ERROR_NONE:-ERROR_OPERATION_FAILED;
+}
+
+static int32_t prvSDHC_SCSIReadNext(uint8_t LUN, void *pUserData)
+{
+#if 1
+	SDHC_SPICtrlStruct *pSDHC = pUserData;
+	uint32_t ReadBlocks;
+	if (pSDHC->EndBlock <= pSDHC->CurBlock) return -1;
+
+	if ( ((pSDHC->EndBlock - pSDHC->CurBlock) << 9) > pSDHC->SCSIDataBuf->MaxLen)
+	{
+		ReadBlocks = pSDHC->SCSIDataBuf->MaxLen >> 9;
+	}
+	else
+	{
+		ReadBlocks = pSDHC->EndBlock - pSDHC->CurBlock;
+	}
+	SDHC_SpiReadBlocks(pSDHC, DBuffer_GetCache(pSDHC->SCSIDataBuf, 1), pSDHC->CurBlock, ReadBlocks);
+	pSDHC->CurBlock += ReadBlocks;
+	DBuffer_SetDataLen(pSDHC->SCSIDataBuf, ReadBlocks << 9, 1);
+#endif
+	return ERROR_NONE;
+}
+
+
+static int32_t prvSDHC_SCSIPreWrite(uint8_t LUN, uint32_t BlockAddress, uint32_t BlockNums, void *pUserData)
+{
+	SDHC_SPICtrlStruct *pSDHC = pUserData;
+	if (!SDHC_IsReady(pSDHC)) return -1;
+	if ((BlockAddress + BlockNums) > pSDHC->Info.LogBlockNbr)
+	{
+		return -1;
+	}
+	pSDHC->CurBlock = BlockAddress;
+	pSDHC->EndBlock = BlockAddress + BlockNums;
+	DBuffer_SetDataLen(pSDHC->SCSIDataBuf, 0, 1);
+	return 0;
+}
+
+static int32_t prvSDHC_SCSIWrite(uint8_t LUN, uint8_t *Data, uint32_t Len, void *pUserData)
+{
+	SDHC_SPICtrlStruct *pSDHC = pUserData;
+	uint32_t WriteBlocks = Len >> 9;
+	if (!SDHC_IsReady(pSDHC)) return -1;
+	if (pSDHC->EndBlock <= pSDHC->CurBlock) return -1;
+	memcpy(DBuffer_GetCache(pSDHC->SCSIDataBuf, 1) + DBuffer_GetDataLen(pSDHC->SCSIDataBuf, 1), Data, Len);
+	DBuffer_SetDataLen(pSDHC->SCSIDataBuf, DBuffer_GetDataLen(pSDHC->SCSIDataBuf, 1) + Len, 1);
+	return ERROR_NONE;
+}
+
+static int32_t prvSDHC_SCSIDoWrite(uint8_t LUN, void *pUserData)
+{
+	SDHC_SPICtrlStruct *pSDHC = pUserData;
+	uint32_t WriteBlocks = DBuffer_GetDataLen(pSDHC->SCSIDataBuf, 1) >> 9;
+	if (pSDHC->EndBlock <= pSDHC->CurBlock) return -1;
+	if (WriteBlocks)
+	{
+		if (WriteBlocks > (pSDHC->EndBlock - pSDHC->CurBlock))
+		{
+			WriteBlocks = pSDHC->EndBlock - pSDHC->CurBlock;
+		}
+		SDHC_SpiWriteBlocks(pSDHC, DBuffer_GetCache(pSDHC->SCSIDataBuf, 1), pSDHC->CurBlock, WriteBlocks);
+		DBuffer_SetDataLen(pSDHC->SCSIDataBuf, 0, 1);
+	}
+	pSDHC->CurBlock += WriteBlocks;
+	return ERROR_NONE;
+}
+
+static int32_t prvSDHC_SCSIUserCmd(USB_EndpointDataStruct *pEpData, MSC_SCSICtrlStruct *pMSC)
+{
+	return -1;
+}
+
+static int32_t prvSDHC_SCSIGetMaxLUN(uint8_t *LUN, void *pUserData)
+{
+	*LUN = 0;
+}
+
+const USB_StorageSCSITypeDef prvSDHC_SCSIFun =
+{
+		prvSDHC_SCSIGetMaxLUN,
+		prvSDHC_SCSIInit,
+		prvSDHC_SCSIGetCapacity,
+		prvSDHC_SCSIIsReady,
+		prvSDHC_SCSIIsWriteProtected,
+		prvSDHC_SCSIPreRead,
+		prvSDHC_SCSIRead,
+		prvSDHC_SCSIReadNext,
+		prvSDHC_SCSIPreWrite,
+		prvSDHC_SCSIWrite,
+		prvSDHC_SCSIDoWrite,
+		prvSDHC_SCSIUserCmd,
+		&prvSDHC_StandardInquiryData,
+		&prvCore_MSCPage00InquiryData,
+		&prvCore_MSCPage80InquiryData,
+		&prvCore_MSCModeSense6data,
+		&prvCore_MSCModeSense10data,
+};
+
 static void SDHC_SpiCS(SDHC_SPICtrlStruct *Ctrl, uint8_t OnOff)
 {
 	uint8_t Temp[1] = {0xff};

+ 4 - 0
bsp/usb/include/usb_msc.h

@@ -108,6 +108,7 @@ typedef struct
 	Buffer_Struct BotDataBuffer;
 	SCSI_SenseTypeDef Sense;
 	HANDLE pSCSIUserFunList;
+	Timer_t *ReadTimer;
 	void *pUserData;
 	uint32_t XferDoneLen;
 	uint32_t LastXferLen;
@@ -118,6 +119,7 @@ typedef struct
 	uint8_t ToHostEpIndex;
 	uint8_t ToDeviceEpIndex;
 	uint8_t LogicalUnitNum;
+	uint8_t USB_ID;
 }MSC_SCSICtrlStruct;
 
 typedef struct
@@ -129,8 +131,10 @@ typedef struct
 	int32_t (* IsWriteProtected)(uint8_t LUN, void *pUserData);
 	int32_t (* PreRead)(uint8_t LUN, uint32_t BlockAddress, uint32_t BlockNums, void *pUserData);
 	int32_t (* Read)(uint8_t LUN, uint32_t Len, void **pOutData, uint32_t *OutLen, void *pUserData);
+	int32_t (* ReadNext)(uint8_t LUN, void *pUserData);
 	int32_t (* PreWrite)(uint8_t LUN, uint32_t BlockAddress, uint32_t BlockNums, void *pUserData);
 	int32_t (* Write)(uint8_t LUN, uint8_t *Data, uint32_t Len, void *pUserData);
+	int32_t (* DoWrite)(uint8_t LUN, void *pUserData);
 	int32_t (* UserCmd)(USB_EndpointDataStruct *pEpData, MSC_SCSICtrlStruct *pMSC);
 	void *pStandardInquiry;
 	void *pPage00InquiryData;

+ 39 - 7
bsp/usb/src/core_usb_class_msc_scsi.c

@@ -67,6 +67,8 @@ static const SCSI_CmdFun prvSCSI_CmdFunList []=
 
 };
 
+
+
 static void prvUSB_SendCSW(USB_EndpointDataStruct *pEpData, MSC_SCSICtrlStruct *pMSC)
 {
 	pMSC->CSW.dTag = pMSC->CBW.dTag;
@@ -84,7 +86,18 @@ static void prvUSB_SendCSW(USB_EndpointDataStruct *pEpData, MSC_SCSICtrlStruct *
 	pMSC->XferTotalLen = 0;
 	pMSC->XferDoneLen = 0;
 	pMSC->LastXferLen = 0;
-	USB_StackTxEpData(pEpData->USB_ID, pMSC->ToHostEpIndex, &pMSC->CSW, USB_MSC_BOT_CSW_LENGTH, USB_MSC_BOT_CSW_LENGTH, 0);
+	USB_StackTxEpData(pMSC->USB_ID, pMSC->ToHostEpIndex, &pMSC->CSW, USB_MSC_BOT_CSW_LENGTH, USB_MSC_BOT_CSW_LENGTH, 0);
+	Timer_Stop(pMSC->ReadTimer);
+}
+
+static int32_t prvUSB_MSCTimeout(void *pData, void *pParam)
+{
+	MSC_SCSICtrlStruct *pMSC = (void *)pParam;
+	DBG("!");
+	pMSC->CSWStatus = USB_MSC_CSW_CMD_FAILED;
+	USB_StackStopDeviceTx(pMSC->USB_ID, pMSC->ToHostEpIndex, 0);
+	USB_StackSetEpStatus(pMSC->USB_ID, pMSC->ToHostEpIndex, 1, USB_EP_STATE_STALL);
+	prvUSB_SendCSW(NULL, pMSC);
 }
 
 static void prvUSB_SendBotData(USB_EndpointDataStruct *pEpData, MSC_SCSICtrlStruct *pMSC)
@@ -129,11 +142,14 @@ void USB_SCSISetSenseState(MSC_SCSICtrlStruct *pMSC, uint8_t Skey, uint8_t ASC,
 
 void USB_MSCHandle(USB_EndpointDataStruct *pEpData, MSC_SCSICtrlStruct *pMSC)
 {
+	pMSC->USB_ID = pEpData->USB_ID;
 	if (pEpData->IsToDevice)
 	{
 		switch(pMSC->BotState)
 		{
 		case USB_MSC_BOT_STATE_CSW:
+			DBG("!");
+			pMSC->BotState = USB_MSC_BOT_STATE_IDLE;
 		case USB_MSC_BOT_STATE_IDLE:
 			if (pMSC->CSW.bStatus)
 			{
@@ -154,10 +170,12 @@ void USB_MSCHandle(USB_EndpointDataStruct *pEpData, MSC_SCSICtrlStruct *pMSC)
 				}
 				pMSC->XferDoneLen = 0;
 				prvUSB_SCSIHandleCmd(pEpData, pMSC);
-
 				if (!pMSC->CBW.dDataLength)
 				{
-					prvUSB_SendCSW(pEpData, pMSC);
+					if (pMSC->BotState != USB_MSC_BOT_STATE_CSW)
+					{
+						prvUSB_SendCSW(pEpData, pMSC);
+					}
 				}
 				else if ((pMSC->BotState != USB_MSC_BOT_STATE_DATA_OUT_TO_DEVICE) && (pMSC->BotState != USB_MSC_BOT_STATE_DATA_IN_TO_HOST) )
 				{
@@ -193,6 +211,9 @@ void USB_MSCHandle(USB_EndpointDataStruct *pEpData, MSC_SCSICtrlStruct *pMSC)
 		case USB_MSC_BOT_STATE_DATA_IN_TO_HOST:
 			prvUSB_SCSIHandleToHostData(pEpData, pMSC);
 			break;
+		case USB_MSC_BOT_STATE_IDLE:
+			DBG("!");
+			break;
 		default:
 			DBG("%d", pMSC->BotState);
 			pMSC->CSWStatus = USB_MSC_CSW_CMD_FAILED;
@@ -203,6 +224,7 @@ void USB_MSCHandle(USB_EndpointDataStruct *pEpData, MSC_SCSICtrlStruct *pMSC)
 	}
 	return ;
 ERROR_OUT:
+	DBG("!");
 	pMSC->CSWStatus = USB_MSC_CSW_CMD_FAILED;
 	USB_StackSetEpStatus(pEpData->USB_ID, pMSC->ToDeviceEpIndex, 1, USB_EP_STATE_STALL);
 	prvUSB_SendCSW(pEpData, pMSC);
@@ -232,6 +254,7 @@ static void prvUSB_SCSIHandleCmd(USB_EndpointDataStruct *pEpData, MSC_SCSICtrlSt
 CMD_PROC_END:
 	if (Result)
 	{
+		DBG("%02x", pMSC->CBW.CB[0]);
 		if (!pMSC->Sense.Skey)
 		{
 			USB_SCSISetSenseState(pMSC, SENSE_KEY_ILLEGAL_REQUEST, INVALID_COMMAND_OPERATION_CODE, 0, NULL);
@@ -276,7 +299,7 @@ static void prvUSB_SCSIHandleToDeviceData(USB_EndpointDataStruct *pEpData, MSC_S
 	{
 		prvUSB_SendCSW(pEpData, pMSC);
 	}
-
+	pUserFun->DoWrite(pMSC->CBW.bLUN, pMSC->pUserData);
 }
 
 static void prvUSB_SCSIHandleToHostData(USB_EndpointDataStruct *pEpData, MSC_SCSICtrlStruct *pMSC)
@@ -286,13 +309,13 @@ static void prvUSB_SCSIHandleToHostData(USB_EndpointDataStruct *pEpData, MSC_SCS
 	uint32_t TxLen;
 	USB_StorageSCSITypeDef *pUserFun = (USB_StorageSCSITypeDef *)pMSC->pSCSIUserFunList;
 	pMSC->XferDoneLen += pMSC->LastXferLen;
-//	DBG("%u,%u,%u", pMSC->XferTotalLen, pMSC->XferDoneLen, pMSC->LastXferLen);
 	if (pMSC->XferDoneLen >= pMSC->XferTotalLen)
 	{
 		prvUSB_SendCSW(pEpData, pMSC);
 		return;
 	}
 	Result = pUserFun->Read(pMSC->CBW.bLUN, pMSC->XferTotalLen - pMSC->XferDoneLen, &TxData, &TxLen, pMSC->pUserData);
+//	DBG("%u,%u,%u,%u", pMSC->XferTotalLen, pMSC->XferDoneLen, pMSC->LastXferLen, TxLen);
 	if (Result)
 	{
 		DBG("sense error %x,%x,%x", pMSC->Sense.Skey, pMSC->Sense.ASC, pMSC->Sense.ASCQ);
@@ -307,11 +330,14 @@ static void prvUSB_SCSIHandleToHostData(USB_EndpointDataStruct *pEpData, MSC_SCS
 	{
 		pMSC->LastXferLen = TxLen;
 		USB_StackTxEpData(pEpData->USB_ID, pMSC->ToHostEpIndex, TxData, TxLen, TxLen, 0);
+
 	}
+	pUserFun->ReadNext(pMSC->CBW.bLUN, pMSC->pUserData);
 }
 
 void USB_MSCReset(MSC_SCSICtrlStruct *pMSC)
 {
+	USB_StorageSCSITypeDef *pUserFun = (USB_StorageSCSITypeDef *)pMSC->pSCSIUserFunList;
 	OS_ReInitBuffer(&pMSC->BotDataBuffer, 512);
 	memset(&pMSC->CSW, 0, sizeof(MSC_BOT_CSWTypeDef));
 	memset(&pMSC->CBW, 0, sizeof(MSC_BOT_CBWTypeDef));
@@ -321,7 +347,8 @@ void USB_MSCReset(MSC_SCSICtrlStruct *pMSC)
 	pMSC->XferDoneLen = 0;
 	pMSC->LastXferLen = 0;
 	pMSC->BotState = USB_MSC_BOT_STATE_IDLE;
-	pMSC->MediumState == SCSI_MEDIUM_UNLOCKED;
+	pMSC->MediumState = SCSI_MEDIUM_UNLOCKED;
+	pUserFun->Init(0, pMSC->pUserData);
 }
 
 static int32_t prvSCSI_TestUnitReady(USB_EndpointDataStruct *pEpData, MSC_SCSICtrlStruct *pMSC)
@@ -609,6 +636,7 @@ static int32_t prvSCSI_Read(USB_EndpointDataStruct *pEpData, MSC_SCSICtrlStruct
 	int ret = pUserFun->GetCapacity(pMSC->CBW.bLUN, &BlockNum, &BlockSize, pMSC->pUserData);
 	uint32_t BlockNums, CurBLKAddress;
 	CurBLKAddress = BytesGetBe32(&pMSC->CBW.CB[2]);
+	if (!pMSC->ReadTimer) pMSC->ReadTimer = Timer_Create(prvUSB_MSCTimeout, pMSC, NULL);
 	switch(pMSC->CBW.CB[0])
 	{
 	case SCSI_READ10:
@@ -668,6 +696,8 @@ static int32_t prvSCSI_Read(USB_EndpointDataStruct *pEpData, MSC_SCSICtrlStruct
 	pMSC->LastXferLen = TxLen;
 	USB_StackTxEpData(pEpData->USB_ID, pMSC->ToHostEpIndex, TxData, TxLen, TxLen, 0);
 	pMSC->BotState = USB_MSC_BOT_STATE_DATA_IN_TO_HOST;
+	pUserFun->ReadNext(pMSC->CBW.bLUN, pMSC->pUserData);
+	Timer_StartMS(pMSC->ReadTimer, 1000, 0);
     return 0;
 }
 
@@ -700,7 +730,7 @@ static int32_t prvSCSI_Write(USB_EndpointDataStruct *pEpData, MSC_SCSICtrlStruct
 	}
 
     /* case 10 : Ho <> Di */
-    if ((pMSC->CBW.bmFlags & 0x80U) != 0x80U)
+    if ((pMSC->CBW.bmFlags & 0x80U) == 0x80U)
     {
     	USB_SCSISetSenseState(pMSC, SENSE_KEY_ILLEGAL_REQUEST, INVALID_FIELED_IN_COMMAND, 0, NULL);
     	return -1;
@@ -715,6 +745,7 @@ static int32_t prvSCSI_Write(USB_EndpointDataStruct *pEpData, MSC_SCSICtrlStruct
 
     if (pUserFun->IsReady(pMSC->CBW.bLUN, pMSC->pUserData) != 0)
     {
+    	DBG("!");
     	USB_SCSISetSenseState(pMSC, SENSE_KEY_NOT_READY, MEDIUM_NOT_PRESENT, 0, NULL);
     	return -1;
     }
@@ -722,6 +753,7 @@ static int32_t prvSCSI_Write(USB_EndpointDataStruct *pEpData, MSC_SCSICtrlStruct
     /* cases 4,5 : Hi <> Dn */
     if (pMSC->CBW.dDataLength != (BlockNums * BlockSize))
     {
+    	DBG("!");
     	USB_SCSISetSenseState(pMSC, SENSE_KEY_ILLEGAL_REQUEST, INVALID_FIELED_IN_COMMAND, 0, NULL);
     	return -1;
     }

+ 0 - 1
bsp/usb/src/core_usb_stack.c

@@ -1096,7 +1096,6 @@ void USB_StackAnalyzeDeviceEpRx(uint8_t USB_ID, uint8_t EpIndex)
 	{
 		USBCore->pEpCtrl[EpIndex].RxBuf.Pos = 0;
 		EpData.IsDataStage = (EpData.Len < USBCore->pEpCtrl[EpIndex].MaxPacketLen)?0:1;
-
 		if (USBCore->pEpCtrl[EpIndex].CB(&EpData, USBCore->pEpCtrl[EpIndex].pData))
 		{
 			USB_SetDeviceEPStatus(USBCore->pHWCtrl, EpIndex, 1, USB_EP_STATE_STALL);

+ 20 - 13
project/air105/bl.ld

@@ -1,16 +1,17 @@
 /* Entry Point */
 ENTRY(Reset_Handler)
 
-_stext = ORIGIN(FLASH);
+_stext = ORIGIN(CODE);
 _Min_Heap_Size = 0 ;	/* required amount of heap  */
-_Min_Stack_Size = 0x10000 ;	/* required amount of stack */
+_Min_Stack_Size = 0x4000 ;	/* required amount of stack */
 _estack = ORIGIN(RAM) + _Min_Stack_Size + _Min_Heap_Size;	/* start of "RAM" Ram type memory */
 _sstack = ORIGIN(RAM); /* start of "RAM" Ram type memory */
 __ram_end = ORIGIN(RAM) + LENGTH(RAM);
 /* Memories definition */
 MEMORY
 {
-    RAM    (xrw)    : ORIGIN = 0x20000000,   LENGTH = 640K
+    RAM    (xrw)    : ORIGIN = 0x20010000,   LENGTH = 576K
+    CODE   (rx)    : ORIGIN = 0x20000400,   LENGTH = 63K
     FLASH    (rx)    : ORIGIN = 0x01001000,   LENGTH = 56K
 }
 
@@ -31,10 +32,15 @@ SECTIONS
     {
         . = ALIGN(4);
         *startup_full.o(.text .text.*)
+        *startup_full.s.o(.text .text.*)
+        *startup_run_in_ram.o(.text .text.*)
+        *startup_run_in_ram.s.o(.text .text.*)
     } >FLASH
+    _sitext = LOADADDR(.text);
     .text :
     {
         . = ALIGN(4);
+        _sstext = .;
         *(.text)           /* .text sections (code) */
         *(.text*)          /* .text* sections (code) */
         *(.glue_7)         /* glue arm to thumb code */
@@ -46,7 +52,7 @@ SECTIONS
 
         . = ALIGN(4);
         _etext = .;        /* define a global symbols at end of code */
-    } >FLASH
+    } >CODE AT> FLASH
 
     /* Constant data into "FLASH" Rom type memory */
     .rodata :
@@ -55,13 +61,13 @@ SECTIONS
         *(.rodata)         /* .rodata sections (constants, strings, etc.) */
         *(.rodata*)        /* .rodata* sections (constants, strings, etc.) */
         . = ALIGN(4);
-    } >FLASH
+    } >CODE AT> FLASH
 
     .ARM.extab   : {
         . = ALIGN(4);
         *(.ARM.extab* .gnu.linkonce.armextab.*)
         . = ALIGN(4);
-    } >FLASH
+    } >CODE AT> FLASH
 
     .ARM : {
         . = ALIGN(4);
@@ -69,7 +75,7 @@ SECTIONS
         *(.ARM.exidx*)
         __exidx_end = .;
         . = ALIGN(4);
-    } >FLASH
+    } >CODE AT> FLASH
 
     .preinit_array     :
     {
@@ -78,7 +84,7 @@ SECTIONS
         KEEP (*(.preinit_array*))
         PROVIDE_HIDDEN (__preinit_array_end = .);
         . = ALIGN(4);
-    } >FLASH
+    } >CODE AT> FLASH
 
     .init_array :
     {
@@ -88,7 +94,7 @@ SECTIONS
         KEEP (*(.init_array*))
         PROVIDE_HIDDEN (__init_array_end = .);
         . = ALIGN(4);
-    } >FLASH
+    } >CODE AT> FLASH
 
     .fini_array :
     {
@@ -98,7 +104,7 @@ SECTIONS
         KEEP (*(.fini_array*))
         PROVIDE_HIDDEN (__fini_array_end = .);
         . = ALIGN(4);
-    } >FLASH
+    } >CODE AT> FLASH
     
     .preinit_fun_array :
     {
@@ -108,7 +114,7 @@ SECTIONS
         KEEP (*(.preinit_fun_array*))
         __preinit_fun_array_end = .;
         . = ALIGN(4);
-    } > FLASH
+    } >CODE AT> FLASH
     
     .init_fun_array :
     {
@@ -118,7 +124,7 @@ SECTIONS
         KEEP (*(.init_fun_array*))
         __init_fun_array_end = .;
         . = ALIGN(4);
-    } > FLASH
+    } >CODE AT> FLASH
     
     .task_fun_array :
     {
@@ -128,7 +134,8 @@ SECTIONS
         KEEP (*(.task_fun_array*))
         __task_fun_array_end = .;
         . = ALIGN(4);
-    } > FLASH
+        _setext = .;
+    } >CODE AT> FLASH
     
     /* User_heap_stack section, used to check that there is enough "RAM" Ram  type memory left */
     ._user_heap_stack :

+ 0 - 82
project/air105/build_debug.bat

@@ -1,82 +0,0 @@
-::编译前准备工作
-@echo off
-setlocal enabledelayedexpansion
-set line=0
-for /f  %%a in ('wmic cpu get numberofcores') do (
-set /a line+=1
-if !line!==2 set A=%%a
-)
-set /a CPU_LINE=%A%+%A%
-
-if "%1" == "" (
-    set make_target=app
-) else (
-    set make_target=%1
-)
-set CROSS_TOOL_WIN32_PATH=D:\gcc-mcu
-set CROSS_TOOL_PATH=%CROSS_TOOL_WIN32_PATH:\=/%
-
-set PATH=%CROSS_TOOL_WIN32_PATH%\bin;%PATH%
-REM debug属性标记
-set __DEBUG__=true
-REM 获取项目路径
-set PROJ_DIR=%cd:\=/%
-set CUR_DIR=%cd%
-REM 获取项目名称
-for /f %%i in ("%cd%") do set PROJ_NAME=%%~ni
-REM 获取代码根目录
-cd ../..
-set ROOT_PATH=%cd:\=/%
-set TOP_PATH=%cd%
-set BUILD_PATH=%TOP_PATH%\build\%PROJ_NAME%\debug
-set HEX_PATH=%TOP_PATH%\hex\%PROJ_NAME%\debug
-if not exist %HEX_PATH% (mkdir %HEX_PATH%)
-if not exist %BUILD_PATH% (mkdir %BUILD_PATH%)
-REM 进入第一个makefile的目录project
-cd %CUR_DIR%/../../compilation
-set BUILD_PATH=%TOP_PATH%\build\%PROJ_NAME%\debug
-if exist %BUILD_PATH%\build_error.log (
-	del %BUILD_PATH%\build_error.log
-)
-make %make_target% 2>%BUILD_PATH%\build_error.log
-if %errorlevel% == 0 (
-    @echo build ok
-) else (
-    type %BUILD_PATH%\build_error.log
-)
-
-REM make all
-
-if not exist %BUILD_PATH%\bootloader.hex (
-    echo bootloader.hex file not exist
-    goto end
-)
-if not exist %BUILD_PATH%\app.hex (
-    echo app.hex file not exist
-    goto end
-)
-if exist %BUILD_PATH%\all.hex (
-    del %BUILD_PATH%\all.hex
-
-)
-
-for /f "delims=" %%i in (%BUILD_PATH%\bootloader.hex) do (
-    if "%%i"==":00000001FF" (
-        goto add_bl_done
-    ) else (
-        echo %%i>>%BUILD_PATH%\all.hex
-    )
-)
-:add_bl_done
-type %BUILD_PATH%\app.hex >> %BUILD_PATH%\all.hex
-copy %BUILD_PATH%\bootloader.bin %HEX_PATH%\bootloader.bin
-copy %BUILD_PATH%\app.bin %HEX_PATH%\app.bin
-copy %CUR_DIR%\info.json %HEX_PATH%\info.json
-copy %CUR_DIR%\soc_download.exe %HEX_PATH%\soc_download.exe
-:end
-
-::回到当前项目目录
-cd %CUR_DIR%
-del %HEX_PATH%\LuatOS-SoC_%PROJ_NAME%.soc
-7za.exe a "%HEX_PATH%\LuatOS-SoC_%PROJ_NAME%.soc" "%HEX_PATH%\*.*"
-pause

+ 0 - 73
project/air105/build_release.bat

@@ -1,73 +0,0 @@
-::编译前准备工作
-@echo off
-
-setlocal enabledelayedexpansion
-set line=0
-for /f  %%a in ('wmic cpu get numberofcores') do (
-set /a line+=1
-if !line!==2 set A=%%a
-)
-set /a CPU_LINE=%A%+%A%
-
-set CROSS_TOOL_WIN32_PATH=D:\gcc-mcu
-set CROSS_TOOL_PATH=%CROSS_TOOL_WIN32_PATH:\=/%
-set PATH=%CROSS_TOOL_WIN32_PATH%\bin;%PATH%
-REM debug属性标记
-REM set __DEBUG__=true
-REM 获取项目路径
-set PROJ_DIR=%cd:\=/%
-set CUR_DIR=%cd%
-REM 获取项目名称
-for /f %%i in ("%cd%") do set PROJ_NAME=%%~ni
-REM 获取代码根目录
-cd ../..
-set ROOT_PATH=%cd:\=/%
-set TOP_PATH=%cd%
-REM 进入第一个makefile的目录project
-cd %CUR_DIR%/../../compilation
-set BUILD_PATH=%TOP_PATH%\build\%PROJ_NAME%\release
-set HEX_PATH=%TOP_PATH%\hex\%PROJ_NAME%\release
-if not exist %HEX_PATH% (mkdir %HEX_PATH%)
-make cleanall
-if not exist %BUILD_PATH% (mkdir %BUILD_PATH%)
-make all 2>%BUILD_PATH%\build_error.log
-if %errorlevel% == 0 (
-    @echo build ok
-) else (
-    type %BUILD_PATH%\build_error.log
-)
-REM make all
-
-
-if not exist %BUILD_PATH%\bootloader.hex (
-    echo bootloader.hex file not exist
-    goto end
-)
-if not exist %BUILD_PATH%\app.hex (
-    echo app.hex file not exist
-    goto end
-)
-if exist %BUILD_PATH%\all.hex (
-    del %BUILD_PATH%\all.hex
-
-)
-
-for /f "delims=" %%i in (%BUILD_PATH%\bootloader.hex) do (
-    if "%%i"==":00000001FF" (
-        goto add_bl_done
-    ) else (
-        @echo %%i>>%BUILD_PATH%\all.hex
-    )
-)
-:add_bl_done
-type %BUILD_PATH%\app.hex >> %BUILD_PATH%\all.hex
-copy %BUILD_PATH%\bootloader.bin %HEX_PATH%\bootloader.bin
-copy %BUILD_PATH%\app.bin %HEX_PATH%\app.bin
-copy %CUR_DIR%\info.json %HEX_PATH%\info.json
-copy %CUR_DIR%\soc_download.exe %HEX_PATH%\soc_download.exe
-:end
-::回到当前项目目录
-cd %CUR_DIR%
-del %HEX_PATH%\LuatOS-SoC_%PROJ_NAME%.soc
-7za.exe a "%HEX_PATH%\LuatOS-SoC_%PROJ_NAME%.soc" "%HEX_PATH%\*.*"
-pause

BIN
project/air105/soc_download.exe


+ 6 - 2
xmake.lua

@@ -77,6 +77,8 @@ target("bootloader.elf")
     -- set kind
     set_kind("binary")
     set_targetdir("$(buildir)/out")
+
+    add_defines("__RUN_IN_RAM__")
     -- add deps
     add_files("Third_Party/cm_backtrace/*.c",{public = true})
     --add_files("Third_Party/cm_backtrace/fault_handler/gcc/cmb_fault.S",{public = true})
@@ -100,7 +102,7 @@ target("bootloader.elf")
     add_includedirs("Third_Party/lzma/include",{public = true})
 
     -- add files
-    add_files("bsp/air105/platform/startup_full.s")
+    add_files("bsp/air105/platform/startup_run_in_ram.s")
     add_files("bsp/air105/platform/bl_main.c")
     add_files("bsp/air105/hal/*.c")
     -- add_files("bsp/air105/chip/src/*.c")
@@ -114,8 +116,10 @@ target("bootloader.elf")
 
 	after_build(function(target)
         sdk_dir = target:toolchains()[1]:sdkdir().."/"
-        os.exec(sdk_dir .. "bin/arm-none-eabi-objcopy -O binary --gap-fill=0xff $(buildir)/out/bootloader.elf $(buildir)/out/bootloader.bin")
+        -- os.exec(sdk_dir .. "bin/arm-none-eabi-objcopy -O binary --gap-fill=0xff $(buildir)/out/bootloader.elf $(buildir)/out/bootloader.bin")
         os.exec(sdk_dir .. "bin/arm-none-eabi-objcopy -O ihex $(buildir)/out/bootloader.elf $(buildir)/out/bootloader.hex")
+        os.exec("./project/air105/hex2bin.exe $(buildir)/out/bootloader.hex")
+        
         io.writefile("$(buildir)/out/bootloader.list", os.iorun(sdk_dir .. "bin/arm-none-eabi-objdump -h -S $(buildir)/out/bootloader.elf"))
         io.writefile("$(buildir)/out/bootloader.size", os.iorun(sdk_dir .. "bin/arm-none-eabi-size $(buildir)/out/bootloader.elf"))
         -- os.run(sdk_dir .. "bin/arm-none-eabi-objdump -h -S $(buildir)/out/bootloader.elf > $(buildir)/out/bootloader.list")