瀏覽代碼

update:新的task加载方式,默认开u8g2的12号字体,audio简易api,adc使用时gpio上拉取消

alienwalker 4 年之前
父節點
當前提交
8e989770ce

+ 1 - 1
application/include/luat_conf_bsp.h

@@ -90,7 +90,7 @@
 /**********U8G2&LCD FONT*************/
 // #define USE_U8G2_UNIFONT_SYMBOLS
 #define USE_U8G2_OPPOSANSM12_CHINESE
-#define USE_U8G2_OPPOSANSM16_CHINESE
+//#define USE_U8G2_OPPOSANSM16_CHINESE
 // #define USE_U8G2_OPPOSANSM24_CHINESE
 // #define USE_U8G2_OPPOSANSM32_CHINESE
 /**********LVGL FONT*************/

+ 5 - 0
application/src/luat_adc_air105.c

@@ -36,20 +36,25 @@ int luat_adc_open(int ch, void *args)
         return 0;
     case 1:
         GPIO_Iomux(GPIOC_00, 2);
+        GPIO_PullConfig(GPIOC_00, 0, 0);
         break;
     case 2:
         GPIO_Iomux(GPIOC_01, 2);
+        GPIO_PullConfig(GPIOC_01, 0, 0);
         break;
     case 3:
         return -1;
     case 4:
         GPIO_Iomux(GPIOC_03, 2);
+        GPIO_PullConfig(GPIOC_03, 0, 0);
         break;
     case 5:
         GPIO_Iomux(GPIOC_04, 2);
+        GPIO_PullConfig(GPIOC_04, 0, 0);
         break;
     case 6:
         GPIO_Iomux(GPIOC_05, 2);
+        GPIO_PullConfig(GPIOC_05, 0, 0);
         break;
     default:
         return -1;

+ 12 - 1
application/src/luat_dac_air105.c

@@ -23,6 +23,14 @@
 #include "luat_dac.h"
 #include "app_interface.h"
 
+static int32_t luat_dac_cb(void *pData, void *pParam)
+{
+	uint32_t DAC_ID = pData;
+	HANDLE Mutex = pParam;
+	OS_MutexRelease(Mutex);
+	return 0;
+}
+
 int luat_dac_setup(uint32_t ch, uint32_t freq, uint32_t mode) {
     if (ch != 0)
         return -1;
@@ -35,7 +43,10 @@ int luat_dac_setup(uint32_t ch, uint32_t freq, uint32_t mode) {
 int luat_dac_write(uint32_t ch, uint16_t* buff, size_t len) {
     if (ch != 0)
         return -1;
-    DAC_Send(ch, buff, len, NULL, NULL);
+    HANDLE Mutex = OS_MutexCreate();
+    DAC_Send(ch, buff, len, luat_dac_cb, Mutex);
+    OS_MutexLock(Mutex);
+    OS_MutexDelete(Mutex);
     return 0;
 }
 

+ 5 - 0
bsp/air105/hal/core_adc.c

@@ -229,4 +229,9 @@ uint32_t ADC_GetChannelValue(uint8_t Channel)
 	ADC0->ADC_CR1 = 0;
 	return ((total - max) -min)/(SAMPLE_PER_CH-12);
 }
+
+#ifdef __BUILD_APP__
+INIT_HW_EXPORT(ADC_GlobalInit, "1");
+#endif
+
 #endif

+ 4 - 0
bsp/air105/hal/core_i2c.c

@@ -448,3 +448,7 @@ int32_t I2C_BlockRead(uint8_t I2CID, uint8_t ChipAddress, uint8_t *Reg, uint8_t
 	while(!I2C_WaitResult(I2CID, &Result)) {;}
 	return Result;
 }
+
+#ifdef __BUILD_APP__
+INIT_HW_EXPORT(I2C_GlobalInit, "1");
+#endif

+ 4 - 0
bsp/air105/hal/core_rng.c

@@ -50,3 +50,7 @@ void RNG_GetData(uint32_t Buf[4])
 
 
 }
+
+#ifdef __BUILD_APP__
+INIT_HW_EXPORT(RNG_Init, "1");
+#endif

+ 3 - 0
bsp/air105/hal/core_rtc.c

@@ -126,3 +126,6 @@ uint64_t RTC_GetUTC(void)
 	return curTime;
 }
 
+#ifdef __BUILD_APP__
+INIT_HW_EXPORT(RTC_GlobalInit, "1");
+#endif

+ 0 - 2
bsp/air105/hal/core_spi.c

@@ -788,8 +788,6 @@ int32_t SPI_BlockTransfer(uint8_t SpiID, const uint8_t *TxData, uint8_t *RxData,
 	if (OS_MutexLockWtihTime(prvSPI[SpiID].Sem, Time + 10))
 	{
 		DBG("!!!");
-		DMA_StopStream(prvSPI[SpiID].DMATxStream);
-		DMA_StopStream(prvSPI[SpiID].DMARxStream);
 		SPI_TransferStop(SpiID);
 		prvSPI[SpiID].IsBlockMode = 0;
 		return -1;

+ 1 - 0
bsp/air105/hal/core_timer.c

@@ -333,3 +333,4 @@ void Timer_PrintAll(void)
 	OS_ExitCritical(Critical);
 
 }
+

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

@@ -1925,3 +1925,6 @@ int32_t USB_ExitLatency(HANDLE hUSB, uint8_t Config[6])
 	return -1;
 }
 
+#ifdef __BUILD_APP__
+INIT_DRV_EXPORT(USB_GlobalInit, "0");
+#endif

+ 1 - 0
bsp/air105/include/app_inc.h

@@ -57,6 +57,7 @@ typedef long long           int64_t;
 #include "bget.h"
 #include "core_task.h"
 #include "core_service.h"
+
 #define mallc OS_Malloc
 #define zallc OS_Zalloc
 #define reallc OS_Realloc

+ 1 - 0
bsp/air105/include/bl_inc.h

@@ -50,4 +50,5 @@
 #include "usb_cdc.h"
 
 #include "dev_spiflash.h"
+#include "audio_ll_drv.h"
 #endif

+ 36 - 7
bsp/air105/platform/app_main.c

@@ -26,7 +26,12 @@ static HANDLE prvWDTTimer;
 extern const uint32_t __isr_start_address;
 extern const uint32_t __os_heap_start;
 extern const uint32_t __ram_end;
-
+extern const uint32_t __preinit_fun_array_start;
+extern const uint32_t __preinit_fun_array_end;
+extern const uint32_t __init_fun_array_start;
+extern const uint32_t __init_fun_array_end;
+extern const uint32_t __task_fun_array_start;
+extern const uint32_t __task_fun_array_end;
 const uint32_t __attribute__((section (".app_info")))
     g_CAppInfo[256] =
 {
@@ -124,6 +129,33 @@ static void prvMain_InitHeap(void)
 	bpool((uint32_t)(&__os_heap_start), prvHeapLen);
 }
 
+static void prvTask_Init(void)
+{
+	volatile CommonFun_t *pFun;
+	for(pFun = &__task_fun_array_start; pFun < &__task_fun_array_end; pFun++)
+	{
+		(*pFun)();
+	}
+}
+
+static void prvDrv_Init(void)
+{
+	volatile CommonFun_t *pFun;
+	for(pFun = &__init_fun_array_start; pFun < &__init_fun_array_end; pFun++)
+	{
+		(*pFun)();
+	}
+}
+
+static void prvHW_Init(void)
+{
+	volatile CommonFun_t *pFun;
+	for(pFun = &__preinit_fun_array_start; pFun < &__preinit_fun_array_end; pFun++)
+	{
+		(*pFun)();
+	}
+}
+
 int main(void)
 {
     cm_backtrace_init_ex("air105", "1.0", "v0001", prvSystemReserCtrl);
@@ -135,15 +167,12 @@ int main(void)
 	Uart_GlobalInit();
 	DMA_TakeStream(DMA1_STREAM_1);//for qspi
 	DBG_Init(1);
-	ADC_GlobalInit();
 	Timer_Init();
-	I2C_GlobalInit();
-	RTC_GlobalInit();
-	USB_GlobalInit();
-	RNG_Init();
+	prvHW_Init();
+	prvDrv_Init();
 	gMainWDTEnable = 1;
 	prvWDTTimer = Timer_Create(prvMainWDT, NULL, NULL);
-	Core_ServiceInit();
+	prvTask_Init();
 #ifdef __DEBUG__
 	DBG("APP Build debug %s %s!", __DATE__, __TIME__);
 #else

+ 53 - 0
bsp/air105/test/test_audio.c

@@ -0,0 +1,53 @@
+#include "user.h"
+#include "wave_data.h"
+#define ONCE_READ_LEN	(32 * 1024)
+extern const uint16_t wavData[WAVE_DATA_SIZE];
+static Audio_StreamStruct prvStream;
+//下面模拟从文件读取
+static uint8_t *pBuf;
+static uint32_t TotalLen = WAVE_DATA_SIZE * 2;
+static uint32_t ReadLen;
+static int32_t Audio_TestCB(void *pData, void *pParam)
+{
+	if (pParam == INVALID_HANDLE_VALUE)
+	{
+		DBG("finish!");
+		//在这里通知某个线程所有数据都传输完成,可以停止了,如果是DAC,需要用DAC_Stop来等待彻底停止,或者延迟一小段时间,再用DAC_Stop
+	}
+	if (ReadLen >= TotalLen)
+	{
+		return 0;
+	}
+	//在这里通知某个线程需要获取更多数据
+	if ((TotalLen - ReadLen) > ONCE_READ_LEN)
+	{
+		Audio_WriteRaw(&prvStream, pBuf + ReadLen, ONCE_READ_LEN);
+		ReadLen += ONCE_READ_LEN;
+	}
+	else
+	{
+		Audio_WriteRaw(&prvStream, pBuf + ReadLen, (TotalLen - ReadLen));
+		ReadLen = TotalLen;
+	}
+	return 0;
+}
+
+void Audio_Test(void)
+{
+	prvStream.BitDepth = 16;
+	prvStream.BusType = AUSTREAM_BUS_DAC;
+	prvStream.BusID = 0;
+	prvStream.Format = AUSTREAM_FORMAT_PCM;
+	prvStream.CB = Audio_TestCB;
+	prvStream.ChannelCount = 1;
+	prvStream.SampleRate = SAMPLE_RATE;
+	prvStream.IsDataSigned = 1;
+	DBG("%d", Audio_StartRaw(&prvStream));
+	ReadLen = 0;
+	pBuf = wavData;
+	//内存充足的情况下,可以连续写入2次,第一块发送完成后,会立刻发送第二块, 同时回调让用户输入更多数据
+	Audio_WriteRaw(&prvStream, pBuf, ONCE_READ_LEN);
+	Audio_WriteRaw(&prvStream, pBuf + ONCE_READ_LEN, ONCE_READ_LEN);
+	ReadLen += 2 * ONCE_READ_LEN;
+}
+

+ 0 - 19
bsp/air105/test/test_dac.c

@@ -1,19 +0,0 @@
-#include "user.h"
-#include "wave_data.h"
-extern uint16_t wavData[WAVE_DATA_SIZE/2];
-
-static int DAC_TestCB(void *pData, void *pParam)
-{
-	DBG("%d", DAC_CheckRun((uint32_t)pData));
-	DAC_Send(0, wavData, WAVE_DATA_SIZE/2, DAC_TestCB, 0);
-}
-
-void DAC_Test(void)
-{
-	GPIO_Iomux(GPIOC_00, 2);
-	wave_DataHandle();
-	DAC_DMAInit(0, DAC_TX_DMA_STREAM);
-	DAC_Setup(0, SAMPLE_RATE, 1);
-	DAC_Send(0, wavData, WAVE_DATA_SIZE/2, DAC_TestCB, 0);
-
-}

+ 7 - 7
bsp/air105/test/wave_data.c

@@ -2,7 +2,7 @@
 
 
 
-uint16_t wavData[WAVE_DATA_SIZE/2] =
+const uint16_t wavData[WAVE_DATA_SIZE] =
 {
     0x0011, 0x0019, 0x0007, 0x001b, 0x0007, 0x0019, 0x0011, 0x0001, 0x0019, 0xfff5, 0x0013, 0x0001, 0x000b, 0x0007, 0x000b, 0x0000, 
     0xffff, 0x000b, 0x0001, 0x0013, 0x0011, 0x0007, 0x0000, 0x0001, 0x0011, 0x0011, 0x0001, 0x0011, 0x0000, 0x0011, 0x0001, 0x0001, 
@@ -3244,11 +3244,11 @@ uint16_t wavData[WAVE_DATA_SIZE/2] =
 
 void wave_DataHandle(void)
 {
-    uint32_t i = 0;
-    
-    for (i = 0; i < WAVE_DATA_SIZE/2; i++)
-    {
-        wavData[i] = (wavData[i] + 0x8000) >> 6;
-    }
+//    uint32_t i = 0;
+//
+//    for (i = 0; i < WAVE_DATA_SIZE; i++)
+//    {
+//        wavData[i] = (wavData[i] + 0x8000) >> 6;
+//    }
 }
  

+ 2 - 2
bsp/air105/test/wave_data.h

@@ -4,9 +4,9 @@
 #include <stdint.h>
 
 #define SAMPLE_RATE          22050      /* sample rate��22050Hz */
-#define WAVE_DATA_SIZE       (0x19442)
+#define WAVE_DATA_SIZE       (0x19442 >> 1)
 
-extern uint16_t wavData[WAVE_DATA_SIZE >> 1];
+extern const uint16_t wavData[WAVE_DATA_SIZE];
 
 void wave_DataHandle(void);
 

+ 52 - 0
bsp/audio/include/audio_ll_drv.h

@@ -0,0 +1,52 @@
+#ifndef __AUDIO_LL_DRV_H__
+#define __AUDIO_LL_DRV_H__
+
+typedef enum
+{
+    AUSTREAM_FORMAT_UNKNOWN, ///< placeholder for unknown format
+    AUSTREAM_FORMAT_PCM,     ///< raw PCM data
+    AUSTREAM_FORMAT_WAVPCM,  ///< WAV, PCM inside
+    AUSTREAM_FORMAT_MP3,     ///< MP3
+    AUSTREAM_FORMAT_AMRNB,   ///< AMR-NB
+    AUSTREAM_FORMAT_AMRWB,   ///< AMR_WB
+    AUSTREAM_FORMAT_SBC,     ///< bt SBC
+} auStreamFormat_t;
+
+typedef enum
+{
+    AUSTREAM_BUS_DAC,
+	AUSTREAM_BUS_I2S,
+} auStreamBusType_t;
+
+typedef struct
+{
+	CBFuncEx_t CB;	//pData是自身Audio_StreamStruct指针
+	void *pParam;
+	llist_head DataHead;
+	uint32_t SampleRate;
+	uint8_t BitDepth;
+	uint8_t ChannelCount;	//声道,目前只有1
+	auStreamFormat_t Format;
+	auStreamBusType_t BusType;	//音频总线类型,DAC, IIS之类的
+	uint8_t BusID;		//音频总线ID
+	uint8_t IsDataSigned;	//数据是否是有符号的
+	uint8_t IsHardwareRun;
+	uint8_t IsPause;
+}Audio_StreamStruct;
+
+void Audio_GlobalInit(void);
+/**
+ * @brief 开始播放原始音频流
+ *
+ * @param pStream 原始音频流数据结构, 底层不保存这个结构,需要用户保存
+ * @return =0 成功 < 0失败错误码
+ */
+int32_t Audio_StartRaw(Audio_StreamStruct *pStream);
+
+int32_t Audio_WriteRaw(Audio_StreamStruct *pStream, uint8_t *pByteData, uint32_t ByteLen);
+
+void Audio_Stop(Audio_StreamStruct *pStream);
+
+void Audio_Pause(Audio_StreamStruct *pStream);
+void Audio_Resume(Audio_StreamStruct *pStream);
+#endif

+ 255 - 0
bsp/audio/src/audio_ll_drv.c

@@ -0,0 +1,255 @@
+#include "user.h"
+
+enum
+{
+	AUDIO_STATE_IDLE,
+	AUDIO_STATE_NEED_DATA,
+	AUDIO_STATE_WAIT_PAUSE,
+	AUDIO_STATE_PAUSE,
+};
+
+typedef struct
+{
+	llist_head Node;
+	PV_Union uPV;
+	uint32_t Len;
+}Audio_DataBlockStruct;
+
+typedef struct
+{
+	uint32_t DACOutRMode;
+	uint8_t DACBit;
+}Audio_CtrlStruct;
+
+static Audio_CtrlStruct prvAudio;
+
+static int32_t prvAudio_DACCB(void *pData, void *pParam)
+{
+	Audio_StreamStruct *pStream = (Audio_StreamStruct *)pParam;
+	Audio_DataBlockStruct *OldBlock, *NewBlock;
+	OldBlock = (Audio_DataBlockStruct *)pStream->DataHead.next;
+	llist_del(&OldBlock->Node);
+
+
+	if (!llist_empty(&pStream->DataHead) && !pStream->IsPause)
+	{
+		NewBlock = (Audio_DataBlockStruct *)pStream->DataHead.next;
+		DAC_Send(pStream->BusID, NewBlock->uPV.pu16, NewBlock->Len, prvAudio_DACCB, pParam);
+		pStream->IsHardwareRun = 1;
+	}
+	free(OldBlock->uPV.pu8);
+	free(OldBlock);
+	if (!pStream->IsPause)
+	{
+		pStream->CB(pStream, NULL);
+	}
+	if (llist_empty(&pStream->DataHead))
+	{
+		pStream->IsHardwareRun = 0;
+		pStream->CB(pStream, INVALID_HANDLE_VALUE);
+	}
+	else if (!pStream->IsPause)
+	{
+		if (!pStream->IsHardwareRun)
+		{
+			NewBlock = (Audio_DataBlockStruct *)pStream->DataHead.next;
+			DAC_Send(pStream->BusID, NewBlock->uPV.pu16, NewBlock->Len, prvAudio_DACCB, pParam);
+			pStream->IsHardwareRun = 1;
+		}
+
+	}
+	else
+	{
+		pStream->IsHardwareRun = 0;
+	}
+	return 0;
+}
+
+void Audio_GlobalInit(void)
+{
+	prvAudio.DACOutRMode = 1;
+	prvAudio.DACBit = 10;
+}
+
+int32_t Audio_StartRaw(Audio_StreamStruct *pStream)
+{
+	INIT_LLIST_HEAD(&pStream->DataHead);
+	if (pStream->BitDepth > 16) return -ERROR_PARAM_INVALID;
+	if (pStream->BitDepth < 8) return -ERROR_PARAM_INVALID;
+	switch(pStream->Format)
+	{
+	case AUSTREAM_FORMAT_PCM:
+		break;
+	default:
+		return -ERROR_PARAM_INVALID;
+	}
+	switch(pStream->BusType)
+	{
+	case AUSTREAM_BUS_DAC:
+		GPIO_Iomux(GPIOC_00, 2);
+		GPIO_PullConfig(GPIOC_00, 0, 0);
+		DAC_ForceStop(pStream->BusID);
+		DAC_DMAInit(0, DAC_TX_DMA_STREAM);
+		DAC_Setup(pStream->BusID, pStream->SampleRate, prvAudio.DACOutRMode);
+		pStream->IsHardwareRun = 0;
+		pStream->IsPause = 0;
+		break;
+	default:
+		return -ERROR_PARAM_INVALID;
+	}
+	return ERROR_NONE;
+}
+
+static int32_t prvAudio_RunDAC(Audio_StreamStruct *pStream)
+{
+	Audio_DataBlockStruct *Block = (Audio_DataBlockStruct *)pStream->DataHead.next;
+	if (llist_empty(&pStream->DataHead))
+	{
+		pStream->CB(pStream, NULL);
+	}
+	else
+	{
+		Block = (Audio_DataBlockStruct *)pStream->DataHead.next;
+		DAC_Send(pStream->BusID, Block->uPV.pu16, Block->Len, prvAudio_DACCB, pStream);
+		pStream->IsHardwareRun = 1;
+	}
+	return ERROR_NONE;
+}
+
+static int32_t prvAudio_WriteDACRaw(Audio_StreamStruct *pStream, uint8_t *pByteData, uint32_t ByteLen)
+{
+	uint32_t i;
+	uint32_t DiffBit;
+	Audio_DataBlockStruct *Block = zalloc(sizeof(Audio_DataBlockStruct));
+	if (pStream->BitDepth > 8)
+	{
+		Block->uPV.pu8 = malloc(ByteLen);
+		if (!Block->uPV.pu8)
+		{
+			free(Block);
+			DBG("no mem!");
+			return -ERROR_NO_MEMORY;
+		}
+		memcpy(Block->uPV.pu8, pByteData, ByteLen);
+		Block->Len = ByteLen >> 1;
+		if (pStream->IsDataSigned)
+		{
+			for(i = 0; i < Block->Len; i++)
+			{
+				Block->uPV.pu16[i] += 0x8000;
+			}
+		}
+		if (pStream->BitDepth >= prvAudio.DACBit)
+		{
+			DiffBit = pStream->BitDepth - prvAudio.DACBit;
+			for(i = 0; i < Block->Len; i++)
+			{
+				Block->uPV.pu16[i] = Block->uPV.pu16[i] >> DiffBit;
+			}
+		}
+		else
+		{
+			DiffBit = prvAudio.DACBit - pStream->BitDepth;
+			for(i = 0; i < Block->Len; i++)
+			{
+				Block->uPV.pu16[i] = Block->uPV.pu16[i] << DiffBit;
+			}
+		}
+
+	}
+	else
+	{
+		Block->uPV.pu8 = malloc(ByteLen * 2);
+		if (!Block->uPV.pu8)
+		{
+			free(Block);
+			DBG("no mem!");
+			return -ERROR_NO_MEMORY;
+		}
+		Block->Len = ByteLen;
+		DiffBit = prvAudio.DACBit - 8;
+		if (pStream->IsDataSigned)
+		{
+			for(i = 0; i < Block->Len; i++)
+			{
+				Block->uPV.pu16[i] = ((pByteData[i] + 0x80) & 0x00ff);
+				Block->uPV.pu16[i] <<= DiffBit;
+			}
+		}
+		else
+		{
+			for(i = 0; i < Block->Len; i++)
+			{
+				Block->uPV.pu16[i] = pByteData[i];
+				Block->uPV.pu16[i] <<= DiffBit;
+			}
+		}
+	}
+	uint32_t Critical;
+	Critical = OS_EnterCritical();
+	llist_add_tail(&Block->Node, &pStream->DataHead);
+	OS_ExitCritical(Critical);
+	if (!pStream->IsHardwareRun)
+	{
+		return prvAudio_RunDAC(pStream);
+	}
+	return ERROR_NONE;
+}
+
+int32_t Audio_WriteRaw(Audio_StreamStruct *pStream, uint8_t *pByteData, uint32_t ByteLen)
+{
+	switch(pStream->BusType)
+	{
+	case AUSTREAM_BUS_DAC:
+		return prvAudio_WriteDACRaw(pStream, pByteData, ByteLen);
+	default:
+		return -ERROR_PARAM_INVALID;
+	}
+
+}
+
+static int32_t prvAudio_DeleteData(void *pData, void *pParam)
+{
+	Buffer_Struct *UriBuf = (Buffer_Struct *)pParam;
+	Audio_DataBlockStruct *Block = (Audio_DataBlockStruct *)pData;
+	free(Block->uPV.p);
+	return LIST_DEL;
+}
+
+void Audio_Stop(Audio_StreamStruct *pStream)
+{
+	switch(pStream->BusType)
+	{
+	case AUSTREAM_BUS_DAC:
+		DAC_ForceStop(pStream->BusID);
+		llist_traversal(&pStream->DataHead, prvAudio_DeleteData, NULL);
+		break;
+	default:
+		return;
+	}
+}
+
+void Audio_Pause(Audio_StreamStruct *pStream)
+{
+	pStream->IsPause = 1;
+}
+
+void Audio_Resume(Audio_StreamStruct *pStream)
+{
+	pStream->IsPause = 0;
+	if (!pStream->IsHardwareRun)
+	{
+		switch(pStream->BusType)
+		{
+		case AUSTREAM_BUS_DAC:
+			prvAudio_RunDAC(pStream);
+			break;
+		default:
+			return;
+		}
+	}
+}
+
+#ifdef __BUILD_APP__
+INIT_DRV_EXPORT(Audio_GlobalInit, "0");
+#endif

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

@@ -162,10 +162,33 @@ enum
 #define MIN(X,Y)	(((X) < (Y))?(X):(Y))
 
 typedef void (* TaskFun_t)( void * );
+typedef void (* CommonFun_t)(void);
 typedef void(* CBDataFun_t)(uint8_t *Data, uint32_t Len);
 typedef int32_t(*CBFuncEx_t)(void *pData, void *pParam);
 typedef uint64_t LongInt;
 
+
+
+#define INIT_FUN_EXPORT(fn, location, level) const CommonFun_t __ex_init_##fn __attribute__((section(location level))) = fn
+#define INIT_HW_EXPORT(fn, level) INIT_FUN_EXPORT(fn, ".preinit_fun_array.", level)
+#define INIT_DRV_EXPORT(fn, level) INIT_FUN_EXPORT(fn, ".init_fun_array.", level)
+#define INIT_TASK_EXPORT(fn, level) INIT_FUN_EXPORT(fn, ".task_fun_array.", level)
+
+/* board init routines will be called in board_init() function */
+#define INIT_BOARD_EXPORT(fn)           INIT_EXPORT(fn, "1")
+
+/* pre/device/component/env/app init routines will be called in init_thread */
+/* components pre-initialization (pure software initilization) */
+#define INIT_PREV_EXPORT(fn)            INIT_EXPORT(fn, "2")
+/* device initialization */
+#define INIT_DEVICE_EXPORT(fn)          INIT_EXPORT(fn, "3")
+/* components initialization (dfs, lwip, ...) */
+#define INIT_COMPONENT_EXPORT(fn)       INIT_EXPORT(fn, "4")
+/* environment initialization (mount disk, ...) */
+#define INIT_ENV_EXPORT(fn)             INIT_EXPORT(fn, "5")
+/* appliation initialization (rtgui application etc ...) */
+#define INIT_APP_EXPORT(fn)             INIT_EXPORT(fn, "6")
+
 typedef struct
 {
 	CBFuncEx_t CB;
@@ -192,9 +215,11 @@ typedef struct
 __attribute__((weak)) uint8_t OS_CheckInIrq(void);
 #ifdef __BUILD_OS__
 HANDLE OS_MutexCreate(void);
+HANDLE OS_MutexCreateUnlock(void);
 void OS_MutexLock(HANDLE Sem);
 int32_t OS_MutexLockWtihTime(HANDLE Sem, uint32_t TimeoutMs);
 HANDLE OS_MutexRelease(HANDLE Sem);
+void OS_MutexDelete(HANDLE Sem);
 #endif
 uint32_t OS_EnterCritical(void);
 void OS_ExitCritical(uint32_t Critical);

+ 14 - 1
bsp/common/src/bsp_common.c

@@ -269,9 +269,17 @@ HANDLE OS_MutexCreate(void)
 	return xSemaphoreCreateBinary();
 }
 
+HANDLE OS_MutexCreateUnlock(void)
+{
+	HANDLE Sem = xSemaphoreCreateBinary();
+	xSemaphoreGive(Sem);
+	return Sem;
+}
+
 void OS_MutexLock(HANDLE Sem)
 {
 	xSemaphoreTake(Sem, portMAX_DELAY);
+
 }
 
 int32_t OS_MutexLockWtihTime(HANDLE Sem, uint32_t TimeoutMs)
@@ -303,6 +311,11 @@ HANDLE OS_MutexRelease(HANDLE Sem)
 		xSemaphoreGive(Sem);
 	}
 }
+
+void OS_MutexDelete(HANDLE Sem)
+{
+	vSemaphoreDelete(Sem);
+}
 #endif
 static uint8_t prvOSRunFlag;
 __attribute__((weak)) void OS_SetStartFlag(void)
@@ -1525,7 +1538,7 @@ void *llist_traversal(llist_head *head, CBFuncEx_t cb, void *pData)
 			if (result < 0)
 			{
 				llist_del(del);
-				cb((void *)del, NULL);
+				free(del);
 			}
 		}
 	}

+ 22 - 15
bsp/common/src/core_service.c

@@ -1262,7 +1262,7 @@ static void prvService_Task(void* params)
 	CBDataFun_t CBDataFun;
 	PV_Union uPV;
 	OS_EVENT Event;
-//	InFlash_Test();
+//	Audio_Test();
 	while(1)
 	{
 		Task_GetEventByMS(prvService.ServiceHandle, CORE_EVENT_ID_ANY, &Event, NULL, 0);
@@ -1337,20 +1337,6 @@ static void prvLuatOS_Task(void* params)
 }
 extern void luat_base_init(void);
 
-
-void Core_ServiceInit(void)
-{
-	uint32_t i;
-	prvService.SleepEnable = 0;
-	prvService.HardwareHandle = Task_Create(prvHW_Task, NULL, 4 * 1024, HW_TASK_PRO, "HW task");
-	prvService.ServiceHandle = Task_Create(prvService_Task, NULL, 8 * 1024, SERVICE_TASK_PRO, "Serv task");
-#ifdef __LUATOS__
-
-	prvService.UserHandle = Task_Create(prvLuatOS_Task, NULL, 16*1024, LUATOS_TASK_PRO, "luatos task");
-	luat_base_init();
-#endif
-}
-
 uint32_t Core_LCDDrawCacheLen(void)
 {
 	if (prvService.LCDDrawRequireByte > prvService.LCDDrawDoneByte)
@@ -1473,5 +1459,26 @@ void Core_DebugMem(uint8_t HeapID, const char *FuncName, uint32_t Line)
 	}
 }
 
+void Core_HWTaskInit(void)
+{
+	prvService.HardwareHandle = Task_Create(prvHW_Task, NULL, 4 * 1024, HW_TASK_PRO, "HW task");
+}
+
+void Core_ServiceInit(void)
+{
+	prvService.SleepEnable = 0;
+	prvService.ServiceHandle = Task_Create(prvService_Task, NULL, 8 * 1024, SERVICE_TASK_PRO, "Serv task");
+}
+
+void Core_UserTaskInit(void)
+{
+#ifdef __LUATOS__
+	prvService.UserHandle = Task_Create(prvLuatOS_Task, NULL, 16*1024, LUATOS_TASK_PRO, "luatos task");
+	luat_base_init();
+#endif
+}
 
+INIT_TASK_EXPORT(Core_HWTaskInit, "0");
+INIT_TASK_EXPORT(Core_ServiceInit, "1");
+INIT_TASK_EXPORT(Core_UserTaskInit, "2");
 #endif

+ 29 - 0
project/air105/app.ld

@@ -103,6 +103,35 @@ SECTIONS
         . = ALIGN(4);
     } >FLASH
 
+    .preinit_fun_array :
+    {
+        . = ALIGN(4);
+        __preinit_fun_array_start = .;
+        KEEP (*(SORT(.preinit_fun_array.*)))
+        KEEP (*(.preinit_fun_array*))
+        __preinit_fun_array_end = .;
+        . = ALIGN(4);
+    } > FLASH
+    
+    .init_fun_array :
+    {
+        . = ALIGN(4);
+        __init_fun_array_start = .;
+        KEEP (*(SORT(.init_fun_array.*)))
+        KEEP (*(.init_fun_array*))
+        __init_fun_array_end = .;
+        . = ALIGN(4);
+    } > FLASH
+    
+    .task_fun_array :
+    {
+        . = ALIGN(4);
+        __task_fun_array_start = .;
+        KEEP (*(SORT(.task_fun_array.*)))
+        KEEP (*(.task_fun_array*))
+        __task_fun_array_end = .;
+        . = ALIGN(4);
+    } > FLASH
 
     /* User_heap_stack section, used to check that there is enough "RAM" Ram  type memory left */
     ._user_heap_stack :

+ 31 - 0
project/air105/bl.ld

@@ -94,6 +94,37 @@ SECTIONS
         PROVIDE_HIDDEN (__fini_array_end = .);
         . = ALIGN(4);
     } >FLASH
+    
+    .preinit_fun_array :
+    {
+        . = ALIGN(4);
+        __preinit_fun_array_start = .;
+        KEEP (*(SORT(.preinit_fun_array.*)))
+        KEEP (*(.preinit_fun_array*))
+        __preinit_fun_array_end = .;
+        . = ALIGN(4);
+    } > FLASH
+    
+    .init_fun_array :
+    {
+        . = ALIGN(4);
+        __init_fun_array_start = .;
+        KEEP (*(SORT(.init_fun_array.*)))
+        KEEP (*(.init_fun_array*))
+        __init_fun_array_end = .;
+        . = ALIGN(4);
+    } > FLASH
+    
+    .task_fun_array :
+    {
+        . = ALIGN(4);
+        __task_fun_array_start = .;
+        KEEP (*(SORT(.task_fun_array.*)))
+        KEEP (*(.task_fun_array*))
+        __task_fun_array_end = .;
+        . = ALIGN(4);
+    } > FLASH
+    
     /* User_heap_stack section, used to check that there is enough "RAM" Ram  type memory left */
     ._user_heap_stack :
     {