Преглед изворни кода

update:补充lua_rtos api部分实现

alienwalker пре 1 година
родитељ
комит
46c0708286

+ 468 - 468
application/src/luat_audio_air105.c

@@ -1,468 +1,468 @@
-/*
- * 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.
- */
-
-
-#include "luat_base.h"
-#include "luat_msgbus.h"
-#include "luat_fs.h"
-#include <stdlib.h>
-#include "app_interface.h"
-#include "luat_multimedia.h"
-
-#define LUAT_LOG_TAG "audio"
-#include "luat_log.h"
-
-//#define __DECODE_DEBUG__
-#ifdef __DECODE_DEBUG__
-#define STEP(X)	Stream->DecodeStep=X
-#else
-#define STEP(X)
-#endif
-#define MP3_FRAME_LEN 4 * 1152
-static Audio_StreamStruct prvAudioStream;
-
-int luat_audio_write_blank_raw(uint32_t multimedia_id, uint8_t cnt);
-
-static int32_t luat_audio_wav_decode(void *pData, void *pParam)
-{
-	Audio_StreamStruct *Stream = (Audio_StreamStruct *)pData;
-	while ( (llist_num(&Stream->DataHead) < 3) && !Stream->IsStop)
-	{
-		Stream->FileDataBuffer.Pos = luat_fs_fread(Stream->FileDataBuffer.Data, Stream->FileDataBuffer.MaxLen, 1, Stream->fd);
-		if (Stream->FileDataBuffer.Pos > 0)
-		{
-			if (!Stream->IsStop)
-			{
-				Audio_WriteRaw(Stream, Stream->FileDataBuffer.Data, Stream->FileDataBuffer.Pos, 0);
-			}
-		}
-		else
-		{
-			return 0;
-		}
-	}
-
-
-	return 0;
-}
-
-static int32_t luat_audio_mp3_decode(void *pData, void *pParam)
-{
-	uint32_t pos = 0;
-	int read_len;
-	int result;
-	uint32_t out_len, hz, used;
-	Audio_StreamStruct *Stream = (Audio_StreamStruct *)pData;
-	Stream->AudioDataBuffer.Pos = 0;
-
-	STEP(1);
-	while ((llist_num(&Stream->DataHead) < 4) && (Stream->IsFileNotEnd || Stream->FileDataBuffer.Pos > 2)&& !Stream->IsStop)
-	{
-		STEP(2);
-		while (( Stream->AudioDataBuffer.Pos < (Stream->AudioDataBuffer.MaxLen - MP3_FRAME_LEN * 2) ) && (Stream->IsFileNotEnd || Stream->FileDataBuffer.Pos > 2) && !Stream->IsStop)
-		{
-			STEP(3);
-			if (Stream->FileDataBuffer.Pos < MP3_MAX_CODED_FRAME_SIZE)
-			{
-				if (Stream->IsFileNotEnd)
-				{
-					read_len = luat_fs_fread(Stream->FileDataBuffer.Data + Stream->FileDataBuffer.Pos, MP3_MAX_CODED_FRAME_SIZE, 1, Stream->fd);
-					if (read_len > 0)
-					{
-						Stream->FileDataBuffer.Pos += read_len;
-					}
-					else
-					{
-						Stream->IsFileNotEnd = 0;
-					}
-				}
-			}
-			pos = 0;
-			STEP(4);
-			do
-			{
-				STEP(5);
-				result = mp3_decoder_get_data(pParam, Stream->FileDataBuffer.Data + pos, Stream->FileDataBuffer.Pos - pos,
-						(int16_t *)&Stream->AudioDataBuffer.Data[Stream->AudioDataBuffer.Pos], &out_len, &hz, &used);
-				STEP(6);
-				if (result > 0)
-				{
-					Stream->AudioDataBuffer.Pos += out_len;
-				}
-				pos += used;
-				if (Stream->AudioDataBuffer.Pos >= (Stream->AudioDataBuffer.MaxLen - MP3_FRAME_LEN * 2))
-				{
-					break;
-				}
-			} while ( ((Stream->FileDataBuffer.Pos - pos) >= (MP3_MAX_CODED_FRAME_SIZE * Stream->IsFileNotEnd + 1)) && !Stream->IsStop);
-			STEP(7);
-			OS_BufferRemove(&Stream->FileDataBuffer, pos);
-		}
-		if (!Stream->IsStop)
-		{
-			STEP(8);
-			Audio_WriteRaw(Stream, Stream->AudioDataBuffer.Data, Stream->AudioDataBuffer.Pos, 0);
-			STEP(9);
-		}
-		Stream->AudioDataBuffer.Pos = 0;
-	}
-	STEP(0);
-	return 0;
-}
-
-static int32_t luat_audio_pa_on(void *pData, void *pParam)
-{
-	if (prvAudioStream.UseOutPA)
-	{
-		GPIO_Output(prvAudioStream.PAPin, prvAudioStream.PAOnLevel);
-	}
-}
-
-int32_t luat_audio_decode_run(void *pData, void *pParam)
-{
-	if (!prvAudioStream.IsStop)
-	{
-		prvAudioStream.Decoder(pData, pParam);
-	}
-	if (prvAudioStream.waitRequire)
-	{
-		prvAudioStream.waitRequire--;
-	}
-}
-
-int32_t luat_audio_app_cb(void *pData, void *pParam)
-{
-    rtos_msg_t msg = {0};
-	msg.handler = l_multimedia_raw_handler;
-	msg.arg1 = (pParam == INVALID_HANDLE_VALUE)?LUAT_MULTIMEDIA_CB_AUDIO_DONE:LUAT_MULTIMEDIA_CB_AUDIO_NEED_DATA;
-	msg.arg2 = prvAudioStream.pParam;
-	luat_msgbus_put(&msg, 1);
-	return 0;
-}
-
-int32_t luat_audio_play_cb(void *pData, void *pParam)
-{
-	Audio_StreamStruct *Stream = (Audio_StreamStruct *)pData;
-	if (pParam == INVALID_HANDLE_VALUE)
-	{
-	    rtos_msg_t msg = {0};
-		msg.handler = l_multimedia_raw_handler;
-		msg.arg1 = LUAT_MULTIMEDIA_CB_AUDIO_DONE;
-		msg.arg2 = prvAudioStream.pParam;
-		luat_msgbus_put(&msg, 1);
-	}
-	else
-	{
-		if (!prvAudioStream.IsStop)
-		{
-			prvAudioStream.waitRequire++;
-			if (prvAudioStream.waitRequire > 2)
-			{
-				DBG("%d,%d,%u,%u", prvAudioStream.waitRequire, prvAudioStream.DecodeStep,prvAudioStream.FileDataBuffer.Pos,prvAudioStream.AudioDataBuffer.Pos);
-			}
-			Core_ServiceRunUserAPIWithFile(luat_audio_decode_run, &prvAudioStream, prvAudioStream.CoderParam);
-		}
-	}
-	return 0;
-}
-
-int luat_audio_start_raw(uint8_t multimedia_id, uint8_t audio_format, uint8_t num_channels, uint32_t sample_rate, uint8_t bits_per_sample, uint8_t is_signed)
-{
-	prvAudioStream.pParam = multimedia_id;
-	if (prvAudioStream.fd) {
-		prvAudioStream.CB = luat_audio_play_cb;
-	} else {
-		prvAudioStream.CB = luat_audio_app_cb;
-	}
-
-	prvAudioStream.BitDepth = bits_per_sample;
-	prvAudioStream.BusType = AUSTREAM_BUS_DAC;
-	prvAudioStream.BusID = 0;
-	prvAudioStream.Format = audio_format;
-	prvAudioStream.ChannelCount = num_channels;
-	prvAudioStream.SampleRate = sample_rate;
-	prvAudioStream.IsDataSigned = is_signed;
-	GPIO_Iomux(GPIOC_01, 2);
-	int result = Audio_StartRaw(&prvAudioStream);
-	if (!result)
-	{
-		if (prvAudioStream.DummyAudioTime)
-		{
-			luat_audio_write_blank_raw(multimedia_id, prvAudioStream.DummyAudioTime);
-		}
-		if (prvAudioStream.PADelayTimer)
-		{
-			Timer_StartMS(prvAudioStream.PADelayTimer, prvAudioStream.PADelayTime, 0);
-		}
-	}
-	return result;
-}
-
-int luat_audio_write_blank_raw(uint32_t multimedia_id, uint8_t cnt)
-{
-	uint32_t total = ((prvAudioStream.SampleRate / 10) * prvAudioStream.ChannelCount * (prvAudioStream.BitDepth / 8) );
-	uint8_t *dummy = malloc(total);
-	memset(dummy, 0, total);
-	for(int i = 0 ; i < cnt; i++)
-	{
-		Audio_WriteRaw(&prvAudioStream, dummy, total, 1);
-	}
-	free(dummy);
-	return 0;
-}
-
-int luat_audio_write_raw(uint8_t multimedia_id, uint8_t *data, uint32_t len)
-{
-	if (len)
-		return Audio_WriteRaw(&prvAudioStream, data, len, 0);
-	return -1;
-}
-
-
-int luat_audio_stop_raw(uint8_t multimedia_id)
-{
-	if (prvAudioStream.UseOutPA)
-	{
-		GPIO_Output(prvAudioStream.PAPin, !prvAudioStream.PAOnLevel);
-	}
-	if (prvAudioStream.PADelayTimer)
-	{
-		Timer_Stop(prvAudioStream.PADelayTimer);
-	}
-	Audio_Stop(&prvAudioStream);
-	OS_DeInitBuffer(&prvAudioStream.FileDataBuffer);
-	OS_DeInitBuffer(&prvAudioStream.AudioDataBuffer);
-	if (prvAudioStream.fd)
-	{
-		luat_fs_fclose(prvAudioStream.fd);
-		prvAudioStream.fd = NULL;
-	}
-	if (prvAudioStream.CoderParam)
-	{
-		luat_heap_free(prvAudioStream.CoderParam);
-		prvAudioStream.CoderParam = NULL;
-	}
-	prvAudioStream.IsStop = 0;
-	prvAudioStream.IsPlaying = 0;
-	prvAudioStream.waitRequire = 0;
-
-	return ERROR_NONE;
-}
-
-int luat_audio_pause_raw(uint8_t multimedia_id, uint8_t is_pause)
-{
-	if (is_pause)
-	{
-		Audio_Pause(&prvAudioStream);
-	}
-	else
-	{
-		Audio_Resume(&prvAudioStream);
-	}
-	return ERROR_NONE;
-}
-
-int luat_audio_play_stop(uint8_t multimedia_id)
-{
-	prvAudioStream.IsStop = 1;
-	prvAudioStream.LastError = -1;
-}
-
-uint8_t luat_audio_is_finish(uint8_t multimedia_id)
-{
-	ASSERT(prvAudioStream.waitRequire < 5);
-	return !prvAudioStream.waitRequire;
-}
-
-int luat_audio_play_multi_files(uint8_t multimedia_id, uData_t *info, uint32_t files_num, uint8_t error_stop)
-{
-	return -1;
-}
-
-int luat_audio_play_file(uint8_t multimedia_id, const char *path)
-{
-	if (prvAudioStream.IsPlaying)
-	{
-		luat_audio_stop_raw(multimedia_id);
-	}
-
-	uint32_t jump, i;
-	uint8_t temp[16];
-	void *mp3_decoder;
-	int result;
-	int audio_format = LUAT_MULTIMEDIA_DATA_TYPE_PCM;
-	uint8_t num_channels;
-	uint32_t sample_rate;
-	int bits_per_sample = 16;
-	uint32_t align;
-	int is_signed = 1;
-    size_t len;
-	FILE *fd = luat_fs_fopen(path, "r");
-	if (!fd)
-	{
-		return -1;
-	}
-	luat_fs_fread(temp, 12, 1, fd);
-	if (!memcmp(temp, "ID3", 3) || (temp[0] == 0xff))
-	{
-		if (temp[0] != 0xff)
-		{
-			jump = 0;
-			for(i = 0; i < 4; i++)
-			{
-				jump <<= 7;
-				jump |= temp[6 + i] & 0x7f;
-			}
-	//		LLOGD("jump head %d", jump);
-			luat_fs_fseek(fd, jump, SEEK_SET);
-		}
-		else
-		{
-			luat_fs_fseek(fd, 0, SEEK_SET);
-		}
-		mp3_decoder = mp3_decoder_create();
-		mp3_decoder_init(mp3_decoder);
-		OS_InitBuffer(&prvAudioStream.FileDataBuffer, MP3_FRAME_LEN);
-		prvAudioStream.FileDataBuffer.Pos = luat_fs_fread(prvAudioStream.FileDataBuffer.Data, MP3_FRAME_LEN, 1, fd);
-
-		result = mp3_decoder_get_info(mp3_decoder, prvAudioStream.FileDataBuffer.Data, prvAudioStream.FileDataBuffer.Pos, &sample_rate, &num_channels);
-		if (result)
-		{
-			prvAudioStream.CoderParam = mp3_decoder;
-			mp3_decoder_init(mp3_decoder);
-			len = (num_channels * sample_rate >> 2);	//一次时间为1/16秒
-			OS_ReInitBuffer(&prvAudioStream.AudioDataBuffer, len + MP3_FRAME_LEN * 2);	//防止溢出,需要多一点空间
-			prvAudioStream.Decoder = luat_audio_mp3_decode;
-		}
-		else
-		{
-			luat_heap_free(mp3_decoder);
-		}
-	}
-	else if (!memcmp(temp, "RIFF", 4) || !memcmp(temp + 8, "WAVE", 4))
-	{
-		result = 0;
-		prvAudioStream.CoderParam = NULL;
-		OS_DeInitBuffer(&prvAudioStream.AudioDataBuffer);
-		luat_fs_fread(temp, 8, 1, fd);
-		if (!memcmp(temp, "fmt ", 4))
-		{
-			memcpy(&len, temp + 4, 4);
-			OS_InitBuffer(&prvAudioStream.FileDataBuffer, len);
-			luat_fs_fread(prvAudioStream.FileDataBuffer.Data, len, 1, fd);
-			audio_format = prvAudioStream.FileDataBuffer.Data[0];
-			num_channels = prvAudioStream.FileDataBuffer.Data[2];
-			memcpy(&sample_rate, prvAudioStream.FileDataBuffer.Data + 4, 4);
-			align = prvAudioStream.FileDataBuffer.Data[12];
-			bits_per_sample = prvAudioStream.FileDataBuffer.Data[14];
-			len = ((align * sample_rate) >> 3) & ~(3);	//一次时间为1/8秒
-			OS_ReInitBuffer(&prvAudioStream.FileDataBuffer, len);
-			luat_fs_fread(temp, 8, 1, fd);
-			if (!memcmp(temp, "fact", 4))
-			{
-				memcpy(&len, temp + 4, 4);
-				luat_fs_fseek(fd, len, SEEK_CUR);
-				luat_fs_fread(temp, 8, 1, fd);
-			}
-			if (!memcmp(temp, "data", 4))
-			{
-				result = 1;
-				prvAudioStream.Decoder = luat_audio_wav_decode;
-			}
-		}
-	}
-	else
-	{
-		result = 0;
-	}
-	if (result)
-	{
-		prvAudioStream.fd = fd;
-		result = luat_audio_start_raw(multimedia_id, audio_format, num_channels, sample_rate, bits_per_sample, is_signed);
-		if (!result)
-		{
-			LLOGD("decode %s ok,param,%d,%d,%d,%d,%d,%d,%u,%u", path,multimedia_id, audio_format, num_channels, sample_rate, bits_per_sample, is_signed, prvAudioStream.FileDataBuffer.MaxLen, prvAudioStream.AudioDataBuffer.MaxLen);
-			prvAudioStream.IsPlaying = 1;
-			prvAudioStream.pParam = multimedia_id;
-			prvAudioStream.IsFileNotEnd = 1;
-			prvAudioStream.Decoder(&prvAudioStream, prvAudioStream.CoderParam);
-			prvAudioStream.LastError = 0;
-			if (!llist_num(&prvAudioStream.DataHead))
-			{
-				prvAudioStream.fd = NULL;
-			}
-			else
-			{
-				return 0;
-			}
-
-		}
-		else
-		{
-			prvAudioStream.fd = 0;
-		}
-	}
-	luat_fs_fclose(fd);
-	OS_DeInitBuffer(&prvAudioStream.FileDataBuffer);
-	OS_DeInitBuffer(&prvAudioStream.AudioDataBuffer);
-	if (prvAudioStream.CoderParam)
-	{
-		luat_heap_free(prvAudioStream.CoderParam);
-		prvAudioStream.CoderParam = NULL;
-	}
-	return -1;
-}
-
-void luat_audio_config_pa(uint8_t multimedia_id, uint32_t pin, int level, uint32_t dummy_time_len, uint32_t pa_delay_time)
-{
-	if (pin < GPIO_NONE)
-	{
-		prvAudioStream.PAPin = pin;
-		prvAudioStream.PAOnLevel = level;
-		prvAudioStream.UseOutPA = 1;
-		GPIO_Config(prvAudioStream.PAPin, 0, !prvAudioStream.PAOnLevel);
-	}
-	else
-	{
-		prvAudioStream.UseOutPA = 0;
-	}
-	prvAudioStream.DummyAudioTime = dummy_time_len;
-	prvAudioStream.PADelayTime = pa_delay_time;
-	if (!prvAudioStream.PADelayTimer && prvAudioStream.PADelayTime)
-	{
-		prvAudioStream.PADelayTimer = Timer_Create(luat_audio_pa_on, NULL, NULL);
-	}
-}
-
-void luat_audio_config_dac(uint8_t multimedia_id, int pin, int level, uint32_t dac_off_delay_time)
-{
-
-}
-
-uint16_t luat_audio_vol(uint8_t multimedia_id, uint16_t vol)
-{
-	return 100;
-}
-
-int luat_audio_play_get_last_error(uint8_t multimedia_id)
-{
-	return prvAudioStream.LastError;
-}
+/*
+ * 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.
+ */
+
+
+#include "luat_base.h"
+#include "luat_msgbus.h"
+#include "luat_fs.h"
+#include <stdlib.h>
+#include "app_interface.h"
+#include "luat_multimedia.h"
+
+#define LUAT_LOG_TAG "audio"
+#include "luat_log.h"
+
+//#define __DECODE_DEBUG__
+#ifdef __DECODE_DEBUG__
+#define STEP(X)	Stream->DecodeStep=X
+#else
+#define STEP(X)
+#endif
+#define MP3_FRAME_LEN 4 * 1152
+static Audio_StreamStruct prvAudioStream;
+
+int luat_audio_write_blank_raw(uint32_t multimedia_id, uint8_t cnt);
+
+static int32_t luat_audio_wav_decode(void *pData, void *pParam)
+{
+	Audio_StreamStruct *Stream = (Audio_StreamStruct *)pData;
+	while ( (llist_num(&Stream->DataHead) < 3) && !Stream->IsStop)
+	{
+		Stream->FileDataBuffer.Pos = luat_fs_fread(Stream->FileDataBuffer.Data, Stream->FileDataBuffer.MaxLen, 1, Stream->fd);
+		if (Stream->FileDataBuffer.Pos > 0)
+		{
+			if (!Stream->IsStop)
+			{
+				Audio_WriteRaw(Stream, Stream->FileDataBuffer.Data, Stream->FileDataBuffer.Pos, 0);
+			}
+		}
+		else
+		{
+			return 0;
+		}
+	}
+
+
+	return 0;
+}
+
+static int32_t luat_audio_mp3_decode(void *pData, void *pParam)
+{
+	uint32_t pos = 0;
+	int read_len;
+	int result;
+	uint32_t out_len, hz, used;
+	Audio_StreamStruct *Stream = (Audio_StreamStruct *)pData;
+	Stream->AudioDataBuffer.Pos = 0;
+
+	STEP(1);
+	while ((llist_num(&Stream->DataHead) < 4) && (Stream->IsFileNotEnd || Stream->FileDataBuffer.Pos > 2)&& !Stream->IsStop)
+	{
+		STEP(2);
+		while (( Stream->AudioDataBuffer.Pos < (Stream->AudioDataBuffer.MaxLen - MP3_FRAME_LEN * 2) ) && (Stream->IsFileNotEnd || Stream->FileDataBuffer.Pos > 2) && !Stream->IsStop)
+		{
+			STEP(3);
+			if (Stream->FileDataBuffer.Pos < MP3_MAX_CODED_FRAME_SIZE)
+			{
+				if (Stream->IsFileNotEnd)
+				{
+					read_len = luat_fs_fread(Stream->FileDataBuffer.Data + Stream->FileDataBuffer.Pos, MP3_MAX_CODED_FRAME_SIZE, 1, Stream->fd);
+					if (read_len > 0)
+					{
+						Stream->FileDataBuffer.Pos += read_len;
+					}
+					else
+					{
+						Stream->IsFileNotEnd = 0;
+					}
+				}
+			}
+			pos = 0;
+			STEP(4);
+			do
+			{
+				STEP(5);
+				result = mp3_decoder_get_data(pParam, Stream->FileDataBuffer.Data + pos, Stream->FileDataBuffer.Pos - pos,
+						(int16_t *)&Stream->AudioDataBuffer.Data[Stream->AudioDataBuffer.Pos], &out_len, &hz, &used);
+				STEP(6);
+				if (result > 0)
+				{
+					Stream->AudioDataBuffer.Pos += out_len;
+				}
+				pos += used;
+				if (Stream->AudioDataBuffer.Pos >= (Stream->AudioDataBuffer.MaxLen - MP3_FRAME_LEN * 2))
+				{
+					break;
+				}
+			} while ( ((Stream->FileDataBuffer.Pos - pos) >= (MP3_MAX_CODED_FRAME_SIZE * Stream->IsFileNotEnd + 1)) && !Stream->IsStop);
+			STEP(7);
+			OS_BufferRemove(&Stream->FileDataBuffer, pos);
+		}
+		if (!Stream->IsStop)
+		{
+			STEP(8);
+			Audio_WriteRaw(Stream, Stream->AudioDataBuffer.Data, Stream->AudioDataBuffer.Pos, 0);
+			STEP(9);
+		}
+		Stream->AudioDataBuffer.Pos = 0;
+	}
+	STEP(0);
+	return 0;
+}
+
+static int32_t luat_audio_pa_on(void *pData, void *pParam)
+{
+	if (prvAudioStream.UseOutPA)
+	{
+		GPIO_Output(prvAudioStream.PAPin, prvAudioStream.PAOnLevel);
+	}
+}
+
+int32_t luat_audio_decode_run(void *pData, void *pParam)
+{
+	if (!prvAudioStream.IsStop)
+	{
+		prvAudioStream.Decoder(pData, pParam);
+	}
+	if (prvAudioStream.waitRequire)
+	{
+		prvAudioStream.waitRequire--;
+	}
+}
+
+int32_t luat_audio_app_cb(void *pData, void *pParam)
+{
+    rtos_msg_t msg = {0};
+	msg.handler = l_multimedia_raw_handler;
+	msg.arg1 = (pParam == INVALID_HANDLE_VALUE)?LUAT_MULTIMEDIA_CB_AUDIO_DONE:LUAT_MULTIMEDIA_CB_AUDIO_NEED_DATA;
+	msg.arg2 = prvAudioStream.pParam;
+	luat_msgbus_put(&msg, 1);
+	return 0;
+}
+
+int32_t luat_audio_play_cb(void *pData, void *pParam)
+{
+	Audio_StreamStruct *Stream = (Audio_StreamStruct *)pData;
+	if (pParam == INVALID_HANDLE_VALUE)
+	{
+	    rtos_msg_t msg = {0};
+		msg.handler = l_multimedia_raw_handler;
+		msg.arg1 = LUAT_MULTIMEDIA_CB_AUDIO_DONE;
+		msg.arg2 = prvAudioStream.pParam;
+		luat_msgbus_put(&msg, 1);
+	}
+	else
+	{
+		if (!prvAudioStream.IsStop)
+		{
+			prvAudioStream.waitRequire++;
+			if (prvAudioStream.waitRequire > 2)
+			{
+				DBG("%d,%d,%u,%u", prvAudioStream.waitRequire, prvAudioStream.DecodeStep,prvAudioStream.FileDataBuffer.Pos,prvAudioStream.AudioDataBuffer.Pos);
+			}
+			Core_ServiceRunUserAPIWithFile(luat_audio_decode_run, &prvAudioStream, prvAudioStream.CoderParam);
+		}
+	}
+	return 0;
+}
+
+int luat_audio_start_raw(uint8_t multimedia_id, uint8_t audio_format, uint8_t num_channels, uint32_t sample_rate, uint8_t bits_per_sample, uint8_t is_signed)
+{
+	prvAudioStream.pParam = multimedia_id;
+	if (prvAudioStream.fd) {
+		prvAudioStream.CB = luat_audio_play_cb;
+	} else {
+		prvAudioStream.CB = luat_audio_app_cb;
+	}
+
+	prvAudioStream.BitDepth = bits_per_sample;
+	prvAudioStream.BusType = AUSTREAM_BUS_DAC;
+	prvAudioStream.BusID = 0;
+	prvAudioStream.Format = audio_format;
+	prvAudioStream.ChannelCount = num_channels;
+	prvAudioStream.SampleRate = sample_rate;
+	prvAudioStream.IsDataSigned = is_signed;
+	GPIO_Iomux(GPIOC_01, 2);
+	int result = Audio_StartRaw(&prvAudioStream);
+	if (!result)
+	{
+		if (prvAudioStream.DummyAudioTime)
+		{
+			luat_audio_write_blank_raw(multimedia_id, prvAudioStream.DummyAudioTime);
+		}
+		if (prvAudioStream.PADelayTimer)
+		{
+			Timer_StartMS(prvAudioStream.PADelayTimer, prvAudioStream.PADelayTime, 0);
+		}
+	}
+	return result;
+}
+
+int luat_audio_write_blank_raw(uint32_t multimedia_id, uint8_t cnt)
+{
+	uint32_t total = ((prvAudioStream.SampleRate / 10) * prvAudioStream.ChannelCount * (prvAudioStream.BitDepth / 8) );
+	uint8_t *dummy = malloc(total);
+	memset(dummy, 0, total);
+	for(int i = 0 ; i < cnt; i++)
+	{
+		Audio_WriteRaw(&prvAudioStream, dummy, total, 1);
+	}
+	free(dummy);
+	return 0;
+}
+
+int luat_audio_write_raw(uint8_t multimedia_id, uint8_t *data, uint32_t len)
+{
+	if (len)
+		return Audio_WriteRaw(&prvAudioStream, data, len, 0);
+	return -1;
+}
+
+
+int luat_audio_stop_raw(uint8_t multimedia_id)
+{
+	if (prvAudioStream.UseOutPA)
+	{
+		GPIO_Output(prvAudioStream.PAPin, !prvAudioStream.PAOnLevel);
+	}
+	if (prvAudioStream.PADelayTimer)
+	{
+		Timer_Stop(prvAudioStream.PADelayTimer);
+	}
+	Audio_Stop(&prvAudioStream);
+	OS_DeInitBuffer(&prvAudioStream.FileDataBuffer);
+	OS_DeInitBuffer(&prvAudioStream.AudioDataBuffer);
+	if (prvAudioStream.fd)
+	{
+		luat_fs_fclose(prvAudioStream.fd);
+		prvAudioStream.fd = NULL;
+	}
+	if (prvAudioStream.CoderParam)
+	{
+		luat_heap_free(prvAudioStream.CoderParam);
+		prvAudioStream.CoderParam = NULL;
+	}
+	prvAudioStream.IsStop = 0;
+	prvAudioStream.IsPlaying = 0;
+	prvAudioStream.waitRequire = 0;
+
+	return ERROR_NONE;
+}
+
+int luat_audio_pause_raw(uint8_t multimedia_id, uint8_t is_pause)
+{
+	if (is_pause)
+	{
+		Audio_Pause(&prvAudioStream);
+	}
+	else
+	{
+		Audio_Resume(&prvAudioStream);
+	}
+	return ERROR_NONE;
+}
+
+int luat_audio_play_stop(uint8_t multimedia_id)
+{
+	prvAudioStream.IsStop = 1;
+	prvAudioStream.LastError = -1;
+}
+
+uint8_t luat_audio_is_finish(uint8_t multimedia_id)
+{
+	ASSERT(prvAudioStream.waitRequire < 5);
+	return !prvAudioStream.waitRequire;
+}
+
+int luat_audio_play_multi_files(uint8_t multimedia_id, uData_t *info, uint32_t files_num, uint8_t error_stop)
+{
+	return -1;
+}
+
+int luat_audio_play_file(uint8_t multimedia_id, const char *path)
+{
+	if (prvAudioStream.IsPlaying)
+	{
+		luat_audio_stop_raw(multimedia_id);
+	}
+
+	uint32_t jump, i;
+	uint8_t temp[16];
+	void *mp3_decoder;
+	int result;
+	int audio_format = LUAT_MULTIMEDIA_DATA_TYPE_PCM;
+	uint8_t num_channels;
+	uint32_t sample_rate;
+	int bits_per_sample = 16;
+	uint32_t align;
+	int is_signed = 1;
+    size_t len;
+	FILE *fd = luat_fs_fopen(path, "r");
+	if (!fd)
+	{
+		return -1;
+	}
+	luat_fs_fread(temp, 12, 1, fd);
+	if (!memcmp(temp, "ID3", 3) || (temp[0] == 0xff))
+	{
+		if (temp[0] != 0xff)
+		{
+			jump = 0;
+			for(i = 0; i < 4; i++)
+			{
+				jump <<= 7;
+				jump |= temp[6 + i] & 0x7f;
+			}
+	//		LLOGD("jump head %d", jump);
+			luat_fs_fseek(fd, jump, SEEK_SET);
+		}
+		else
+		{
+			luat_fs_fseek(fd, 0, SEEK_SET);
+		}
+		mp3_decoder = mp3_decoder_create();
+		mp3_decoder_init(mp3_decoder);
+		OS_InitBuffer(&prvAudioStream.FileDataBuffer, MP3_FRAME_LEN);
+		prvAudioStream.FileDataBuffer.Pos = luat_fs_fread(prvAudioStream.FileDataBuffer.Data, MP3_FRAME_LEN, 1, fd);
+
+		result = mp3_decoder_get_info(mp3_decoder, prvAudioStream.FileDataBuffer.Data, prvAudioStream.FileDataBuffer.Pos, &sample_rate, &num_channels);
+		if (result)
+		{
+			prvAudioStream.CoderParam = mp3_decoder;
+			mp3_decoder_init(mp3_decoder);
+			len = (num_channels * sample_rate >> 2);	//一次时间为1/16秒
+			OS_ReInitBuffer(&prvAudioStream.AudioDataBuffer, len + MP3_FRAME_LEN * 2);	//防止溢出,需要多一点空间
+			prvAudioStream.Decoder = luat_audio_mp3_decode;
+		}
+		else
+		{
+			luat_heap_free(mp3_decoder);
+		}
+	}
+	else if (!memcmp(temp, "RIFF", 4) || !memcmp(temp + 8, "WAVE", 4))
+	{
+		result = 0;
+		prvAudioStream.CoderParam = NULL;
+		OS_DeInitBuffer(&prvAudioStream.AudioDataBuffer);
+		luat_fs_fread(temp, 8, 1, fd);
+		if (!memcmp(temp, "fmt ", 4))
+		{
+			memcpy(&len, temp + 4, 4);
+			OS_InitBuffer(&prvAudioStream.FileDataBuffer, len);
+			luat_fs_fread(prvAudioStream.FileDataBuffer.Data, len, 1, fd);
+			audio_format = prvAudioStream.FileDataBuffer.Data[0];
+			num_channels = prvAudioStream.FileDataBuffer.Data[2];
+			memcpy(&sample_rate, prvAudioStream.FileDataBuffer.Data + 4, 4);
+			align = prvAudioStream.FileDataBuffer.Data[12];
+			bits_per_sample = prvAudioStream.FileDataBuffer.Data[14];
+			len = ((align * sample_rate) >> 3) & ~(3);	//一次时间为1/8秒
+			OS_ReInitBuffer(&prvAudioStream.FileDataBuffer, len);
+			luat_fs_fread(temp, 8, 1, fd);
+			if (!memcmp(temp, "fact", 4))
+			{
+				memcpy(&len, temp + 4, 4);
+				luat_fs_fseek(fd, len, SEEK_CUR);
+				luat_fs_fread(temp, 8, 1, fd);
+			}
+			if (!memcmp(temp, "data", 4))
+			{
+				result = 1;
+				prvAudioStream.Decoder = luat_audio_wav_decode;
+			}
+		}
+	}
+	else
+	{
+		result = 0;
+	}
+	if (result)
+	{
+		prvAudioStream.fd = fd;
+		result = luat_audio_start_raw(multimedia_id, audio_format, num_channels, sample_rate, bits_per_sample, is_signed);
+		if (!result)
+		{
+			LLOGD("decode %s ok,param,%d,%d,%d,%d,%d,%d,%u,%u", path,multimedia_id, audio_format, num_channels, sample_rate, bits_per_sample, is_signed, prvAudioStream.FileDataBuffer.MaxLen, prvAudioStream.AudioDataBuffer.MaxLen);
+			prvAudioStream.IsPlaying = 1;
+			prvAudioStream.pParam = multimedia_id;
+			prvAudioStream.IsFileNotEnd = 1;
+			prvAudioStream.Decoder(&prvAudioStream, prvAudioStream.CoderParam);
+			prvAudioStream.LastError = 0;
+			if (!llist_num(&prvAudioStream.DataHead))
+			{
+				prvAudioStream.fd = NULL;
+			}
+			else
+			{
+				return 0;
+			}
+
+		}
+		else
+		{
+			prvAudioStream.fd = 0;
+		}
+	}
+	luat_fs_fclose(fd);
+	OS_DeInitBuffer(&prvAudioStream.FileDataBuffer);
+	OS_DeInitBuffer(&prvAudioStream.AudioDataBuffer);
+	if (prvAudioStream.CoderParam)
+	{
+		luat_heap_free(prvAudioStream.CoderParam);
+		prvAudioStream.CoderParam = NULL;
+	}
+	return -1;
+}
+
+void luat_audio_config_pa(uint8_t multimedia_id, uint32_t pin, int level, uint32_t dummy_time_len, uint32_t pa_delay_time)
+{
+	if (pin < GPIO_NONE)
+	{
+		prvAudioStream.PAPin = pin;
+		prvAudioStream.PAOnLevel = level;
+		prvAudioStream.UseOutPA = 1;
+		GPIO_Config(prvAudioStream.PAPin, 0, !prvAudioStream.PAOnLevel);
+	}
+	else
+	{
+		prvAudioStream.UseOutPA = 0;
+	}
+	prvAudioStream.DummyAudioTime = dummy_time_len;
+	prvAudioStream.PADelayTime = pa_delay_time;
+	if (!prvAudioStream.PADelayTimer && prvAudioStream.PADelayTime)
+	{
+		prvAudioStream.PADelayTimer = Timer_Create(luat_audio_pa_on, NULL, NULL);
+	}
+}
+
+void luat_audio_config_dac(uint8_t multimedia_id, int pin, int level, uint32_t dac_off_delay_time)
+{
+
+}
+
+uint16_t luat_audio_vol(uint8_t multimedia_id, uint16_t vol)
+{
+	return 100;
+}
+
+int luat_audio_play_get_last_error(uint8_t multimedia_id)
+{
+	return prvAudioStream.LastError;
+}

+ 437 - 437
application/src/luat_base_air105.c

@@ -1,437 +1,437 @@
-/*
- * 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.
- */
-
-#include "luat_base.h"
-#include "luat_msgbus.h"
-#include "luat_fs.h"
-#include "luat_timer.h"
-#include "luat_lcd.h"
-#include "time.h"
-#include <stdlib.h>
-
-#include "app_interface.h"
-
-
-#define LUAT_LOG_TAG "base"
-#include "luat_log.h"
-
-#ifdef LUAT_USE_LVGL
-#include "lvgl.h"
-void luat_lv_fs_init(void);
-void lv_bmp_init(void);
-void lv_png_init(void);
-void lv_split_jpeg_init(void);
-#endif
-extern const uint32_t __isr_start_address;
-const uint32_t __attribute__((section (".app_info")))
-    g_CAppInfo[8] =
-{
-	__APP_START_MAGIC__,
-	&__isr_start_address,
-	__BL_VERSION__,
-	__CORE_VERSION__,
-	__FLASH_BASE_ADDR__ + __FLASH_MAX_SIZE__ - FLASH_FS_REGION_SIZE * 1024,
-	__FLASH_BASE_ADDR__ + __FLASH_MAX_SIZE__ - LUAT_FS_SIZE * 1024,
-	0,
-	0,
-};
-
-LUAMOD_API int luaopen_usbapp( lua_State *L );
-
-static const luaL_Reg loadedlibs[] = {
-  {"_G", luaopen_base}, // _G
-  {LUA_LOADLIBNAME, luaopen_package}, // require
-  {LUA_COLIBNAME, luaopen_coroutine}, // coroutine协程库
-  {LUA_TABLIBNAME, luaopen_table},    // table库,操作table类型的数据结构
-  {LUA_IOLIBNAME, luaopen_io},        // io库,操作文件
-  {LUA_OSLIBNAME, luaopen_os},        // os库,已精简
-  {LUA_STRLIBNAME, luaopen_string},   // string库,字符串操作
-  {LUA_MATHLIBNAME, luaopen_math},    // math 数值计算
-  {LUA_UTF8LIBNAME, luaopen_utf8},
-  {LUA_DBLIBNAME, luaopen_debug},     // debug库,已精简
-#ifdef LUAT_USE_DBG
-#ifndef LUAT_USE_SHELL
-#define LUAT_USE_SHELL
-#endif
-  {"dbg",  luaopen_dbg},               // 调试库
-#endif
-#if defined(LUA_COMPAT_BITLIB)
-  {LUA_BITLIBNAME, luaopen_bit32},    // 不太可能启用
-#endif
-// 往下是LuatOS定制的库, 如需精简请仔细测试
-//----------------------------------------------------------------------
-// 核心支撑库, 不可禁用!!
-  {"rtos",    luaopen_rtos},              // rtos底层库, 核心功能是队列和定时器
-  {"log",     luaopen_log},               // 日志库
-  {"timer",   luaopen_timer},             // 延时库
-//-----------------------------------------------------------------------
-// 设备驱动类, 可按实际情况删减. 即使最精简的固件, 也强烈建议保留uart库
-#ifdef LUAT_USE_UART
-  {"uart",    luaopen_uart},              // 串口操作
-#endif
-#ifdef LUAT_USE_GPIO
-  {"gpio",    luaopen_gpio},              // GPIO脚的操作
-#endif
-#ifdef LUAT_USE_I2C
-  {"i2c",     luaopen_i2c},               // I2C操作
-#endif
-#ifdef LUAT_USE_SPI
-  {"spi",     luaopen_spi},               // SPI操作
-#endif
-#ifdef LUAT_USE_ADC
-  {"adc",     luaopen_adc},               // ADC模块
-#endif
-// #ifdef LUAT_USE_SDIO
-//   {"sdio",     luaopen_sdio},             // SDIO模块
-// #endif
-#ifdef LUAT_USE_PWM
-  {"pwm",     luaopen_pwm},               // PWM模块
-#endif
-#ifdef LUAT_USE_WDT
-  {"wdt",     luaopen_wdt},               // watchdog模块
-#endif
-#ifdef LUAT_USE_PM
-  {"pm",      luaopen_pm},                // 电源管理模块
-#endif
-#ifdef LUAT_USE_MCU
-  {"mcu",     luaopen_mcu},               // MCU特有的一些操作
-#endif
-// #ifdef LUAT_USE_HWTIMER
-//   {"hwtimer", luaopen_hwtimer},           // 硬件定时器
-// #endif
-#ifdef LUAT_USE_RTC
-  {"rtc", luaopen_rtc},                   // 实时时钟
-#endif
-  {"pin", luaopen_pin},                   // pin
-#ifdef LUAT_USE_DAC
-  {"dac", luaopen_dac},
-#endif
-#ifdef LUAT_USE_KEYBOARD
-  {"keyboard", luaopen_keyboard},
-#endif
-#ifdef LUAT_USE_OTP
-  {"otp", luaopen_otp},
-#endif
-#ifdef LUAT_USE_CAMERA
-  {"camera", luaopen_camera},
-#endif
-//-----------------------------------------------------------------------
-// 工具库, 按需选用
-#ifdef LUAT_USE_CRYPTO
-  {"crypto",luaopen_crypto},            // 加密和hash模块
-#endif
-#ifdef LUAT_USE_CJSON
-  {"json",    luaopen_cjson},          // json的序列化和反序列化
-#endif
-#ifdef LUAT_USE_ZBUFF
-  {"zbuff",   luaopen_zbuff},             // 像C语言语言操作内存块
-#endif
-#ifdef LUAT_USE_PACK
-  {"pack",    luaopen_pack},              // pack.pack/pack.unpack
-#endif
-#ifdef LUAT_USE_MQTTCORE
-  {"mqttcore",luaopen_mqttcore},          // MQTT 协议封装
-#endif
-#ifdef LUAT_USE_LIBCOAP
-  {"libcoap", luaopen_libcoap},           // 处理COAP消息
-#endif
-#ifdef LUAT_USE_FATFS
-  {"fatfs", luaopen_fatfs},
-#endif
-#ifdef LUAT_USE_LIBGNSS
-  {"libgnss", luaopen_libgnss},           // 处理GNSS定位数据
-#endif
-#ifdef LUAT_USE_FS
-  {"fs",      luaopen_fs},                // 文件系统库,在io库之外再提供一些方法
-#endif
-#ifdef LUAT_USE_SENSOR
-  {"sensor",  luaopen_sensor},            // 传感器库,支持DS18B20
-#endif
-#ifdef LUAT_USE_SFUD
-  {"sfud", luaopen_sfud},              // sfud
-#endif
-#ifdef LUAT_USE_SFD
-  {"sfd",  luaopen_sfd},                
-#endif
-#ifdef LUAT_USE_DISP
-  {"disp",  luaopen_disp},              // OLED显示模块,支持SSD1306
-#endif
-#ifdef LUAT_USE_U8G2
-  {"u8g2", luaopen_u8g2},              // u8g2
-#endif
-
-#ifdef LUAT_USE_EINK
-  {"eink",  luaopen_eink},              // 电子墨水屏,试验阶段
-#endif
-
-#ifdef LUAT_USE_LVGL
-#ifndef LUAT_USE_LCD
-#define LUAT_USE_LCD
-#endif
-  {"lvgl",   luaopen_lvgl},
-#endif
-
-#ifdef LUAT_USE_LCD
-  {"lcd",    luaopen_lcd},
-#endif
-#ifdef LUAT_USE_STATEM
-  {"statem",    luaopen_statem},
-#endif
-#ifdef LUAT_USE_GTFONT
-  {"gtfont",    luaopen_gtfont},
-#endif
-#ifdef LUAT_USE_COREMARK
-  {"coremark", luaopen_coremark},
-#endif
-#ifdef LUAT_USE_FSKV
-  {"fskv", luaopen_fskv},
-// 启用FSKV的时候,自动禁用FDB
-#ifdef LUAT_USE_FDB
-#undef LUAT_USE_FDB
-#endif
-#endif
-#ifdef LUAT_USE_FDB
-  {"fdb", luaopen_fdb},
-#endif
-#ifdef LUAT_USE_ZLIB
-  {"zlib", luaopen_zlib},
-#endif
-#ifdef LUAT_USE_VMX   
-  {"vmx",       luaopen_vmx}, 
-#endif 
-#ifdef LUAT_USE_NES   
-  {"nes", luaopen_nes}, 
-#endif
-#ifdef LUAT_USE_SOFTKB
-  {"softkb", luaopen_softkb}, 
-#endif
-#ifdef LUAT_USE_YMODEM
-  {"ymodem", luaopen_ymodem},
-#endif
-#ifdef LUAT_USE_W5500
-  {"w5500", luaopen_w5500},
-  {"socket", luaopen_socket_adapter},
-  {"mqtt", luaopen_mqtt},
-  {"http", luaopen_http},
-  {"websocket", luaopen_websocket},
-#ifdef LUAT_USE_FTP
-  {"ftp", luaopen_ftp},
-#endif
-#endif
-// #ifdef LUAT_USE_FOTA
-  {"fota", luaopen_fota},
-// #endif
-#ifdef LUAT_USE_LORA
-  {"lora", luaopen_lora},
-#endif
-#ifdef LUAT_USE_LORA2
-  {"lora2", luaopen_lora2},
-#endif
-#ifdef LUAT_USE_FONTS
-  {"fonts", luaopen_fonts},
-#endif
-#ifdef LUAT_USE_MLX90640
-  {"mlx90640", luaopen_mlx90640},
-#endif
-#ifdef LUAT_USE_MINIZ
-  {"miniz", luaopen_miniz},
-#endif
-#ifdef LUAT_USE_IOTAUTH
-  {"iotauth", luaopen_iotauth},
-#endif
-#ifdef LUAT_USE_PROTOBUF
-  {"protobuf", luaopen_protobuf},
-#endif
-#ifdef LUAT_USE_RSA
-  {"rsa", luaopen_rsa},
-#endif
-#ifdef LUAT_USE_USB
-  {"usbapp", luaopen_usbapp},
-#endif
-#ifdef LUAT_USE_MEDIA
-  {"audio", luaopen_multimedia_audio},
-  {"codec", luaopen_multimedia_codec},
-#endif
-#ifdef LUAT_USE_IO_QUEUE
-  {"ioqueue", luaopen_io_queue},
-#endif
-#ifdef LUAT_USE_MAX30102
-  {"max30102", luaopen_max30102},
-#endif
-#ifdef LUAT_USE_GMSSL
-  {"gmssl",  luaopen_gmssl},              // 国密算法
-#endif
-#ifdef LUAT_USE_ICONV
-  {"iconv", luaopen_iconv},
-#endif
-#ifdef LUAT_USE_BIT64
-  {"bit64", luaopen_bit64},
-#endif
-#ifdef LUAT_USE_REPL
-  {"repl", luaopen_repl},
-#endif
-  {NULL, NULL}
-};
-
-
-void luat_lvgl_tick_sleep(uint8_t OnOff);
-// 按不同的rtconfig加载不同的库函数
-void luat_openlibs(lua_State *L) {
-    // 初始化队列服务
-    luat_msgbus_init();
-    //print_list_mem("done>luat_msgbus_init");
-    // 加载系统库
-    const luaL_Reg *lib;
-    /* "require" functions from 'loadedlibs' and set results to global table */
-    for (lib = loadedlibs; lib->func; lib++) {
-        luaL_requiref(L, lib->name, lib->func, 1);
-        lua_pop(L, 1);  /* remove lib */
-    }
-}
-
-void luat_os_reboot(int code) {
-	SystemReset();
-}
-
-uint32_t luat_poweron_reason(void){
-  return 0;
-}
-
-const char* luat_os_bsp(void) {
-    return "AIR105";
-}
-
-void vConfigureTimerForRunTimeStats( void ) {}
-
-/** 设备进入待机模式 */
-void luat_os_standy(int timeout) {
-    return; // nop
-}
-
-void luat_ota_reboot(int timeout_ms) {
-	luat_lvgl_tick_sleep(1);
-  if (timeout_ms > 0)
-    luat_timer_mdelay(timeout_ms);
-  SystemReset();
-}
-
-#ifdef LUAT_USE_LVGL
-#include "app_interface.h"
-#define LVGL_TICK_PERIOD	10
-unsigned int gLVFlashTime;
-static timer_t *lv_timer;
-static uint32_t lvgl_tick_cnt;
-static int luat_lvg_handler(lua_State* L, void* ptr) {
-//	DBG("%u", lv_tick_get());
-	if (lvgl_tick_cnt) lvgl_tick_cnt--;
-    lv_task_handler();
-    return 0;
-}
-static int32_t _lvgl_handler(void *pData, void *pParam) {
-	if (lvgl_tick_cnt < 10)
-	{
-		lvgl_tick_cnt++;
-	    rtos_msg_t msg = {0};
-	    msg.handler = luat_lvg_handler;
-	    luat_msgbus_put(&msg, 0);
-	}
-	return 0;
-}
-void luat_lvgl_tick_sleep(uint8_t OnOff)
-{
-	if (!OnOff)
-	{
-		Timer_StartMS(lv_timer, LVGL_TICK_PERIOD, 1);
-	}
-	else
-	{
-		Timer_Stop(lv_timer);
-	}
-}
-#else
-void luat_lvgl_tick_sleep(uint8_t OnOff)
-{
-
-}
-#endif
-
-void luat_shell_poweron(int _drv);
-
-void luat_base_init(void)
-{
-	luat_vm_pool_init();
-
-#if defined(LUAT_USE_SHELL) || defined(LUAT_USE_REPL)
-  luat_shell_poweron(0);
-#endif
-
-#ifdef LUAT_USE_LVGL
-  gLVFlashTime = 33;
-	lv_init();
-	lv_timer = Timer_Create(_lvgl_handler, NULL, NULL);
-#ifdef __LVGL_SLEEP_ENABLE__
-    luat_lvgl_tick_sleep(1);
-#else
-	Timer_StartMS(lv_timer, LVGL_TICK_PERIOD, 1);
-#endif
-#endif
-}
-
-time_t luat_time(time_t *_Time) {
-  if (_Time != NULL) {
-    *_Time = RTC_GetUTC();
-  }
-  return RTC_GetUTC();
-}
-
-
-static uint32_t cri;
-uint8_t cri_flag;
-static uint8_t disable_all;	//如果设置成1,将关闭总中断,非常危险,谨慎使用
-
-void luat_os_set_cri_all(uint8_t onoff)
-{
-	disable_all = onoff;
-}
-
-//进入临界保护,不可重入
-void luat_os_entry_cri(void) {
-	if (disable_all) {
-		__disable_irq();
-		return;
-	}
-	if (!cri_flag) {
-		cri = OS_EnterCritical();
-		cri_flag = 1;
-	}
-}
-
-//退出临界保护,不可重入
-void luat_os_exit_cri(void) {
-	if (disable_all) {
-		__enable_irq();
-		return;
-	}
-	if (cri_flag) {
-		cri_flag = 0;
-		OS_ExitCritical(cri);
-	}
-}
+/*
+ * 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.
+ */
+
+#include "luat_base.h"
+#include "luat_msgbus.h"
+#include "luat_fs.h"
+#include "luat_timer.h"
+#include "luat_lcd.h"
+#include "time.h"
+#include <stdlib.h>
+
+#include "app_interface.h"
+
+
+#define LUAT_LOG_TAG "base"
+#include "luat_log.h"
+
+#ifdef LUAT_USE_LVGL
+#include "lvgl.h"
+void luat_lv_fs_init(void);
+void lv_bmp_init(void);
+void lv_png_init(void);
+void lv_split_jpeg_init(void);
+#endif
+extern const uint32_t __isr_start_address;
+const uint32_t __attribute__((section (".app_info")))
+    g_CAppInfo[8] =
+{
+	__APP_START_MAGIC__,
+	&__isr_start_address,
+	__BL_VERSION__,
+	__CORE_VERSION__,
+	__FLASH_BASE_ADDR__ + __FLASH_MAX_SIZE__ - FLASH_FS_REGION_SIZE * 1024,
+	__FLASH_BASE_ADDR__ + __FLASH_MAX_SIZE__ - LUAT_FS_SIZE * 1024,
+	0,
+	0,
+};
+
+LUAMOD_API int luaopen_usbapp( lua_State *L );
+
+static const luaL_Reg loadedlibs[] = {
+  {"_G", luaopen_base}, // _G
+  {LUA_LOADLIBNAME, luaopen_package}, // require
+  {LUA_COLIBNAME, luaopen_coroutine}, // coroutine协程库
+  {LUA_TABLIBNAME, luaopen_table},    // table库,操作table类型的数据结构
+  {LUA_IOLIBNAME, luaopen_io},        // io库,操作文件
+  {LUA_OSLIBNAME, luaopen_os},        // os库,已精简
+  {LUA_STRLIBNAME, luaopen_string},   // string库,字符串操作
+  {LUA_MATHLIBNAME, luaopen_math},    // math 数值计算
+  {LUA_UTF8LIBNAME, luaopen_utf8},
+  {LUA_DBLIBNAME, luaopen_debug},     // debug库,已精简
+#ifdef LUAT_USE_DBG
+#ifndef LUAT_USE_SHELL
+#define LUAT_USE_SHELL
+#endif
+  {"dbg",  luaopen_dbg},               // 调试库
+#endif
+#if defined(LUA_COMPAT_BITLIB)
+  {LUA_BITLIBNAME, luaopen_bit32},    // 不太可能启用
+#endif
+// 往下是LuatOS定制的库, 如需精简请仔细测试
+//----------------------------------------------------------------------
+// 核心支撑库, 不可禁用!!
+  {"rtos",    luaopen_rtos},              // rtos底层库, 核心功能是队列和定时器
+  {"log",     luaopen_log},               // 日志库
+  {"timer",   luaopen_timer},             // 延时库
+//-----------------------------------------------------------------------
+// 设备驱动类, 可按实际情况删减. 即使最精简的固件, 也强烈建议保留uart库
+#ifdef LUAT_USE_UART
+  {"uart",    luaopen_uart},              // 串口操作
+#endif
+#ifdef LUAT_USE_GPIO
+  {"gpio",    luaopen_gpio},              // GPIO脚的操作
+#endif
+#ifdef LUAT_USE_I2C
+  {"i2c",     luaopen_i2c},               // I2C操作
+#endif
+#ifdef LUAT_USE_SPI
+  {"spi",     luaopen_spi},               // SPI操作
+#endif
+#ifdef LUAT_USE_ADC
+  {"adc",     luaopen_adc},               // ADC模块
+#endif
+// #ifdef LUAT_USE_SDIO
+//   {"sdio",     luaopen_sdio},             // SDIO模块
+// #endif
+#ifdef LUAT_USE_PWM
+  {"pwm",     luaopen_pwm},               // PWM模块
+#endif
+#ifdef LUAT_USE_WDT
+  {"wdt",     luaopen_wdt},               // watchdog模块
+#endif
+#ifdef LUAT_USE_PM
+  {"pm",      luaopen_pm},                // 电源管理模块
+#endif
+#ifdef LUAT_USE_MCU
+  {"mcu",     luaopen_mcu},               // MCU特有的一些操作
+#endif
+// #ifdef LUAT_USE_HWTIMER
+//   {"hwtimer", luaopen_hwtimer},           // 硬件定时器
+// #endif
+#ifdef LUAT_USE_RTC
+  {"rtc", luaopen_rtc},                   // 实时时钟
+#endif
+  {"pin", luaopen_pin},                   // pin
+#ifdef LUAT_USE_DAC
+  {"dac", luaopen_dac},
+#endif
+#ifdef LUAT_USE_KEYBOARD
+  {"keyboard", luaopen_keyboard},
+#endif
+#ifdef LUAT_USE_OTP
+  {"otp", luaopen_otp},
+#endif
+#ifdef LUAT_USE_CAMERA
+  {"camera", luaopen_camera},
+#endif
+//-----------------------------------------------------------------------
+// 工具库, 按需选用
+#ifdef LUAT_USE_CRYPTO
+  {"crypto",luaopen_crypto},            // 加密和hash模块
+#endif
+#ifdef LUAT_USE_CJSON
+  {"json",    luaopen_cjson},          // json的序列化和反序列化
+#endif
+#ifdef LUAT_USE_ZBUFF
+  {"zbuff",   luaopen_zbuff},             // 像C语言语言操作内存块
+#endif
+#ifdef LUAT_USE_PACK
+  {"pack",    luaopen_pack},              // pack.pack/pack.unpack
+#endif
+#ifdef LUAT_USE_MQTTCORE
+  {"mqttcore",luaopen_mqttcore},          // MQTT 协议封装
+#endif
+#ifdef LUAT_USE_LIBCOAP
+  {"libcoap", luaopen_libcoap},           // 处理COAP消息
+#endif
+#ifdef LUAT_USE_FATFS
+  {"fatfs", luaopen_fatfs},
+#endif
+#ifdef LUAT_USE_LIBGNSS
+  {"libgnss", luaopen_libgnss},           // 处理GNSS定位数据
+#endif
+#ifdef LUAT_USE_FS
+  {"fs",      luaopen_fs},                // 文件系统库,在io库之外再提供一些方法
+#endif
+#ifdef LUAT_USE_SENSOR
+  {"sensor",  luaopen_sensor},            // 传感器库,支持DS18B20
+#endif
+#ifdef LUAT_USE_SFUD
+  {"sfud", luaopen_sfud},              // sfud
+#endif
+#ifdef LUAT_USE_SFD
+  {"sfd",  luaopen_sfd},                
+#endif
+#ifdef LUAT_USE_DISP
+  {"disp",  luaopen_disp},              // OLED显示模块,支持SSD1306
+#endif
+#ifdef LUAT_USE_U8G2
+  {"u8g2", luaopen_u8g2},              // u8g2
+#endif
+
+#ifdef LUAT_USE_EINK
+  {"eink",  luaopen_eink},              // 电子墨水屏,试验阶段
+#endif
+
+#ifdef LUAT_USE_LVGL
+#ifndef LUAT_USE_LCD
+#define LUAT_USE_LCD
+#endif
+  {"lvgl",   luaopen_lvgl},
+#endif
+
+#ifdef LUAT_USE_LCD
+  {"lcd",    luaopen_lcd},
+#endif
+#ifdef LUAT_USE_STATEM
+  {"statem",    luaopen_statem},
+#endif
+#ifdef LUAT_USE_GTFONT
+  {"gtfont",    luaopen_gtfont},
+#endif
+#ifdef LUAT_USE_COREMARK
+  {"coremark", luaopen_coremark},
+#endif
+#ifdef LUAT_USE_FSKV
+  {"fskv", luaopen_fskv},
+// 启用FSKV的时候,自动禁用FDB
+#ifdef LUAT_USE_FDB
+#undef LUAT_USE_FDB
+#endif
+#endif
+#ifdef LUAT_USE_FDB
+  {"fdb", luaopen_fdb},
+#endif
+#ifdef LUAT_USE_ZLIB
+  {"zlib", luaopen_zlib},
+#endif
+#ifdef LUAT_USE_VMX   
+  {"vmx",       luaopen_vmx}, 
+#endif 
+#ifdef LUAT_USE_NES   
+  {"nes", luaopen_nes}, 
+#endif
+#ifdef LUAT_USE_SOFTKB
+  {"softkb", luaopen_softkb}, 
+#endif
+#ifdef LUAT_USE_YMODEM
+  {"ymodem", luaopen_ymodem},
+#endif
+#ifdef LUAT_USE_W5500
+  {"w5500", luaopen_w5500},
+  {"socket", luaopen_socket_adapter},
+  {"mqtt", luaopen_mqtt},
+  {"http", luaopen_http},
+  {"websocket", luaopen_websocket},
+#ifdef LUAT_USE_FTP
+  {"ftp", luaopen_ftp},
+#endif
+#endif
+// #ifdef LUAT_USE_FOTA
+  {"fota", luaopen_fota},
+// #endif
+#ifdef LUAT_USE_LORA
+  {"lora", luaopen_lora},
+#endif
+#ifdef LUAT_USE_LORA2
+  {"lora2", luaopen_lora2},
+#endif
+#ifdef LUAT_USE_FONTS
+  {"fonts", luaopen_fonts},
+#endif
+#ifdef LUAT_USE_MLX90640
+  {"mlx90640", luaopen_mlx90640},
+#endif
+#ifdef LUAT_USE_MINIZ
+  {"miniz", luaopen_miniz},
+#endif
+#ifdef LUAT_USE_IOTAUTH
+  {"iotauth", luaopen_iotauth},
+#endif
+#ifdef LUAT_USE_PROTOBUF
+  {"protobuf", luaopen_protobuf},
+#endif
+#ifdef LUAT_USE_RSA
+  {"rsa", luaopen_rsa},
+#endif
+#ifdef LUAT_USE_USB
+  {"usbapp", luaopen_usbapp},
+#endif
+#ifdef LUAT_USE_MEDIA
+  {"audio", luaopen_multimedia_audio},
+  {"codec", luaopen_multimedia_codec},
+#endif
+#ifdef LUAT_USE_IO_QUEUE
+  {"ioqueue", luaopen_io_queue},
+#endif
+#ifdef LUAT_USE_MAX30102
+  {"max30102", luaopen_max30102},
+#endif
+#ifdef LUAT_USE_GMSSL
+  {"gmssl",  luaopen_gmssl},              // 国密算法
+#endif
+#ifdef LUAT_USE_ICONV
+  {"iconv", luaopen_iconv},
+#endif
+#ifdef LUAT_USE_BIT64
+  {"bit64", luaopen_bit64},
+#endif
+#ifdef LUAT_USE_REPL
+  {"repl", luaopen_repl},
+#endif
+  {NULL, NULL}
+};
+
+
+void luat_lvgl_tick_sleep(uint8_t OnOff);
+// 按不同的rtconfig加载不同的库函数
+void luat_openlibs(lua_State *L) {
+    // 初始化队列服务
+    luat_msgbus_init();
+    //print_list_mem("done>luat_msgbus_init");
+    // 加载系统库
+    const luaL_Reg *lib;
+    /* "require" functions from 'loadedlibs' and set results to global table */
+    for (lib = loadedlibs; lib->func; lib++) {
+        luaL_requiref(L, lib->name, lib->func, 1);
+        lua_pop(L, 1);  /* remove lib */
+    }
+}
+
+void luat_os_reboot(int code) {
+	SystemReset();
+}
+
+uint32_t luat_poweron_reason(void){
+  return 0;
+}
+
+const char* luat_os_bsp(void) {
+    return "AIR105";
+}
+
+void vConfigureTimerForRunTimeStats( void ) {}
+
+/** 设备进入待机模式 */
+void luat_os_standy(int timeout) {
+    return; // nop
+}
+
+void luat_ota_reboot(int timeout_ms) {
+	luat_lvgl_tick_sleep(1);
+  if (timeout_ms > 0)
+    luat_timer_mdelay(timeout_ms);
+  SystemReset();
+}
+
+#ifdef LUAT_USE_LVGL
+#include "app_interface.h"
+#define LVGL_TICK_PERIOD	10
+unsigned int gLVFlashTime;
+static timer_t *lv_timer;
+static uint32_t lvgl_tick_cnt;
+static int luat_lvg_handler(lua_State* L, void* ptr) {
+//	DBG("%u", lv_tick_get());
+	if (lvgl_tick_cnt) lvgl_tick_cnt--;
+    lv_task_handler();
+    return 0;
+}
+static int32_t _lvgl_handler(void *pData, void *pParam) {
+	if (lvgl_tick_cnt < 10)
+	{
+		lvgl_tick_cnt++;
+	    rtos_msg_t msg = {0};
+	    msg.handler = luat_lvg_handler;
+	    luat_msgbus_put(&msg, 0);
+	}
+	return 0;
+}
+void luat_lvgl_tick_sleep(uint8_t OnOff)
+{
+	if (!OnOff)
+	{
+		Timer_StartMS(lv_timer, LVGL_TICK_PERIOD, 1);
+	}
+	else
+	{
+		Timer_Stop(lv_timer);
+	}
+}
+#else
+void luat_lvgl_tick_sleep(uint8_t OnOff)
+{
+
+}
+#endif
+
+void luat_shell_poweron(int _drv);
+
+void luat_base_init(void)
+{
+	luat_vm_pool_init();
+
+#if defined(LUAT_USE_SHELL) || defined(LUAT_USE_REPL)
+  luat_shell_poweron(0);
+#endif
+
+#ifdef LUAT_USE_LVGL
+  gLVFlashTime = 33;
+	lv_init();
+	lv_timer = Timer_Create(_lvgl_handler, NULL, NULL);
+#ifdef __LVGL_SLEEP_ENABLE__
+    luat_lvgl_tick_sleep(1);
+#else
+	Timer_StartMS(lv_timer, LVGL_TICK_PERIOD, 1);
+#endif
+#endif
+}
+
+time_t luat_time(time_t *_Time) {
+  if (_Time != NULL) {
+    *_Time = RTC_GetUTC();
+  }
+  return RTC_GetUTC();
+}
+
+
+static uint32_t cri;
+uint8_t cri_flag;
+static uint8_t disable_all;	//如果设置成1,将关闭总中断,非常危险,谨慎使用
+
+void luat_os_set_cri_all(uint8_t onoff)
+{
+	disable_all = onoff;
+}
+
+//进入临界保护,不可重入
+void luat_os_entry_cri(void) {
+	if (disable_all) {
+		__disable_irq();
+		return;
+	}
+	if (!cri_flag) {
+		cri = OS_EnterCritical();
+		cri_flag = 1;
+	}
+}
+
+//退出临界保护,不可重入
+void luat_os_exit_cri(void) {
+	if (disable_all) {
+		__enable_irq();
+		return;
+	}
+	if (cri_flag) {
+		cri_flag = 0;
+		OS_ExitCritical(cri);
+	}
+}

+ 28 - 28
application/src/luat_flash_air105.c

@@ -1,28 +1,28 @@
-
-#include "app_interface.h"
-#include "luat_base.h"
-#include "luat_flash.h"
-
-#include "luat_log.h"
-#include "luat_timer.h"
-#include "stdio.h"
-#include "luat_ota.h"
-
-#include "core_flash.h"
-
-
-int luat_flash_read(char* buff, size_t addr, size_t len) {
-    if (addr == 0)
-        return 0;
-    memcpy((uint8_t*)addr, buff, len);
-    return len;
-}
-
-int luat_flash_write(char* buff, size_t addr, size_t len) {
-	return Flash_Program( addr, buff, len);
-}
-
-int luat_flash_erase(size_t addr, size_t len) {
-    Flash_Erase(addr, len);
-    return 0;
-}
+
+#include "app_interface.h"
+#include "luat_base.h"
+#include "luat_flash.h"
+
+#include "luat_log.h"
+#include "luat_timer.h"
+#include "stdio.h"
+#include "luat_ota.h"
+
+#include "core_flash.h"
+
+
+int luat_flash_read(char* buff, size_t addr, size_t len) {
+    if (addr == 0)
+        return 0;
+    memcpy((uint8_t*)addr, buff, len);
+    return len;
+}
+
+int luat_flash_write(char* buff, size_t addr, size_t len) {
+	return Flash_Program( addr, buff, len);
+}
+
+int luat_flash_erase(size_t addr, size_t len) {
+    Flash_Erase(addr, len);
+    return 0;
+}

+ 209 - 209
application/src/luat_fs_air105.c

@@ -1,209 +1,209 @@
-/*
- * 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.
- */
-
-#include "app_interface.h"
-#include "luat_base.h"
-#include "luat_fs.h"
-#include "luat_ota.h"
-
-
-struct lfs_config mcu_flash_lfs_cfg;
-struct lfs LFS;
-
-#define LFS_BLOCK_DEVICE_READ_SIZE      (256)
-#define LFS_BLOCK_DEVICE_PROG_SIZE      (__FLASH_PAGE_SIZE__)
-#define LFS_BLOCK_DEVICE_LOOK_AHEAD     (16)
-#define LFS_BLOCK_DEVICE_CACHE_SIZE     (256)
-// 根据头文件的定义, 算出脚本区和文件系统区的绝对地址
-const size_t script_luadb_start_addr = (__FLASH_BASE_ADDR__ + __FLASH_MAX_SIZE__ - FLASH_FS_REGION_SIZE * 1024);
-const size_t lfs_fs_start_addr = (__FLASH_BASE_ADDR__ + __FLASH_MAX_SIZE__ - LUAT_FS_SIZE * 1024);
-static HANDLE lfs_locker;
-static int block_device_read(const struct lfs_config *cfg, lfs_block_t block,
-        lfs_off_t off, void *buffer, lfs_size_t size)
-{
-	uint32_t start_address = block * __FLASH_SECTOR_SIZE__ + off + lfs_fs_start_addr;
-	memcpy(buffer, start_address, size);
-//	DBG("%x, %u", start_address, size);
-//	DBG_HexPrintf(buffer, 16);
-	return LFS_ERR_OK;
-}
-static int block_device_prog(const struct lfs_config *cfg, lfs_block_t block,
-        lfs_off_t off, const void *buffer, lfs_size_t size)
-{
-	int result;
-	uint32_t start_address = block * __FLASH_SECTOR_SIZE__ + off + lfs_fs_start_addr;
-//	DBG("%x", start_address);
-	OS_MutexLock(lfs_locker);
-	if (size & 0x03)
-	{
-		uint32_t len = (size & 0xfc) + 4;
-		DBG("%u not align to 4, change to ", size, len);
-		uint8_t *program_cache = malloc(len);
-		memset(program_cache, 0xff, len);
-		memcpy(program_cache, buffer, size);
-		result = Flash_Program(start_address, program_cache, size);
-		free(program_cache);
-	}
-	else
-	{
-		result = Flash_Program(start_address, buffer, size);
-	}
-	OS_MutexRelease(lfs_locker);
-	return result?LFS_ERR_IO:LFS_ERR_OK;
-}
-
-static int block_device_erase(const struct lfs_config *cfg, lfs_block_t block)
-{
-	uint32_t start_address = block * __FLASH_SECTOR_SIZE__ + lfs_fs_start_addr;
-//	DBG("%x", start_address);
-	OS_MutexLock(lfs_locker);
-	if (Flash_Erase(start_address, __FLASH_SECTOR_SIZE__))
-	{
-		OS_MutexRelease(lfs_locker);
-		return LFS_ERR_IO;
-	}
-	OS_MutexRelease(lfs_locker);
-	return LFS_ERR_OK;
-}
-
-static int block_device_sync(const struct lfs_config *cfg)
-{
-	//DBG_Trace("block_device_sync");
-    return 0;
-}
-
-#define LFS_BLOCK_DEVICE_READ_SIZE      (256)
-#define LFS_BLOCK_DEVICE_PROG_SIZE      (__FLASH_PAGE_SIZE__)
-#define LFS_BLOCK_DEVICE_LOOK_AHEAD     (16)
-#define LFS_BLOCK_DEVICE_CACHE_SIZE     (256)
-
-#ifdef __BUILD_APP__
-//__attribute__ ((aligned (8))) static char lfs_cache_buff[LFS_BLOCK_DEVICE_CACHE_SIZE];
-__attribute__ ((aligned (8))) static char lfs_read_buff[LFS_BLOCK_DEVICE_READ_SIZE];
-__attribute__ ((aligned (8))) static char lfs_prog_buff[LFS_BLOCK_DEVICE_PROG_SIZE];
-__attribute__ ((aligned (8))) static char lfs_lookahead_buff[16];
-#endif
-
-
-void FileSystem_Init(void)
-{
-	struct lfs_config *config = &mcu_flash_lfs_cfg;
-	//DBG_INFO("ID:%02x,%02x,%02x,Size:%uKB", Ctrl->FlashID[0], Ctrl->FlashID[1], Ctrl->FlashID[2], Ctrl->Size);
-	config->context = NULL;
-	config->cache_size = LFS_BLOCK_DEVICE_READ_SIZE;
-	config->prog_size = __FLASH_PAGE_SIZE__;
-	config->block_size = __FLASH_SECTOR_SIZE__;
-	config->read_size = LFS_BLOCK_DEVICE_READ_SIZE;
-	config->block_cycles = 200;
-	config->lookahead_size = LFS_BLOCK_DEVICE_LOOK_AHEAD;
-	//config->block_count = (Ctrl->Size / 4) - __CORE_FLASH_SECTOR_NUM__ - __SCRIPT_FLASH_SECTOR_NUM__;
-	config->block_count = 512 / 4 ;
-	config->name_max = 63;
-	config->read = block_device_read;
-	config->prog = block_device_prog;
-	config->erase = block_device_erase;
-	config->sync  = block_device_sync;
-
-	//config->buffer = (void*)lfs_cache_buff;
-	config->read_buffer = (void*)lfs_read_buff;
-	config->prog_buffer = (void*)lfs_prog_buff;
-	config->lookahead_buffer = (void*)lfs_lookahead_buff;
-
-	if (!lfs_locker)
-	{
-		lfs_locker = OS_MutexCreateUnlock();
-	}
-/*
- * 正式加入luatos代码可以开启
- */
-	int re = lfs_mount(&LFS, &mcu_flash_lfs_cfg);
-	if (re) {
-		DBG_INFO("lfs, mount fail=%d", re);
-		re = lfs_format(&LFS, &mcu_flash_lfs_cfg);
-		if (re) {
-			DBG_INFO("lfs, format fail=%d", re);
-		}
-		else {
-			lfs_mount(&LFS, &mcu_flash_lfs_cfg);
-		}
-	}
-}
-
-extern const struct luat_vfs_filesystem vfs_fs_lfs2;
-extern const struct luat_vfs_filesystem vfs_fs_luadb;
-extern const struct luat_vfs_filesystem vfs_fs_ram;
-extern size_t luat_luadb_act_size;
-
-#ifdef LUAT_USE_VFS_INLINE_LIB
-//extern const char luadb_inline[];
-// extern const char luadb_inline_sys[];
-#endif
-
-int luat_fs_init(void) {
-	FileSystem_Init();
-	#ifdef LUAT_USE_FS_VFS
-	// vfs进行必要的初始化
-	luat_vfs_init(NULL);
-
-	// 注册vfs for posix 实现
-	luat_vfs_reg(&vfs_fs_lfs2);
-	luat_vfs_reg(&vfs_fs_luadb);
-	// 指向3M + 512k的littefs 文件区
-	luat_fs_conf_t conf = {
-		.busname = (char*)&LFS,
-		.type = "lfs2",
-		.filesystem = "lfs2",
-		.mount_point = "",
-	};
-	luat_fs_mount(&conf);
-
-    luat_vfs_reg(&vfs_fs_ram);
-    luat_fs_conf_t conf3 = {
-		.busname = NULL,
-		.type = "ram",
-		.filesystem = "ram",
-		.mount_point = "/ram/"
-	};
-	luat_fs_mount(&conf3);
-
-	// 指向3M 的脚本区, luadb格式
-	luat_fs_conf_t conf2 = {
-		.busname = (char*)script_luadb_start_addr,
-		.type = "luadb",
-		.filesystem = "luadb",
-		.mount_point = "/luadb/",
-	};
-	luat_luadb_act_size = LUAT_SCRIPT_SIZE;
-	#ifdef LUAT_USE_FSKV
-	luat_luadb_act_size -= 64 * 1024;
-	#endif
-	luat_fs_mount(&conf2);
-	// #endif
-	#endif
-
-	#ifdef LUAT_USE_LVGL
-	luat_lv_fs_init();
-	//lv_bmp_init();
-	lv_png_init();
-	lv_split_jpeg_init();
-	#endif
-	return 0;
-}
+/*
+ * 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.
+ */
+
+#include "app_interface.h"
+#include "luat_base.h"
+#include "luat_fs.h"
+#include "luat_ota.h"
+
+
+struct lfs_config mcu_flash_lfs_cfg;
+struct lfs LFS;
+
+#define LFS_BLOCK_DEVICE_READ_SIZE      (256)
+#define LFS_BLOCK_DEVICE_PROG_SIZE      (__FLASH_PAGE_SIZE__)
+#define LFS_BLOCK_DEVICE_LOOK_AHEAD     (16)
+#define LFS_BLOCK_DEVICE_CACHE_SIZE     (256)
+// 根据头文件的定义, 算出脚本区和文件系统区的绝对地址
+const size_t script_luadb_start_addr = (__FLASH_BASE_ADDR__ + __FLASH_MAX_SIZE__ - FLASH_FS_REGION_SIZE * 1024);
+const size_t lfs_fs_start_addr = (__FLASH_BASE_ADDR__ + __FLASH_MAX_SIZE__ - LUAT_FS_SIZE * 1024);
+static HANDLE lfs_locker;
+static int block_device_read(const struct lfs_config *cfg, lfs_block_t block,
+        lfs_off_t off, void *buffer, lfs_size_t size)
+{
+	uint32_t start_address = block * __FLASH_SECTOR_SIZE__ + off + lfs_fs_start_addr;
+	memcpy(buffer, start_address, size);
+//	DBG("%x, %u", start_address, size);
+//	DBG_HexPrintf(buffer, 16);
+	return LFS_ERR_OK;
+}
+static int block_device_prog(const struct lfs_config *cfg, lfs_block_t block,
+        lfs_off_t off, const void *buffer, lfs_size_t size)
+{
+	int result;
+	uint32_t start_address = block * __FLASH_SECTOR_SIZE__ + off + lfs_fs_start_addr;
+//	DBG("%x", start_address);
+	OS_MutexLock(lfs_locker);
+	if (size & 0x03)
+	{
+		uint32_t len = (size & 0xfc) + 4;
+		DBG("%u not align to 4, change to ", size, len);
+		uint8_t *program_cache = malloc(len);
+		memset(program_cache, 0xff, len);
+		memcpy(program_cache, buffer, size);
+		result = Flash_Program(start_address, program_cache, size);
+		free(program_cache);
+	}
+	else
+	{
+		result = Flash_Program(start_address, buffer, size);
+	}
+	OS_MutexRelease(lfs_locker);
+	return result?LFS_ERR_IO:LFS_ERR_OK;
+}
+
+static int block_device_erase(const struct lfs_config *cfg, lfs_block_t block)
+{
+	uint32_t start_address = block * __FLASH_SECTOR_SIZE__ + lfs_fs_start_addr;
+//	DBG("%x", start_address);
+	OS_MutexLock(lfs_locker);
+	if (Flash_Erase(start_address, __FLASH_SECTOR_SIZE__))
+	{
+		OS_MutexRelease(lfs_locker);
+		return LFS_ERR_IO;
+	}
+	OS_MutexRelease(lfs_locker);
+	return LFS_ERR_OK;
+}
+
+static int block_device_sync(const struct lfs_config *cfg)
+{
+	//DBG_Trace("block_device_sync");
+    return 0;
+}
+
+#define LFS_BLOCK_DEVICE_READ_SIZE      (256)
+#define LFS_BLOCK_DEVICE_PROG_SIZE      (__FLASH_PAGE_SIZE__)
+#define LFS_BLOCK_DEVICE_LOOK_AHEAD     (16)
+#define LFS_BLOCK_DEVICE_CACHE_SIZE     (256)
+
+#ifdef __BUILD_APP__
+//__attribute__ ((aligned (8))) static char lfs_cache_buff[LFS_BLOCK_DEVICE_CACHE_SIZE];
+__attribute__ ((aligned (8))) static char lfs_read_buff[LFS_BLOCK_DEVICE_READ_SIZE];
+__attribute__ ((aligned (8))) static char lfs_prog_buff[LFS_BLOCK_DEVICE_PROG_SIZE];
+__attribute__ ((aligned (8))) static char lfs_lookahead_buff[16];
+#endif
+
+
+void FileSystem_Init(void)
+{
+	struct lfs_config *config = &mcu_flash_lfs_cfg;
+	//DBG_INFO("ID:%02x,%02x,%02x,Size:%uKB", Ctrl->FlashID[0], Ctrl->FlashID[1], Ctrl->FlashID[2], Ctrl->Size);
+	config->context = NULL;
+	config->cache_size = LFS_BLOCK_DEVICE_READ_SIZE;
+	config->prog_size = __FLASH_PAGE_SIZE__;
+	config->block_size = __FLASH_SECTOR_SIZE__;
+	config->read_size = LFS_BLOCK_DEVICE_READ_SIZE;
+	config->block_cycles = 200;
+	config->lookahead_size = LFS_BLOCK_DEVICE_LOOK_AHEAD;
+	//config->block_count = (Ctrl->Size / 4) - __CORE_FLASH_SECTOR_NUM__ - __SCRIPT_FLASH_SECTOR_NUM__;
+	config->block_count = 512 / 4 ;
+	config->name_max = 63;
+	config->read = block_device_read;
+	config->prog = block_device_prog;
+	config->erase = block_device_erase;
+	config->sync  = block_device_sync;
+
+	//config->buffer = (void*)lfs_cache_buff;
+	config->read_buffer = (void*)lfs_read_buff;
+	config->prog_buffer = (void*)lfs_prog_buff;
+	config->lookahead_buffer = (void*)lfs_lookahead_buff;
+
+	if (!lfs_locker)
+	{
+		lfs_locker = OS_MutexCreateUnlock();
+	}
+/*
+ * 正式加入luatos代码可以开启
+ */
+	int re = lfs_mount(&LFS, &mcu_flash_lfs_cfg);
+	if (re) {
+		DBG_INFO("lfs, mount fail=%d", re);
+		re = lfs_format(&LFS, &mcu_flash_lfs_cfg);
+		if (re) {
+			DBG_INFO("lfs, format fail=%d", re);
+		}
+		else {
+			lfs_mount(&LFS, &mcu_flash_lfs_cfg);
+		}
+	}
+}
+
+extern const struct luat_vfs_filesystem vfs_fs_lfs2;
+extern const struct luat_vfs_filesystem vfs_fs_luadb;
+extern const struct luat_vfs_filesystem vfs_fs_ram;
+extern size_t luat_luadb_act_size;
+
+#ifdef LUAT_USE_VFS_INLINE_LIB
+//extern const char luadb_inline[];
+// extern const char luadb_inline_sys[];
+#endif
+
+int luat_fs_init(void) {
+	FileSystem_Init();
+	#ifdef LUAT_USE_FS_VFS
+	// vfs进行必要的初始化
+	luat_vfs_init(NULL);
+
+	// 注册vfs for posix 实现
+	luat_vfs_reg(&vfs_fs_lfs2);
+	luat_vfs_reg(&vfs_fs_luadb);
+	// 指向3M + 512k的littefs 文件区
+	luat_fs_conf_t conf = {
+		.busname = (char*)&LFS,
+		.type = "lfs2",
+		.filesystem = "lfs2",
+		.mount_point = "",
+	};
+	luat_fs_mount(&conf);
+
+    luat_vfs_reg(&vfs_fs_ram);
+    luat_fs_conf_t conf3 = {
+		.busname = NULL,
+		.type = "ram",
+		.filesystem = "ram",
+		.mount_point = "/ram/"
+	};
+	luat_fs_mount(&conf3);
+
+	// 指向3M 的脚本区, luadb格式
+	luat_fs_conf_t conf2 = {
+		.busname = (char*)script_luadb_start_addr,
+		.type = "luadb",
+		.filesystem = "luadb",
+		.mount_point = "/luadb/",
+	};
+	luat_luadb_act_size = LUAT_SCRIPT_SIZE;
+	#ifdef LUAT_USE_FSKV
+	luat_luadb_act_size -= 64 * 1024;
+	#endif
+	luat_fs_mount(&conf2);
+	// #endif
+	#endif
+
+	#ifdef LUAT_USE_LVGL
+	luat_lv_fs_init();
+	//lv_bmp_init();
+	lv_png_init();
+	lv_split_jpeg_init();
+	#endif
+	return 0;
+}

+ 267 - 267
application/src/luat_io_queue_air105.c

@@ -1,267 +1,267 @@
-/*
- * 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.
- */
-#include "luat_base.h"
-#include "luat_msgbus.h"
-#include "app_interface.h"
-#include "luat_lib_io_queue.h"
-
-#define LUAT_LOG_TAG "ioqueue"
-#include "luat_log.h"
-
-static int32_t luat_io_queue_done_cb(void *pData, void *pParam)
-{
-	rtos_msg_t msg;
-	msg.handler = l_io_queue_done_handler;
-	msg.ptr = pParam;
-	luat_msgbus_put(&msg, 1);
-	return 0;
-}
-
-static int32_t __FUNC_IN_RAM__ luat_io_queue_dummy_cb(void *pData, void *pParam)
-{
-	return 0;
-}
-
-static int32_t __FUNC_IN_RAM__ luat_io_queue_capture_cb(void *pData, void *pParam)
-{
-	rtos_msg_t msg;
-	uint64_t tick = GetSysTick();
-	msg.handler = l_io_queue_capture_handler;
-	msg.ptr = ((uint32_t)pData << 8) | GPIO_Input(pData);
-	msg.arg1 = (tick >> 32) & 0xffffffff;
-	msg.arg2 = tick & 0xffffffff;
-	luat_msgbus_put(&msg, 1);
-	return 0;
-}
-
-void luat_io_queue_init(uint8_t hw_timer_id, uint32_t cmd_cnt, uint32_t repeat_cnt)
-{
-	if (hw_timer_id >= HW_TIMER_MAX) return;
-	HWTimer_InitOperationQueue(hw_timer_id, cmd_cnt, repeat_cnt, luat_io_queue_done_cb, hw_timer_id);
-}
-
-void luat_io_queue_start(uint8_t hw_timer_id)
-{
-	if (hw_timer_id >= HW_TIMER_MAX) return;
-	HWTimer_StartOperationQueue(hw_timer_id);
-}
-
-void luat_io_queue_stop(uint8_t hw_timer_id, uint32_t *repeat_cnt, uint32_t *cmd_cnt)
-{
-	if (hw_timer_id >= HW_TIMER_MAX) return;
-	HWTimer_Stop(hw_timer_id);
-	HWTimer_GetResultOperationInfo(hw_timer_id, repeat_cnt, cmd_cnt);
-}
-
-
-void luat_io_queue_clear(uint8_t hw_timer_id)
-{
-	if (hw_timer_id >= HW_TIMER_MAX) return;
-	HWTimer_ClearOperationQueue(hw_timer_id);
-}
-
-void luat_io_queue_release(uint8_t hw_timer_id)
-{
-	if (hw_timer_id >= HW_TIMER_MAX) return;
-	HWTimer_FreeOperationQueue(hw_timer_id);
-}
-
-void luat_io_queue_set_delay(uint8_t hw_timer_id, uint16_t time, uint8_t sub_tick, uint8_t is_continue)
-{
-	if (hw_timer_id >= HW_TIMER_MAX) return;
-	OPQueue_CmdStruct cmd;
-	cmd.CB = NULL;
-	cmd.Operation = is_continue?OP_QUEUE_CMD_CONTINUE_DELAY:OP_QUEUE_CMD_ONE_TIME_DELAY;
-	cmd.PinOrDelay = sub_tick;
-	cmd.uArg.Time = time;
-	HWTimer_AddOperation(hw_timer_id, &cmd);
-}
-
-void luat_io_queue_repeat_delay(uint8_t hw_timer_id)
-{
-	if (hw_timer_id >= HW_TIMER_MAX) return;
-	OPQueue_CmdStruct cmd;
-	cmd.CB = NULL;
-	cmd.Operation = OP_QUEUE_CMD_REPEAT_DELAY;
-	HWTimer_AddOperation(hw_timer_id, &cmd);
-}
-
-void luat_io_queue_add_io_config(uint8_t hw_timer_id, uint8_t pin, uint8_t is_input, uint8_t pull_mode, uint8_t level)
-{
-	if (hw_timer_id >= HW_TIMER_MAX) return;
-	OPQueue_CmdStruct cmd;
-	cmd.CB = NULL;
-	cmd.Operation = is_input?OP_QUEUE_CMD_SET_GPIO_DIR_IN:OP_QUEUE_CMD_SET_GPIO_DIR_OUT;
-	cmd.PinOrDelay = pin;
-	cmd.uArg.IOArg.Level = level;
-	cmd.uArg.IOArg.PullMode = pull_mode;
-	HWTimer_AddOperation(hw_timer_id, &cmd);
-}
-
-
-void luat_io_queue_add_io_out(uint8_t hw_timer_id, uint8_t pin, uint8_t level)
-{
-	if (hw_timer_id >= HW_TIMER_MAX) return;
-	OPQueue_CmdStruct cmd;
-	cmd.CB = NULL;
-	cmd.Operation = OP_QUEUE_CMD_GPIO_OUT;
-	cmd.PinOrDelay = pin;
-	cmd.uArg.IOArg.Level = level;
-	HWTimer_AddOperation(hw_timer_id, &cmd);
-}
-
-void luat_io_queue_add_io_in(uint8_t hw_timer_id, uint8_t pin, CBFuncEx_t CB, void *user_data)
-{
-	if (hw_timer_id >= HW_TIMER_MAX) return;
-	OPQueue_CmdStruct cmd;
-	cmd.CB = CB;
-	cmd.uParam.pParam = user_data;
-	cmd.Operation = CB?OP_QUEUE_CMD_GPIO_IN_CB:OP_QUEUE_CMD_GPIO_IN;
-	cmd.PinOrDelay = pin;
-	HWTimer_AddOperation(hw_timer_id, &cmd);
-}
-
-void luat_io_queue_capture_set(uint8_t hw_timer_id, uint32_t max_tick, uint8_t pin, uint8_t pull_mode, uint8_t irq_mode)
-{
-	if (hw_timer_id >= HW_TIMER_MAX) return;
-	OPQueue_CmdStruct cmd;
-	cmd.CB = NULL;
-	cmd.Operation = OP_QUEUE_CMD_CAPTURE_SET;
-	cmd.PinOrDelay = pin;
-	cmd.uParam.MaxCnt = max_tick;
-	cmd.uArg.ExitArg.ExtiMode = irq_mode;
-	cmd.uArg.ExitArg.PullMode = pull_mode;
-	HWTimer_AddOperation(hw_timer_id, &cmd);
-}
-
-void luat_io_queue_capture(uint8_t hw_timer_id, CBFuncEx_t CB, void *user_data)
-{
-	if (hw_timer_id >= HW_TIMER_MAX) return;
-	OPQueue_CmdStruct cmd;
-	cmd.CB = CB;
-	cmd.PinOrDelay = 0xff;
-	cmd.uParam.pParam = user_data;
-	cmd.Operation = CB?OP_QUEUE_CMD_CAPTURE_CB:OP_QUEUE_CMD_CAPTURE;
-	HWTimer_AddOperation(hw_timer_id, &cmd);
-}
-
-void luat_io_queue_capture_end(uint8_t hw_timer_id, uint8_t pin)
-{
-	if (hw_timer_id >= HW_TIMER_MAX) return;
-	OPQueue_CmdStruct cmd;
-	cmd.CB = NULL;
-	cmd.Operation = OP_QUEUE_CMD_CAPTURE_END;
-	cmd.PinOrDelay = pin;
-	HWTimer_AddOperation(hw_timer_id, &cmd);
-}
-
-void luat_io_queue_end(uint8_t hw_timer_id)
-{
-	if (hw_timer_id >= HW_TIMER_MAX) return;
-	OPQueue_CmdStruct cmd;
-	cmd.Operation = OP_QUEUE_CMD_END;
-	HWTimer_AddOperation(hw_timer_id, &cmd);
-}
-
-uint8_t luat_io_queue_check_done(uint8_t hw_timer_id)
-{
-	if (hw_timer_id >= HW_TIMER_MAX) return 0;
-	return HWTimer_CheckOperationQueueDone(hw_timer_id);
-
-}
-
-int luat_io_queue_get_size(uint8_t hw_timer_id)
-{
-	if (hw_timer_id >= HW_TIMER_MAX) return 0;
-	return HWTimer_GetOperationQueueLen(hw_timer_id);
-
-}
-
-void luat_io_queue_get_data(uint8_t hw_timer_id, uint8_t *input_buff, uint32_t *input_cnt, uint8_t *capture_buff, uint32_t *capture_cnt)
-{
-	if ((hw_timer_id >= HW_TIMER_MAX) || !HWTimer_GetOperationQueue(hw_timer_id))
-	{
-		*input_cnt = 0;
-		*capture_cnt = 0;
-	}
-	else
-	{
-		OPQueue_CmdStruct *Cmd = HWTimer_GetOperationQueue(hw_timer_id);
-		uint32_t len = HWTimer_GetOperationQueueLen(hw_timer_id);
-		uint32_t input_pos = 0;
-		uint32_t capture_pos = 0;
-		uint32_t i;
-		for(i = 0; i < len; i++)
-		{
-			switch(Cmd[i].Operation)
-			{
-			case OP_QUEUE_CMD_GPIO_IN:
-			case OP_QUEUE_CMD_GPIO_IN_CB:
-				input_buff[input_pos * 2] = Cmd[i].PinOrDelay;
-				input_buff[input_pos * 2 + 1] = Cmd[i].uArg.IOArg.Level;
-				input_pos++;
-				break;
-			case OP_QUEUE_CMD_CAPTURE:
-			case OP_QUEUE_CMD_CAPTURE_CB:
-				if (Cmd[i].PinOrDelay >= GPIO_NONE)
-				{
-					len = 0;
-					break;
-				}
-
-				capture_buff[capture_pos * 6] = Cmd[i].PinOrDelay;
-				capture_buff[capture_pos * 6 + 1] = Cmd[i].uArg.IOArg.Level;
-				BytesPutLe32(&capture_buff[capture_pos * 6 + 2], Cmd[i].uParam.MaxCnt);
-				capture_pos++;
-				break;
-			}
-		}
-		*input_cnt = input_pos;
-		*capture_cnt = capture_pos;
-	}
-	return ;
-
-}
-
-void luat_io_queue_capture_start_with_sys_tick(uint8_t pin, uint8_t pull_mode, uint8_t irq_mode)
-{
-	GPIO_PullConfig(pin, pull_mode, (pull_mode > 1)?0:1);
-	GPIO_Config(pin, 1, 0);
-	GPIO_ExtiSetCB(pin, luat_io_queue_capture_cb, NULL);
-	switch(irq_mode)
-	{
-	case OP_QUEUE_CMD_IO_EXTI_BOTH:
-		GPIO_ExtiConfig(pin, 0, 1, 1);
-		break;
-	case OP_QUEUE_CMD_IO_EXTI_UP:
-		GPIO_ExtiConfig(pin, 0, 1, 0);
-		break;
-	case OP_QUEUE_CMD_IO_EXTI_DOWN:
-		GPIO_ExtiConfig(pin, 0, 0, 1);
-		break;
-	}
-}
-
-void luat_io_queue_capture_end_with_sys_tick(uint8_t pin)
-{
-	GPIO_ExtiSetCB(pin, NULL, NULL);
-	GPIO_ExtiConfig(pin, 0, 0, 0);
-}
+/*
+ * 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.
+ */
+#include "luat_base.h"
+#include "luat_msgbus.h"
+#include "app_interface.h"
+#include "luat_lib_io_queue.h"
+
+#define LUAT_LOG_TAG "ioqueue"
+#include "luat_log.h"
+
+static int32_t luat_io_queue_done_cb(void *pData, void *pParam)
+{
+	rtos_msg_t msg;
+	msg.handler = l_io_queue_done_handler;
+	msg.ptr = pParam;
+	luat_msgbus_put(&msg, 1);
+	return 0;
+}
+
+static int32_t __FUNC_IN_RAM__ luat_io_queue_dummy_cb(void *pData, void *pParam)
+{
+	return 0;
+}
+
+static int32_t __FUNC_IN_RAM__ luat_io_queue_capture_cb(void *pData, void *pParam)
+{
+	rtos_msg_t msg;
+	uint64_t tick = GetSysTick();
+	msg.handler = l_io_queue_capture_handler;
+	msg.ptr = ((uint32_t)pData << 8) | GPIO_Input(pData);
+	msg.arg1 = (tick >> 32) & 0xffffffff;
+	msg.arg2 = tick & 0xffffffff;
+	luat_msgbus_put(&msg, 1);
+	return 0;
+}
+
+void luat_io_queue_init(uint8_t hw_timer_id, uint32_t cmd_cnt, uint32_t repeat_cnt)
+{
+	if (hw_timer_id >= HW_TIMER_MAX) return;
+	HWTimer_InitOperationQueue(hw_timer_id, cmd_cnt, repeat_cnt, luat_io_queue_done_cb, hw_timer_id);
+}
+
+void luat_io_queue_start(uint8_t hw_timer_id)
+{
+	if (hw_timer_id >= HW_TIMER_MAX) return;
+	HWTimer_StartOperationQueue(hw_timer_id);
+}
+
+void luat_io_queue_stop(uint8_t hw_timer_id, uint32_t *repeat_cnt, uint32_t *cmd_cnt)
+{
+	if (hw_timer_id >= HW_TIMER_MAX) return;
+	HWTimer_Stop(hw_timer_id);
+	HWTimer_GetResultOperationInfo(hw_timer_id, repeat_cnt, cmd_cnt);
+}
+
+
+void luat_io_queue_clear(uint8_t hw_timer_id)
+{
+	if (hw_timer_id >= HW_TIMER_MAX) return;
+	HWTimer_ClearOperationQueue(hw_timer_id);
+}
+
+void luat_io_queue_release(uint8_t hw_timer_id)
+{
+	if (hw_timer_id >= HW_TIMER_MAX) return;
+	HWTimer_FreeOperationQueue(hw_timer_id);
+}
+
+void luat_io_queue_set_delay(uint8_t hw_timer_id, uint16_t time, uint8_t sub_tick, uint8_t is_continue)
+{
+	if (hw_timer_id >= HW_TIMER_MAX) return;
+	OPQueue_CmdStruct cmd;
+	cmd.CB = NULL;
+	cmd.Operation = is_continue?OP_QUEUE_CMD_CONTINUE_DELAY:OP_QUEUE_CMD_ONE_TIME_DELAY;
+	cmd.PinOrDelay = sub_tick;
+	cmd.uArg.Time = time;
+	HWTimer_AddOperation(hw_timer_id, &cmd);
+}
+
+void luat_io_queue_repeat_delay(uint8_t hw_timer_id)
+{
+	if (hw_timer_id >= HW_TIMER_MAX) return;
+	OPQueue_CmdStruct cmd;
+	cmd.CB = NULL;
+	cmd.Operation = OP_QUEUE_CMD_REPEAT_DELAY;
+	HWTimer_AddOperation(hw_timer_id, &cmd);
+}
+
+void luat_io_queue_add_io_config(uint8_t hw_timer_id, uint8_t pin, uint8_t is_input, uint8_t pull_mode, uint8_t level)
+{
+	if (hw_timer_id >= HW_TIMER_MAX) return;
+	OPQueue_CmdStruct cmd;
+	cmd.CB = NULL;
+	cmd.Operation = is_input?OP_QUEUE_CMD_SET_GPIO_DIR_IN:OP_QUEUE_CMD_SET_GPIO_DIR_OUT;
+	cmd.PinOrDelay = pin;
+	cmd.uArg.IOArg.Level = level;
+	cmd.uArg.IOArg.PullMode = pull_mode;
+	HWTimer_AddOperation(hw_timer_id, &cmd);
+}
+
+
+void luat_io_queue_add_io_out(uint8_t hw_timer_id, uint8_t pin, uint8_t level)
+{
+	if (hw_timer_id >= HW_TIMER_MAX) return;
+	OPQueue_CmdStruct cmd;
+	cmd.CB = NULL;
+	cmd.Operation = OP_QUEUE_CMD_GPIO_OUT;
+	cmd.PinOrDelay = pin;
+	cmd.uArg.IOArg.Level = level;
+	HWTimer_AddOperation(hw_timer_id, &cmd);
+}
+
+void luat_io_queue_add_io_in(uint8_t hw_timer_id, uint8_t pin, CBFuncEx_t CB, void *user_data)
+{
+	if (hw_timer_id >= HW_TIMER_MAX) return;
+	OPQueue_CmdStruct cmd;
+	cmd.CB = CB;
+	cmd.uParam.pParam = user_data;
+	cmd.Operation = CB?OP_QUEUE_CMD_GPIO_IN_CB:OP_QUEUE_CMD_GPIO_IN;
+	cmd.PinOrDelay = pin;
+	HWTimer_AddOperation(hw_timer_id, &cmd);
+}
+
+void luat_io_queue_capture_set(uint8_t hw_timer_id, uint32_t max_tick, uint8_t pin, uint8_t pull_mode, uint8_t irq_mode)
+{
+	if (hw_timer_id >= HW_TIMER_MAX) return;
+	OPQueue_CmdStruct cmd;
+	cmd.CB = NULL;
+	cmd.Operation = OP_QUEUE_CMD_CAPTURE_SET;
+	cmd.PinOrDelay = pin;
+	cmd.uParam.MaxCnt = max_tick;
+	cmd.uArg.ExitArg.ExtiMode = irq_mode;
+	cmd.uArg.ExitArg.PullMode = pull_mode;
+	HWTimer_AddOperation(hw_timer_id, &cmd);
+}
+
+void luat_io_queue_capture(uint8_t hw_timer_id, CBFuncEx_t CB, void *user_data)
+{
+	if (hw_timer_id >= HW_TIMER_MAX) return;
+	OPQueue_CmdStruct cmd;
+	cmd.CB = CB;
+	cmd.PinOrDelay = 0xff;
+	cmd.uParam.pParam = user_data;
+	cmd.Operation = CB?OP_QUEUE_CMD_CAPTURE_CB:OP_QUEUE_CMD_CAPTURE;
+	HWTimer_AddOperation(hw_timer_id, &cmd);
+}
+
+void luat_io_queue_capture_end(uint8_t hw_timer_id, uint8_t pin)
+{
+	if (hw_timer_id >= HW_TIMER_MAX) return;
+	OPQueue_CmdStruct cmd;
+	cmd.CB = NULL;
+	cmd.Operation = OP_QUEUE_CMD_CAPTURE_END;
+	cmd.PinOrDelay = pin;
+	HWTimer_AddOperation(hw_timer_id, &cmd);
+}
+
+void luat_io_queue_end(uint8_t hw_timer_id)
+{
+	if (hw_timer_id >= HW_TIMER_MAX) return;
+	OPQueue_CmdStruct cmd;
+	cmd.Operation = OP_QUEUE_CMD_END;
+	HWTimer_AddOperation(hw_timer_id, &cmd);
+}
+
+uint8_t luat_io_queue_check_done(uint8_t hw_timer_id)
+{
+	if (hw_timer_id >= HW_TIMER_MAX) return 0;
+	return HWTimer_CheckOperationQueueDone(hw_timer_id);
+
+}
+
+int luat_io_queue_get_size(uint8_t hw_timer_id)
+{
+	if (hw_timer_id >= HW_TIMER_MAX) return 0;
+	return HWTimer_GetOperationQueueLen(hw_timer_id);
+
+}
+
+void luat_io_queue_get_data(uint8_t hw_timer_id, uint8_t *input_buff, uint32_t *input_cnt, uint8_t *capture_buff, uint32_t *capture_cnt)
+{
+	if ((hw_timer_id >= HW_TIMER_MAX) || !HWTimer_GetOperationQueue(hw_timer_id))
+	{
+		*input_cnt = 0;
+		*capture_cnt = 0;
+	}
+	else
+	{
+		OPQueue_CmdStruct *Cmd = HWTimer_GetOperationQueue(hw_timer_id);
+		uint32_t len = HWTimer_GetOperationQueueLen(hw_timer_id);
+		uint32_t input_pos = 0;
+		uint32_t capture_pos = 0;
+		uint32_t i;
+		for(i = 0; i < len; i++)
+		{
+			switch(Cmd[i].Operation)
+			{
+			case OP_QUEUE_CMD_GPIO_IN:
+			case OP_QUEUE_CMD_GPIO_IN_CB:
+				input_buff[input_pos * 2] = Cmd[i].PinOrDelay;
+				input_buff[input_pos * 2 + 1] = Cmd[i].uArg.IOArg.Level;
+				input_pos++;
+				break;
+			case OP_QUEUE_CMD_CAPTURE:
+			case OP_QUEUE_CMD_CAPTURE_CB:
+				if (Cmd[i].PinOrDelay >= GPIO_NONE)
+				{
+					len = 0;
+					break;
+				}
+
+				capture_buff[capture_pos * 6] = Cmd[i].PinOrDelay;
+				capture_buff[capture_pos * 6 + 1] = Cmd[i].uArg.IOArg.Level;
+				BytesPutLe32(&capture_buff[capture_pos * 6 + 2], Cmd[i].uParam.MaxCnt);
+				capture_pos++;
+				break;
+			}
+		}
+		*input_cnt = input_pos;
+		*capture_cnt = capture_pos;
+	}
+	return ;
+
+}
+
+void luat_io_queue_capture_start_with_sys_tick(uint8_t pin, uint8_t pull_mode, uint8_t irq_mode)
+{
+	GPIO_PullConfig(pin, pull_mode, (pull_mode > 1)?0:1);
+	GPIO_Config(pin, 1, 0);
+	GPIO_ExtiSetCB(pin, luat_io_queue_capture_cb, NULL);
+	switch(irq_mode)
+	{
+	case OP_QUEUE_CMD_IO_EXTI_BOTH:
+		GPIO_ExtiConfig(pin, 0, 1, 1);
+		break;
+	case OP_QUEUE_CMD_IO_EXTI_UP:
+		GPIO_ExtiConfig(pin, 0, 1, 0);
+		break;
+	case OP_QUEUE_CMD_IO_EXTI_DOWN:
+		GPIO_ExtiConfig(pin, 0, 0, 1);
+		break;
+	}
+}
+
+void luat_io_queue_capture_end_with_sys_tick(uint8_t pin)
+{
+	GPIO_ExtiSetCB(pin, NULL, NULL);
+	GPIO_ExtiConfig(pin, 0, 0, 0);
+}

+ 163 - 163
application/src/luat_malloc_air105.c

@@ -1,163 +1,163 @@
-/*
- * 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.
- */
-
-
-// 这个文件包含 系统heap和lua heap的默认实现
-
-
-#include <stdlib.h>
-#include <string.h>//add for memset
-#include "bget.h"
-#include "luat_malloc.h"
-#include "luat_bget.h"
-#define LUAT_LOG_TAG "heap"
-#include "luat_log.h"
-
-#include "FreeRTOS.h"
-#include "task.h"
-#include "app_interface.h"
-
-#ifndef	LUAT_HEAP_SIZE
-#define LUAT_HEAP_SIZE		200
-#endif
-
-#if (LUAT_HEAP_SIZE > 400) || (LUAT_HEAP_SIZE < 100)
-#undef LUAT_HEAP_SIZE
-#define LUAT_HEAP_SIZE 		200
-#endif
-
-static luat_bget_t luavm_pool;
-static uint64_t luavm_pool_data[LUAT_HEAP_SIZE / 8 * 1024];
-//------------------------------------------------
-//  管理系统内存
-
-void* luat_heap_malloc(size_t len) {
-    return malloc(len);
-}
-
-void luat_heap_free(void* ptr) {
-    free(ptr);
-}
-
-void* luat_heap_realloc(void* ptr, size_t len) {
-    return realloc(ptr, len);
-}
-
-void* luat_heap_calloc(size_t count, size_t _size) {
-    return calloc(count,_size);
-}
-
-void* luat_heap_zalloc(size_t _size) {
-    return zalloc(_size);
-}
-
-//------------------------------------------------
-void luat_vm_pool_init(void)
-{
-	luat_bget_init(&luavm_pool);
-	luat_bpool(&luavm_pool, luavm_pool_data, sizeof(luavm_pool_data));
-}
-//------------------------------------------------
-
-void *luat_vm_malloc(size_t nsize)
-{
-	return luat_bget(&luavm_pool, nsize);
-}
-
-void luat_vm_free(void *ptr)
-{
-	return luat_brel(&luavm_pool, ptr);
-}
-// ---------- 管理 LuaVM所使用的内存----------------
-void* luat_heap_alloc(void *ud, void *ptr, size_t osize, size_t nsize) {
-//    if (0) {
-//        if (ptr) {
-//            if (nsize) {
-//                // 缩放内存块
-//                LLOGD("realloc %p from %d to %d", ptr, osize, nsize);
-//            }
-//            else {
-//                // 释放内存块
-//                LLOGD("free %p ", ptr);
-//                free(ptr);
-//                return NULL;
-//            }
-//        }
-//        else {
-//            // 申请内存块
-//            ptr = malloc(nsize);
-//            LLOGD("malloc %p type=%d size=%d", ptr, osize, nsize);
-//            return ptr;
-//        }
-//    }
-    if (nsize)
-    {
-    	void* ptmp = luat_bget(&luavm_pool, nsize);
-    	if (ptmp)
-    	{
-    		if (ptr)
-    		{
-        		if (osize > nsize)
-        		{
-        			memcpy(ptmp, ptr, nsize);
-        		}
-        		else
-        		{
-        			memcpy(ptmp, ptr, osize);
-        		}
-        		if (((uint32_t)ptr & __SRAM_BASE_ADDR__) == __SRAM_BASE_ADDR__)
-        		{
-        			luat_brel(&luavm_pool, ptr);
-        		}
-    		}
-    		return ptmp;
-    	}
-    	else if (osize >= nsize)
-    	{
-    		return ptr;
-    	}
-    }
-	if (((uint32_t)ptr & __SRAM_BASE_ADDR__) == __SRAM_BASE_ADDR__)
-	{
-		luat_brel(&luavm_pool, ptr);
-	}
-    return NULL;
-}
-
-void luat_meminfo_luavm(size_t *total, size_t *used, size_t *max_used) {
-	long curalloc, totfree, maxfree;
-	unsigned long nget, nrel;
-	luat_bstats(&luavm_pool, &curalloc, &totfree, &maxfree, &nget, &nrel);
-	*used = curalloc;
-	*max_used = luat_bstatsmaxget(&luavm_pool);
-    *total = curalloc + totfree;
-}
-
-void luat_meminfo_sys(size_t *total, size_t *used, size_t *max_used) {
-	long curalloc, totfree, maxfree;
-	unsigned long nget, nrel;
-	bstats(&curalloc, &totfree, &maxfree, &nget, &nrel);
-	*used = curalloc;
-	*max_used = bstatsmaxget();
-    *total = curalloc + totfree;
-}
-
-//-----------------------------------------------------------------------------
+/*
+ * 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.
+ */
+
+
+// 这个文件包含 系统heap和lua heap的默认实现
+
+
+#include <stdlib.h>
+#include <string.h>//add for memset
+#include "bget.h"
+#include "luat_malloc.h"
+#include "luat_bget.h"
+#define LUAT_LOG_TAG "heap"
+#include "luat_log.h"
+
+#include "FreeRTOS.h"
+#include "task.h"
+#include "app_interface.h"
+
+#ifndef	LUAT_HEAP_SIZE
+#define LUAT_HEAP_SIZE		200
+#endif
+
+#if (LUAT_HEAP_SIZE > 400) || (LUAT_HEAP_SIZE < 100)
+#undef LUAT_HEAP_SIZE
+#define LUAT_HEAP_SIZE 		200
+#endif
+
+static luat_bget_t luavm_pool;
+static uint64_t luavm_pool_data[LUAT_HEAP_SIZE / 8 * 1024];
+//------------------------------------------------
+//  管理系统内存
+
+void* luat_heap_malloc(size_t len) {
+    return malloc(len);
+}
+
+void luat_heap_free(void* ptr) {
+    free(ptr);
+}
+
+void* luat_heap_realloc(void* ptr, size_t len) {
+    return realloc(ptr, len);
+}
+
+void* luat_heap_calloc(size_t count, size_t _size) {
+    return calloc(count,_size);
+}
+
+void* luat_heap_zalloc(size_t _size) {
+    return zalloc(_size);
+}
+
+//------------------------------------------------
+void luat_vm_pool_init(void)
+{
+	luat_bget_init(&luavm_pool);
+	luat_bpool(&luavm_pool, luavm_pool_data, sizeof(luavm_pool_data));
+}
+//------------------------------------------------
+
+void *luat_vm_malloc(size_t nsize)
+{
+	return luat_bget(&luavm_pool, nsize);
+}
+
+void luat_vm_free(void *ptr)
+{
+	return luat_brel(&luavm_pool, ptr);
+}
+// ---------- 管理 LuaVM所使用的内存----------------
+void* luat_heap_alloc(void *ud, void *ptr, size_t osize, size_t nsize) {
+//    if (0) {
+//        if (ptr) {
+//            if (nsize) {
+//                // 缩放内存块
+//                LLOGD("realloc %p from %d to %d", ptr, osize, nsize);
+//            }
+//            else {
+//                // 释放内存块
+//                LLOGD("free %p ", ptr);
+//                free(ptr);
+//                return NULL;
+//            }
+//        }
+//        else {
+//            // 申请内存块
+//            ptr = malloc(nsize);
+//            LLOGD("malloc %p type=%d size=%d", ptr, osize, nsize);
+//            return ptr;
+//        }
+//    }
+    if (nsize)
+    {
+    	void* ptmp = luat_bget(&luavm_pool, nsize);
+    	if (ptmp)
+    	{
+    		if (ptr)
+    		{
+        		if (osize > nsize)
+        		{
+        			memcpy(ptmp, ptr, nsize);
+        		}
+        		else
+        		{
+        			memcpy(ptmp, ptr, osize);
+        		}
+        		if (((uint32_t)ptr & __SRAM_BASE_ADDR__) == __SRAM_BASE_ADDR__)
+        		{
+        			luat_brel(&luavm_pool, ptr);
+        		}
+    		}
+    		return ptmp;
+    	}
+    	else if (osize >= nsize)
+    	{
+    		return ptr;
+    	}
+    }
+	if (((uint32_t)ptr & __SRAM_BASE_ADDR__) == __SRAM_BASE_ADDR__)
+	{
+		luat_brel(&luavm_pool, ptr);
+	}
+    return NULL;
+}
+
+void luat_meminfo_luavm(size_t *total, size_t *used, size_t *max_used) {
+	long curalloc, totfree, maxfree;
+	unsigned long nget, nrel;
+	luat_bstats(&luavm_pool, &curalloc, &totfree, &maxfree, &nget, &nrel);
+	*used = curalloc;
+	*max_used = luat_bstatsmaxget(&luavm_pool);
+    *total = curalloc + totfree;
+}
+
+void luat_meminfo_sys(size_t *total, size_t *used, size_t *max_used) {
+	long curalloc, totfree, maxfree;
+	unsigned long nget, nrel;
+	bstats(&curalloc, &totfree, &maxfree, &nget, &nrel);
+	*used = curalloc;
+	*max_used = bstatsmaxget();
+    *total = curalloc + totfree;
+}
+
+//-----------------------------------------------------------------------------

+ 13 - 13
application/src/luat_ota_air105.c

@@ -1,13 +1,13 @@
-
-#include "luat_base.h"
-#include "luat_ota.h"
-#include "luat_fs.h"
-#include "luat_timer.h"
-#include "luat_malloc.h"
-#include "luat_flash.h"
-
-extern const size_t script_luadb_start_addr;
-
-int luat_ota_exec(void) {
-    return luat_ota(script_luadb_start_addr);
-}
+
+#include "luat_base.h"
+#include "luat_ota.h"
+#include "luat_fs.h"
+#include "luat_timer.h"
+#include "luat_malloc.h"
+#include "luat_flash.h"
+
+extern const size_t script_luadb_start_addr;
+
+int luat_ota_exec(void) {
+    return luat_ota(script_luadb_start_addr);
+}

+ 84 - 84
application/src/luat_pm_air105.c

@@ -1,84 +1,84 @@
-#include "luat_base.h"
-#include "luat_pm.h"
-#include "app_interface.h"
-
-#define LUAT_LOG_TAG "pm"
-#include "luat_log.h"
-
-int luat_pm_request(int mode) {
-//    if (mode != LUAT_PM_SLEEP_MODE_LIGHT || mode == LUAT_PM_SLEEP_MODE_DEEP) {
-//        LLOGW("only pm.LIGHT/pm.DEEP supported");
-//        return -1;
-//    }
-//    uint8_t i;
-//    for(i = UART_ID1; i< UART_MAX; i++)
-//    {
-//    	Uart_Sleep(i, 0);
-//    }
-	if (mode > LUAT_PM_SLEEP_MODE_IDLE)
-	{
-		PM_SetDriverRunFlag(PM_DRV_DBG, 0);
-	}
-	else
-	{
-		PM_SetDriverRunFlag(PM_DRV_DBG, 1);
-	}
-
-    return 0;
-}
-
-int luat_pm_release(int mode) {
-    return 0;
-}
-
-int luat_pm_dtimer_start(int id, size_t timeout) {
-    if (id != 0)
-        return -1;
-    RTC_SetAlarm(timeout / 1000, NULL, NULL); // 无需回调, 或者改成回调里重启, 也不太对的样
-    return 0;
-}
-
-int luat_pm_dtimer_stop(int id) {
-    if (id != 0)
-        return -1;
-    RTC_SetAlarm(0, NULL, NULL); // 设置为0就是关闭
-    return 0;
-}
-
-int luat_pm_dtimer_check(int id) {
-    return -1;
-}
-
-// void luat_pm_cb(int event, int arg, void* args);
-
-int luat_pm_last_state(int *lastState, int *rtcOrPad) {
-    return 0;
-}
-
-int luat_pm_force(int mode) {
-    return luat_pm_request(mode);
-}
-
-int luat_pm_check(void) {
-    return 0;
-}
-
-int luat_pm_dtimer_list(size_t* count, size_t* list) {
-    *count = 0;
-    return 0;
-}
-
-int luat_pm_dtimer_wakeup_id(int* id) {
-    return -1;
-}
-
-
-int luat_pm_power_ctrl(int id, uint8_t onoff) {
-    LLOGW("not support yet");
-    return -1;
-}
-
-int luat_pm_wakeup_pin(int pin, int val){
-    LLOGW("not support yet");
-    return -1;
-}
+#include "luat_base.h"
+#include "luat_pm.h"
+#include "app_interface.h"
+
+#define LUAT_LOG_TAG "pm"
+#include "luat_log.h"
+
+int luat_pm_request(int mode) {
+//    if (mode != LUAT_PM_SLEEP_MODE_LIGHT || mode == LUAT_PM_SLEEP_MODE_DEEP) {
+//        LLOGW("only pm.LIGHT/pm.DEEP supported");
+//        return -1;
+//    }
+//    uint8_t i;
+//    for(i = UART_ID1; i< UART_MAX; i++)
+//    {
+//    	Uart_Sleep(i, 0);
+//    }
+	if (mode > LUAT_PM_SLEEP_MODE_IDLE)
+	{
+		PM_SetDriverRunFlag(PM_DRV_DBG, 0);
+	}
+	else
+	{
+		PM_SetDriverRunFlag(PM_DRV_DBG, 1);
+	}
+
+    return 0;
+}
+
+int luat_pm_release(int mode) {
+    return 0;
+}
+
+int luat_pm_dtimer_start(int id, size_t timeout) {
+    if (id != 0)
+        return -1;
+    RTC_SetAlarm(timeout / 1000, NULL, NULL); // 无需回调, 或者改成回调里重启, 也不太对的样
+    return 0;
+}
+
+int luat_pm_dtimer_stop(int id) {
+    if (id != 0)
+        return -1;
+    RTC_SetAlarm(0, NULL, NULL); // 设置为0就是关闭
+    return 0;
+}
+
+int luat_pm_dtimer_check(int id) {
+    return -1;
+}
+
+// void luat_pm_cb(int event, int arg, void* args);
+
+int luat_pm_last_state(int *lastState, int *rtcOrPad) {
+    return 0;
+}
+
+int luat_pm_force(int mode) {
+    return luat_pm_request(mode);
+}
+
+int luat_pm_check(void) {
+    return 0;
+}
+
+int luat_pm_dtimer_list(size_t* count, size_t* list) {
+    *count = 0;
+    return 0;
+}
+
+int luat_pm_dtimer_wakeup_id(int* id) {
+    return -1;
+}
+
+
+int luat_pm_power_ctrl(int id, uint8_t onoff) {
+    LLOGW("not support yet");
+    return -1;
+}
+
+int luat_pm_wakeup_pin(int pin, int val){
+    LLOGW("not support yet");
+    return -1;
+}

+ 93 - 93
application/src/luat_rtc_air105.c

@@ -1,93 +1,93 @@
-/*
- * 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.
- */
-
-#include "luat_base.h"
-#include "luat_rtc.h"
-#include "app_interface.h"
-
-extern int Base_year;
-
-int luat_rtc_set(struct tm *tblock) {
-	Date_UserDataStruct Date;
-	Time_UserDataStruct Time;
-
-    Time.Sec = tblock->tm_sec;
-    Time.Min = tblock->tm_min;
-    Time.Hour = tblock->tm_hour;
-    //tblock->tm_wday = uTime.Time.Week;
-
-    Date.Year = tblock->tm_year;
-    Date.Mon = tblock->tm_mon;
-    Date.Day = tblock->tm_mday;
-
-    Date.Year += Base_year;
-    Date.Mon += 1;
-
-    RTC_SetDateTime(&Date, &Time, 1);
-    return 0;
-}
-
-void luat_rtc_set_tamp32(uint32_t tamp) {
-	RTC_SetUTC(tamp, 1);
-}
-
-int luat_rtc_get(struct tm *tblock) {
-	Date_UserDataStruct Date;
-	Time_UserDataStruct Time;
-    
-    RTC_GetDateTime(&Date, &Time);
-    
-    tblock->tm_sec = Time.Sec;
-    tblock->tm_min = Time.Min;
-    tblock->tm_hour = Time.Hour;
-    tblock->tm_wday = Time.Week;
-
-    tblock->tm_year = Date.Year;
-    tblock->tm_mon = Date.Mon;
-    tblock->tm_mday = Date.Day;
-
-    tblock->tm_year -= Base_year;
-    tblock->tm_mon -= 1;
-
-    return 0;
-}
-
-int luat_rtc_timer_start(int id, struct tm *tblock) {
-    return -1; // 暂不支持
-}
-
-int luat_rtc_timer_stop(int id) {
-    return -1; // 暂不支持
-}
-
-uint32_t luat_get_utc(uint32_t *tamp)
-{
-	uint32_t sec = RTC_GetUTC();
-	if (tamp)
-	{
-		*tamp = sec;
-	}
-	return sec;
-}
-
-int luat_rtc_timezone(int* timezone) {
-    return 32; // 暂不支持
-}
+/*
+ * 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.
+ */
+
+#include "luat_base.h"
+#include "luat_rtc.h"
+#include "app_interface.h"
+
+extern int Base_year;
+
+int luat_rtc_set(struct tm *tblock) {
+	Date_UserDataStruct Date;
+	Time_UserDataStruct Time;
+
+    Time.Sec = tblock->tm_sec;
+    Time.Min = tblock->tm_min;
+    Time.Hour = tblock->tm_hour;
+    //tblock->tm_wday = uTime.Time.Week;
+
+    Date.Year = tblock->tm_year;
+    Date.Mon = tblock->tm_mon;
+    Date.Day = tblock->tm_mday;
+
+    Date.Year += Base_year;
+    Date.Mon += 1;
+
+    RTC_SetDateTime(&Date, &Time, 1);
+    return 0;
+}
+
+void luat_rtc_set_tamp32(uint32_t tamp) {
+	RTC_SetUTC(tamp, 1);
+}
+
+int luat_rtc_get(struct tm *tblock) {
+	Date_UserDataStruct Date;
+	Time_UserDataStruct Time;
+    
+    RTC_GetDateTime(&Date, &Time);
+    
+    tblock->tm_sec = Time.Sec;
+    tblock->tm_min = Time.Min;
+    tblock->tm_hour = Time.Hour;
+    tblock->tm_wday = Time.Week;
+
+    tblock->tm_year = Date.Year;
+    tblock->tm_mon = Date.Mon;
+    tblock->tm_mday = Date.Day;
+
+    tblock->tm_year -= Base_year;
+    tblock->tm_mon -= 1;
+
+    return 0;
+}
+
+int luat_rtc_timer_start(int id, struct tm *tblock) {
+    return -1; // 暂不支持
+}
+
+int luat_rtc_timer_stop(int id) {
+    return -1; // 暂不支持
+}
+
+uint32_t luat_get_utc(uint32_t *tamp)
+{
+	uint32_t sec = RTC_GetUTC();
+	if (tamp)
+	{
+		*tamp = sec;
+	}
+	return sec;
+}
+
+int luat_rtc_timezone(int* timezone) {
+    return 32; // 暂不支持
+}

+ 5 - 0
application/src/luat_rtos_air105.c

@@ -179,3 +179,8 @@ int luat_rtos_queue_recv(luat_rtos_queue_t queue_handle, void *item, uint32_t it
 	}
 	return 0;
 }
+
+
+uint32_t luat_rtos_entry_critical(void) {return OS_EnterCritical();}
+
+void luat_rtos_exit_critical(uint32_t critical) {OS_ExitCritical(critical);}

+ 597 - 597
application/src/luat_spi_air105.c

@@ -1,597 +1,597 @@
-/*
- * 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.
- */
-
-
-
-#include "luat_base.h"
-#include "luat_spi.h"
-#include "luat_lcd.h"
-#include "luat_timer.h"
-#include "luat_malloc.h"
-#include "stdlib.h"
-#include "string.h"
-#include "ff.h"			/* Obtains integer types */
-#include "diskio.h"		/* Declarations of disk functions */
-#include "app_interface.h"
-
-#define LUAT_LOG_TAG "luat.spi"
-#include "luat_log.h"
-
-typedef struct
-{
-	uint8_t id;
-//	uint8_t mark;
-    uint8_t mode;//spi模式
-}Spi_Struct;
-
-static Spi_Struct luat_spi[6] ={0};
-
-int32_t luat_spi_cb(void *pData, void *pParam){
-//    LLOGD("luat_spi_cb pData:%d pParam:%d ",(int)pData,(int)pParam);
-//    switch ((int)pData){
-//        case 0:
-//            luat_spi[5].mark = 0;
-//            break;
-//        case 1:
-//            luat_spi[0].mark = 0;
-//            break;
-//        case 2:
-//            luat_spi[1].mark = 0;
-//            break;
-//        case 3:
-//            luat_spi[2].mark = 0;
-//            break;
-//        default:
-//            break;
-//    }
-}
-
-int luat_spi_device_config(luat_spi_device_t* spi_dev) {
-    uint8_t spi_mode = SPI_MODE_0;
-    if(spi_dev->spi_config.CPHA&&spi_dev->spi_config.CPOL)spi_mode = SPI_MODE_3;
-    else if(spi_dev->spi_config.CPOL)spi_mode = SPI_MODE_2;
-    else if(spi_dev->spi_config.CPHA)spi_mode = SPI_MODE_1;
-    SPI_SetNewConfig(luat_spi[spi_dev->bus_id].id, spi_dev->spi_config.bandrate, spi_mode);
-    return 0;
-}
-
-int luat_spi_bus_setup(luat_spi_device_t* spi_dev){
-    int bus_id = spi_dev->bus_id;
-    if (bus_id == 0) {
-        luat_spi[bus_id].id=SPI_ID0;
-        GPIO_Iomux(GPIOB_12, 0);
-        GPIO_Iomux(GPIOB_14, 0);
-        GPIO_Iomux(GPIOB_15, 0);
-    }
-    else if (bus_id == 1) {
-        luat_spi[bus_id].id=SPI_ID1;
-	    GPIO_Iomux(GPIOA_06,3);
-	    GPIO_Iomux(GPIOA_08,3);
-	    GPIO_Iomux(GPIOA_09,3);
-    }
-    else if (bus_id == 2) {
-        luat_spi[bus_id].id=SPI_ID2;
-	    GPIO_Iomux(GPIOB_02,0);
-	    GPIO_Iomux(GPIOB_04,0);
-	    GPIO_Iomux(GPIOB_05,0);
-    }
-    else if (bus_id == 5) {
-        luat_spi[bus_id].id=HSPI_ID0;
-	    GPIO_Iomux(GPIOC_12,3);
-	    GPIO_Iomux(GPIOC_13,3);
-	    GPIO_Iomux(GPIOC_15,3);
-    }
-    else {
-        return -1;
-    }
-    uint8_t spi_mode = SPI_MODE_0;
-    if(spi_dev->spi_config.CPHA&&spi_dev->spi_config.CPOL)spi_mode = SPI_MODE_3;
-    else if(spi_dev->spi_config.CPOL)spi_mode = SPI_MODE_2;
-    else if(spi_dev->spi_config.CPHA)spi_mode = SPI_MODE_1;
-    luat_spi[bus_id].mode=spi_dev->spi_config.mode;
-    // LLOGD("SPI_MasterInit luat_bus_%d:%d dataw:%d spi_mode:%d bandrate:%d ",bus_id,luat_spi[bus_id].id, spi_dev->spi_config.dataw, spi_mode, spi_dev->spi_config.bandrate);
-    SPI_MasterInit(luat_spi[bus_id].id, spi_dev->spi_config.dataw, spi_mode, spi_dev->spi_config.bandrate, luat_spi_cb, NULL);
-    return 0;
-}
-
-//初始化配置SPI各项参数,并打开SPI
-//成功返回0
-int luat_spi_setup(luat_spi_t* spi) {
-    uint8_t spi_id = spi->id;
-    if (spi_id == 0) {
-        luat_spi[spi_id].id=SPI_ID0;
-        if (spi->cs == 0 || spi->cs == GPIOB_13)
-            GPIO_Iomux(GPIOB_13, 0);
-        GPIO_Iomux(GPIOB_12, 0);
-        GPIO_Iomux(GPIOB_14, 0);
-        GPIO_Iomux(GPIOB_15, 0);
-    }
-    else if (spi_id == 1) {
-        luat_spi[spi_id].id=SPI_ID1;
-        if (spi->cs == 0 || spi->cs == GPIOA_07)
-	        GPIO_Iomux(GPIOA_07,3);
-	    GPIO_Iomux(GPIOA_06,3);
-	    GPIO_Iomux(GPIOA_08,3);
-	    GPIO_Iomux(GPIOA_09,3);
-    }
-    else if (spi_id == 2) {
-        luat_spi[spi_id].id=SPI_ID2;
-        if (spi->cs == 0 || spi->cs == GPIOB_03)
-	        GPIO_Iomux(GPIOB_03,0);
-	    GPIO_Iomux(GPIOB_02,0);
-	    GPIO_Iomux(GPIOB_04,0);
-	    GPIO_Iomux(GPIOB_05,0);
-    }
-    else if (spi_id == 5) {
-        luat_spi[spi_id].id=HSPI_ID0;
-        if (spi->cs == 0 || spi->cs == GPIOC_14)
-	        GPIO_Iomux(GPIOC_14,3);
-	    GPIO_Iomux(GPIOC_12,3);
-	    GPIO_Iomux(GPIOC_13,3);
-	    GPIO_Iomux(GPIOC_15,3);
-    }
-    else {
-        return -1;
-    }
-    uint8_t spi_mode = SPI_MODE_0;
-    if(spi->CPHA&&spi->CPOL)spi_mode = SPI_MODE_3;
-    else if(spi->CPOL)spi_mode = SPI_MODE_2;
-    else if(spi->CPHA)spi_mode = SPI_MODE_1;
-    luat_spi[spi_id].mode=spi->mode;
-//    LLOGD("SPI_MasterInit luat_spi%d:%d dataw:%d spi_mode:%d bandrate:%d ",spi_id,luat_spi[spi_id].id, spi->dataw, spi_mode, spi->bandrate);
-    SPI_MasterInit(luat_spi[spi_id].id, spi->dataw, spi_mode, spi->bandrate, luat_spi_cb, NULL);
-    return 0;
-}
-
-int luat_spi_config_dma(int spi_id, uint32_t tx_channel, uint32_t rx_channel)
-{
-//	if (luat_spi[spi_id].id != HSPI_ID0) {
-//		SPI_DMATxInit(luat_spi[spi_id].id, (tx_channel >= 8)?ETH_SPI_TX_DMA_STREAM:tx_channel, 0);
-//		SPI_DMARxInit(luat_spi[spi_id].id, (rx_channel >= 8)?ETH_SPI_RX_DMA_STREAM:rx_channel, 0);
-//	}
-//	else
-//	{
-//		SPI_DMATxInit(luat_spi[spi_id].id, (tx_channel >= 8)?LCD_SPI_TX_DMA_STREAM:tx_channel, 0);
-//		SPI_DMARxInit(luat_spi[spi_id].id, (rx_channel >= 8)?LCD_SPI_RX_DMA_STREAM:rx_channel, 0);
-//	}
-}
-
-//关闭SPI,成功返回0
-int luat_spi_close(int spi_id) {
-    return 0;
-}
-//收发SPI数据,返回接收字节数
-int luat_spi_transfer(int spi_id, const char* send_buf, size_t send_length, char* recv_buf, size_t recv_length) {
-    // LLOGD("SPI_MasterInit luat_spi%d:%d send_buf:%x recv_buf:%x length:%d ",spi_id,luat_spi[spi_id], *send_buf, *recv_buf, length);
-    // while(luat_spi[spi_id].mark)
-//    luat_spi[spi_id].mark = 1;
-    int32_t result = 0;
-    if(luat_spi[spi_id].mode==0)
-        result = SPI_FlashBlockTransfer(luat_spi[spi_id].id, send_buf, send_length, recv_buf, recv_length);
-    else
-        result = SPI_BlockTransfer(luat_spi[spi_id].id, send_buf, recv_buf, recv_length);
-    if(result)
-        return 0;
-    return recv_length;
-}
-//收SPI数据,返回接收字节数
-int luat_spi_recv(int spi_id, char* recv_buf, size_t length) {
-    // LLOGD("SPI_MasterInit luat_spi%d:%d recv_buf:%x length:%d ",spi_id,luat_spi[spi_id], *recv_buf, length);
-    // while(luat_spi[spi_id].mark)
-//    luat_spi[spi_id].mark = 1;
-    if(SPI_BlockTransfer(luat_spi[spi_id].id, recv_buf, recv_buf, length))
-        return 0;
-    return length;
-}
-//发SPI数据,返回发送字节数
-int luat_spi_send(int spi_id, const char* send_buf, size_t length) {
-    // LLOGD("luat_spi_send luat_spi%d:%d send_buf:%x length:%d ",spi_id,luat_spi[spi_id], *send_buf, length);
-    // while(luat_spi[spi_id].mark)
-//    luat_spi[spi_id].mark = 1;
-    if(SPI_BlockTransfer(luat_spi[spi_id].id, send_buf, NULL, length))
-        return 0;
-    return length;
-}
-
-int luat_spi_change_speed(int spi_id, uint32_t speed)
-{
-	SPI_SetNewConfig(luat_spi[spi_id].id, speed, 0xff);
-	return 0;
-}
-
-int luat_spi_no_block_transfer(int spi_id, uint8_t *tx_buff, uint8_t *rx_buff, size_t len, void *CB, void *pParam)
-{
-	if (SPI_IsTransferBusy(luat_spi[spi_id].id)) return -1;
-	SPI_SetCallbackFun(luat_spi[spi_id].id, CB, pParam);
-	SPI_SetNoBlock(luat_spi[spi_id].id);
-	return SPI_Transfer(luat_spi[spi_id].id, tx_buff, rx_buff, len, 0);
-
-}
-
-int luat_lcd_draw_no_block(luat_lcd_conf_t* conf, int16_t x1, int16_t y1, int16_t x2, int16_t y2, luat_color_t* color, uint8_t last_flush)
-{
-	uint32_t retry_cnt = 0;
-	uint32_t cache_len = Core_LCDDrawCacheLen();
-//	if (last_flush)
-//	{
-//		LLOGD("lcd flush done!");
-//	}
-	if (x1 < 0 || y1 < 0 || x2 > conf->w || y2 > conf->h) {
-		// 暂不支持屏幕外绘制
-	}
-
-	if (conf->port == LUAT_LCD_SPI_DEVICE){
-		while (Core_LCDDrawCacheLen() > (conf->buffer_size))
-		{
-			retry_cnt++;
-			luat_timer_mdelay(1);
-		}
-		if (retry_cnt)
-		{
-			LLOGD("lcd flush delay %ums, status %u,%u,%u,%d", retry_cnt, cache_len, x2-x1+1, y2-y1+1, last_flush);
-		}
-		LCD_DrawStruct *draw = zalloc(sizeof(LCD_DrawStruct));
-		if (!draw)
-		{
-			LLOGE("lcd flush no memory");
-			return -1;
-		}
-		luat_spi_device_t* spi_dev = (luat_spi_device_t*)conf->lcd_spi_device;
-		int spi_id = spi_dev->bus_id;
-	    uint8_t spi_mode = SPI_MODE_0;
-	    if(spi_dev->spi_config.CPHA&&spi_dev->spi_config.CPOL)spi_mode = SPI_MODE_3;
-	    else if(spi_dev->spi_config.CPOL)spi_mode = SPI_MODE_2;
-	    else if(spi_dev->spi_config.CPHA)spi_mode = SPI_MODE_1;
-	    draw->DCDelay = conf->dc_delay_us;
-	    draw->Mode = spi_mode;
-	    draw->Speed = spi_dev->spi_config.bandrate;
-	    draw->SpiID = luat_spi[spi_id].id;
-	    draw->CSPin = spi_dev->spi_config.cs;
-	    draw->DCPin = conf->pin_dc;
-	    draw->x1 = x1;
-	    draw->x2 = x2;
-	    draw->y1 = y1;
-	    draw->y2 = y2;
-	    draw->xoffset = conf->xoffset;
-	    draw->yoffset = conf->yoffset;
-	    draw->Size = (draw->x2 - draw->x1 + 1) * (draw->y2 - draw->y1 + 1) * 2;
-	    draw->ColorMode = COLOR_MODE_RGB_565;
-	    draw->Data = malloc(draw->Size);
-		if (!draw->Data)
-		{
-			LLOGE("lcd flush data no memory");
-			free(draw);
-			return -1;
-		}
-	    memcpy(draw->Data, color, draw->Size);
-	    Core_LCDDraw(draw);
-	    return 0;
-	}
-	else
-	{
-		return -1;
-	}
-}
-
-int luat_spi_get_hw_bus(int spi_id)
-{
-	return luat_spi[spi_id].id;
-}
-
-void luat_lcd_draw_block(luat_lcd_conf_t* conf, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, luat_color_t* color, uint8_t last_flush)
-{
-	LCD_DrawStruct draw;
-	if (conf->port == LUAT_LCD_SPI_DEVICE){
-		luat_spi_device_t* spi_dev = (luat_spi_device_t*)conf->lcd_spi_device;
-		int spi_id = spi_dev->bus_id;
-	    uint8_t spi_mode = SPI_MODE_0;
-	    if(spi_dev->spi_config.CPHA&&spi_dev->spi_config.CPOL)spi_mode = SPI_MODE_3;
-	    else if(spi_dev->spi_config.CPOL)spi_mode = SPI_MODE_2;
-	    else if(spi_dev->spi_config.CPHA)spi_mode = SPI_MODE_1;
-	    draw.DCDelay = conf->dc_delay_us;
-	    draw.Mode = spi_mode;
-	    draw.Speed = spi_dev->spi_config.bandrate;
-	    draw.SpiID = luat_spi[spi_id].id;
-	    draw.CSPin = spi_dev->spi_config.cs;
-	    draw.DCPin = conf->pin_dc;
-	    draw.x1 = x1;
-	    draw.x2 = x2;
-	    draw.y1 = y1;
-	    draw.y2 = y2;
-	    draw.xoffset = conf->xoffset;
-	    draw.yoffset = conf->yoffset;
-	    draw.Size = (draw.x2 - draw.x1 + 1) * (draw.y2 - draw.y1 + 1) * 2;
-	    draw.ColorMode = COLOR_MODE_RGB_565;
-	    draw.Data = color;
-	    Core_LCDDrawBlock(&draw);
-	}
-}
-
-#ifdef LUAT_USE_LCD_CUSTOM_DRAW
-int luat_lcd_flush(luat_lcd_conf_t* conf) {
-    if (conf->buff == NULL) {
-        return 0;
-    }
-    //LLOGD("luat_lcd_flush range %d %d", conf->flush_y_min, conf->flush_y_max);
-    if (conf->flush_y_max < conf->flush_y_min) {
-        // 没有需要刷新的内容,直接跳过
-        //LLOGD("luat_lcd_flush no need");
-        return 0;
-    }
-    if (conf->is_init_done) {
-    	luat_lcd_draw_no_block(conf, 0, conf->flush_y_min, conf->w - 1, conf->flush_y_max, &conf->buff[conf->flush_y_min * conf->w], 0);
-    }
-    else {
-        uint32_t size = conf->w * (conf->flush_y_max - conf->flush_y_min + 1) * 2;
-        luat_lcd_set_address(conf, 0, conf->flush_y_min, conf->w - 1, conf->flush_y_max);
-        const char* tmp = (const char*)(conf->buff + conf->flush_y_min * conf->w);
-    	if (conf->port == LUAT_LCD_SPI_DEVICE){
-    		luat_spi_device_send((luat_spi_device_t*)(conf->lcd_spi_device), tmp, size);
-    	}else{
-    		luat_spi_send(conf->port, tmp, size);
-    	}
-    }
-    // 重置为不需要刷新的状态
-    conf->flush_y_max = 0;
-    conf->flush_y_min = conf->h;
-
-    return 0;
-}
-
-int luat_lcd_draw(luat_lcd_conf_t* conf, int16_t x1, int16_t y1, int16_t x2, int16_t y2, luat_color_t* color) {
-    if (x1 >= conf->w || y1 >= conf->h || x2 < 0 || y2 < 0 || x2 < x1 || y2 < y1) {
-        // LLOGE("out of lcd buff range %d %d %d %d", x1, y1, x2, y2);
-        // LLOGE("out of lcd buff range %d %d %d %d %d", x1 >= conf->w, y1 >= conf->h, y2 < 0, x2 < x1, y2 < y1);
-        return 0;
-    }
-    if (y2 >= conf->h) {
-        y2 = conf->h - 1;
-    }
-    // 直接刷屏模式
-    if (conf->buff == NULL) {
-        // 常规数据, 整体传输
-        if (x1 >= 0 && y1 >= 0 && x2 <= conf->w && y2 <= conf->h) {
-			if (conf->is_init_done) {
-				return luat_lcd_draw_no_block(conf, x1, y1, x2, y2, color, 0);
-			}
-            uint32_t size = (x2 - x1 + 1) * (y2 - y1 + 1);
-            // LLOGD("draw %dx%d %dx%d %d", x1, y1, x2, y2, size);
-            luat_lcd_set_address(conf, x1, y1, x2, y2);
-	        if (conf->port == LUAT_LCD_SPI_DEVICE){
-		        luat_spi_device_send((luat_spi_device_t*)(conf->lcd_spi_device), (const char*)color, size* sizeof(luat_color_t));
-	        }else{
-		        luat_spi_send(conf->port, (const char*)color, size * sizeof(luat_color_t));
-	        }
-        }
-        // 超出边界的数据, 按行传输
-        else {
-            int line_size = (x2 - x1 + 1);
-            // LLOGD("want draw %dx%d %dx%d %d", x1, y1, x2, y2, line_size);
-            luat_color_t* ptr = (luat_color_t*)color;
-            for (int i = y1; i <= y2; i++)
-            {
-                if (i < 0) {
-                    ptr += line_size;
-                    continue;
-                }
-                luat_color_t* line = ptr;
-                int lsize = line_size;
-                int tmp_x1 = x1;
-                int tmp_x2 = x2;
-                if (x1 < 0) {
-                    line += ( - x1);
-                    lsize += (x1);
-                    tmp_x1 = 0;
-                }
-                if (x2 > conf->w) {
-                    lsize -= (conf->w - x2);
-                    tmp_x2 = conf->w;
-                }
-				// LLOGD("action draw %dx%d %dx%d %d", tmp_x1, i, tmp_x2, i, lsize);
-				if (conf->is_init_done) {
-					luat_lcd_draw_no_block(conf, tmp_x1, i, tmp_x2, i, line, 0);
-				}
-				else {
-                	luat_lcd_set_address(conf, tmp_x1, i, tmp_x2, i);
-	            	if (conf->port == LUAT_LCD_SPI_DEVICE){
-		            	luat_spi_device_send((luat_spi_device_t*)(conf->lcd_spi_device), (const char*)line, lsize * sizeof(luat_color_t));
-	            	} else{
-		            	luat_spi_send(conf->port, (const char*)line, lsize * sizeof(luat_color_t));
-	            	}
-				}
-                ptr += line_size;
-            }
-        }
-        return 0;
-    }
-    // buff模式
-    luat_color_t* dst = (conf->buff);
-    size_t lsize = (x2 - x1 + 1);
-    for (int16_t x = x1; x <= x2; x++)
-    {
-        if (x < 0 || x >= conf->w)
-            continue;
-        for (int16_t y = y1; y <= y2; y++)
-        {
-            if (y < 0 || y >= conf->h)
-                continue;
-            memcpy((char*)(dst + (conf->w * y + x)), (char*)(color + (lsize * (y-y1) + (x-x1))), sizeof(luat_color_t));
-        }
-    }
-    // 存储需要刷新的区域
-    if (y1 < conf->flush_y_min) {
-        if (y1 >= 0)
-            conf->flush_y_min = y1;
-        else
-            conf->flush_y_min = 0;
-    }
-    if (y2 > conf->flush_y_max) {
-        conf->flush_y_max = y2;
-    }
-    return 0;
-}
-#endif
-
-#if 1
-static void *luat_fatfs_spi_ctrl;
-static HANDLE luat_fatfs_locker;
-static void sdhc_spi_check(luat_fatfs_spi_t* userdata)
-{
-	if (!luat_fatfs_spi_ctrl)
-	{
-		if(userdata->type == 1){
-			luat_fatfs_spi_ctrl = SDHC_SpiCreate(luat_spi[userdata->spi_device->bus_id].id, userdata->spi_device->spi_config.cs);
-			luat_spi_device_config(userdata->spi_device);
-		}else{
-			luat_fatfs_spi_ctrl = SDHC_SpiCreate(luat_spi[userdata->spi_id].id, userdata->spi_cs);
-		}
-	}
-}
-
-static DSTATUS sdhc_spi_initialize(luat_fatfs_spi_t* userdata)
-{
-	int i;
-	if (!luat_fatfs_locker)
-	{
-		luat_fatfs_locker = OS_MutexCreateUnlock();
-	}
-	OS_MutexLock(luat_fatfs_locker);
-	if (luat_fatfs_spi_ctrl)
-	{
-		for(i = 0; i < USB_MAX; i++)
-		{
-			Core_UDiskDetachSDHC(i, luat_fatfs_spi_ctrl);
-		}
-		SDHC_SpiRelease(luat_fatfs_spi_ctrl);
-		free(luat_fatfs_spi_ctrl);
-		luat_fatfs_spi_ctrl = NULL;
-	}
-	sdhc_spi_check(userdata);
-	SDHC_SpiInitCard(luat_fatfs_spi_ctrl);
-	if(userdata->type == 1){
-		userdata->spi_device->spi_config.bandrate = userdata->fast_speed;
-		luat_spi_device_config(userdata->spi_device);
-	}else{
-		SPI_SetNewConfig(luat_spi[userdata->spi_id].id, userdata->fast_speed, 0);
-	}
-	if (SDHC_IsReady(luat_fatfs_spi_ctrl))
-	{
-		for(i = 0; i < USB_MAX; i++)
-		{
-			Core_UDiskAttachSDHCRecovery(i, luat_fatfs_spi_ctrl);
-		}
-	}
-	OS_MutexRelease(luat_fatfs_locker);
-	return SDHC_IsReady(luat_fatfs_spi_ctrl)?0:STA_NOINIT;
-}
-
-static DSTATUS sdhc_spi_status(luat_fatfs_spi_t* userdata)
-{
-	OS_MutexLock(luat_fatfs_locker);
-	sdhc_spi_check(userdata);
-	OS_MutexRelease(luat_fatfs_locker);
-	return SDHC_IsReady(luat_fatfs_spi_ctrl)?0:STA_NOINIT;
-}
-
-static DRESULT sdhc_spi_read(luat_fatfs_spi_t* userdata, uint8_t* buff, uint32_t sector, uint32_t count)
-{
-	OS_MutexLock(luat_fatfs_locker);
-	sdhc_spi_check(userdata);
-	if (!SDHC_IsReady(luat_fatfs_spi_ctrl))
-	{
-		OS_MutexRelease(luat_fatfs_locker);
-		return RES_NOTRDY;
-	}
-	SDHC_SpiReadBlocks(luat_fatfs_spi_ctrl, buff, sector, count);
-	OS_MutexRelease(luat_fatfs_locker);
-	return SDHC_IsReady(luat_fatfs_spi_ctrl)?RES_OK:RES_ERROR;
-}
-
-static DRESULT sdhc_spi_write(luat_fatfs_spi_t* userdata, const uint8_t* buff, uint32_t sector, uint32_t count)
-{
-	OS_MutexLock(luat_fatfs_locker);
-	sdhc_spi_check(userdata);
-	if (!SDHC_IsReady(luat_fatfs_spi_ctrl))
-	{
-		OS_MutexRelease(luat_fatfs_locker);
-		return RES_NOTRDY;
-	}
-	SDHC_SpiWriteBlocks(luat_fatfs_spi_ctrl, buff, sector, count);
-	OS_MutexRelease(luat_fatfs_locker);
-	return SDHC_IsReady(luat_fatfs_spi_ctrl)?RES_OK:RES_ERROR;
-}
-
-static DRESULT sdhc_spi_ioctl(luat_fatfs_spi_t* userdata, uint8_t ctrl, void* buff)
-{
-	OS_MutexLock(luat_fatfs_locker);
-	sdhc_spi_check(userdata);
-	if (!SDHC_IsReady(luat_fatfs_spi_ctrl))
-	{
-		OS_MutexRelease(luat_fatfs_locker);
-		return RES_NOTRDY;
-	}
-	SDHC_SpiReadCardConfig(luat_fatfs_spi_ctrl);
-	OS_MutexRelease(luat_fatfs_locker);
-	switch (ctrl) {
-		case CTRL_SYNC :		/* Make sure that no pending write process */
-			return RES_OK;
-			break;
-
-		case GET_SECTOR_COUNT :	/* Get number of sectors on the disk (DWORD) */
-			*(uint32_t*)buff = SDHC_GetLogBlockNbr(luat_fatfs_spi_ctrl);
-			return RES_OK;
-			break;
-
-		case GET_BLOCK_SIZE :	/* Get erase block size in unit of sector (DWORD) */
-			*(uint32_t*)buff = 128;
-			return RES_OK;
-			break;
-
-		default:
-			return RES_PARERR;
-	}
-	return RES_PARERR;
-}
-
-static const block_disk_opts_t sdhc_spi_disk_opts = {
-    .initialize = sdhc_spi_initialize,
-    .status = sdhc_spi_status,
-    .read = sdhc_spi_read,
-    .write = sdhc_spi_write,
-    .ioctl = sdhc_spi_ioctl,
-};
-
-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;
-}
-
-#else
-void *luat_spi_get_sdhc_ctrl(void)
-{
-	return NULL;
-}
-#endif
+/*
+ * 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.
+ */
+
+
+
+#include "luat_base.h"
+#include "luat_spi.h"
+#include "luat_lcd.h"
+#include "luat_timer.h"
+#include "luat_malloc.h"
+#include "stdlib.h"
+#include "string.h"
+#include "ff.h"			/* Obtains integer types */
+#include "diskio.h"		/* Declarations of disk functions */
+#include "app_interface.h"
+
+#define LUAT_LOG_TAG "luat.spi"
+#include "luat_log.h"
+
+typedef struct
+{
+	uint8_t id;
+//	uint8_t mark;
+    uint8_t mode;//spi模式
+}Spi_Struct;
+
+static Spi_Struct luat_spi[6] ={0};
+
+int32_t luat_spi_cb(void *pData, void *pParam){
+//    LLOGD("luat_spi_cb pData:%d pParam:%d ",(int)pData,(int)pParam);
+//    switch ((int)pData){
+//        case 0:
+//            luat_spi[5].mark = 0;
+//            break;
+//        case 1:
+//            luat_spi[0].mark = 0;
+//            break;
+//        case 2:
+//            luat_spi[1].mark = 0;
+//            break;
+//        case 3:
+//            luat_spi[2].mark = 0;
+//            break;
+//        default:
+//            break;
+//    }
+}
+
+int luat_spi_device_config(luat_spi_device_t* spi_dev) {
+    uint8_t spi_mode = SPI_MODE_0;
+    if(spi_dev->spi_config.CPHA&&spi_dev->spi_config.CPOL)spi_mode = SPI_MODE_3;
+    else if(spi_dev->spi_config.CPOL)spi_mode = SPI_MODE_2;
+    else if(spi_dev->spi_config.CPHA)spi_mode = SPI_MODE_1;
+    SPI_SetNewConfig(luat_spi[spi_dev->bus_id].id, spi_dev->spi_config.bandrate, spi_mode);
+    return 0;
+}
+
+int luat_spi_bus_setup(luat_spi_device_t* spi_dev){
+    int bus_id = spi_dev->bus_id;
+    if (bus_id == 0) {
+        luat_spi[bus_id].id=SPI_ID0;
+        GPIO_Iomux(GPIOB_12, 0);
+        GPIO_Iomux(GPIOB_14, 0);
+        GPIO_Iomux(GPIOB_15, 0);
+    }
+    else if (bus_id == 1) {
+        luat_spi[bus_id].id=SPI_ID1;
+	    GPIO_Iomux(GPIOA_06,3);
+	    GPIO_Iomux(GPIOA_08,3);
+	    GPIO_Iomux(GPIOA_09,3);
+    }
+    else if (bus_id == 2) {
+        luat_spi[bus_id].id=SPI_ID2;
+	    GPIO_Iomux(GPIOB_02,0);
+	    GPIO_Iomux(GPIOB_04,0);
+	    GPIO_Iomux(GPIOB_05,0);
+    }
+    else if (bus_id == 5) {
+        luat_spi[bus_id].id=HSPI_ID0;
+	    GPIO_Iomux(GPIOC_12,3);
+	    GPIO_Iomux(GPIOC_13,3);
+	    GPIO_Iomux(GPIOC_15,3);
+    }
+    else {
+        return -1;
+    }
+    uint8_t spi_mode = SPI_MODE_0;
+    if(spi_dev->spi_config.CPHA&&spi_dev->spi_config.CPOL)spi_mode = SPI_MODE_3;
+    else if(spi_dev->spi_config.CPOL)spi_mode = SPI_MODE_2;
+    else if(spi_dev->spi_config.CPHA)spi_mode = SPI_MODE_1;
+    luat_spi[bus_id].mode=spi_dev->spi_config.mode;
+    // LLOGD("SPI_MasterInit luat_bus_%d:%d dataw:%d spi_mode:%d bandrate:%d ",bus_id,luat_spi[bus_id].id, spi_dev->spi_config.dataw, spi_mode, spi_dev->spi_config.bandrate);
+    SPI_MasterInit(luat_spi[bus_id].id, spi_dev->spi_config.dataw, spi_mode, spi_dev->spi_config.bandrate, luat_spi_cb, NULL);
+    return 0;
+}
+
+//初始化配置SPI各项参数,并打开SPI
+//成功返回0
+int luat_spi_setup(luat_spi_t* spi) {
+    uint8_t spi_id = spi->id;
+    if (spi_id == 0) {
+        luat_spi[spi_id].id=SPI_ID0;
+        if (spi->cs == 0 || spi->cs == GPIOB_13)
+            GPIO_Iomux(GPIOB_13, 0);
+        GPIO_Iomux(GPIOB_12, 0);
+        GPIO_Iomux(GPIOB_14, 0);
+        GPIO_Iomux(GPIOB_15, 0);
+    }
+    else if (spi_id == 1) {
+        luat_spi[spi_id].id=SPI_ID1;
+        if (spi->cs == 0 || spi->cs == GPIOA_07)
+	        GPIO_Iomux(GPIOA_07,3);
+	    GPIO_Iomux(GPIOA_06,3);
+	    GPIO_Iomux(GPIOA_08,3);
+	    GPIO_Iomux(GPIOA_09,3);
+    }
+    else if (spi_id == 2) {
+        luat_spi[spi_id].id=SPI_ID2;
+        if (spi->cs == 0 || spi->cs == GPIOB_03)
+	        GPIO_Iomux(GPIOB_03,0);
+	    GPIO_Iomux(GPIOB_02,0);
+	    GPIO_Iomux(GPIOB_04,0);
+	    GPIO_Iomux(GPIOB_05,0);
+    }
+    else if (spi_id == 5) {
+        luat_spi[spi_id].id=HSPI_ID0;
+        if (spi->cs == 0 || spi->cs == GPIOC_14)
+	        GPIO_Iomux(GPIOC_14,3);
+	    GPIO_Iomux(GPIOC_12,3);
+	    GPIO_Iomux(GPIOC_13,3);
+	    GPIO_Iomux(GPIOC_15,3);
+    }
+    else {
+        return -1;
+    }
+    uint8_t spi_mode = SPI_MODE_0;
+    if(spi->CPHA&&spi->CPOL)spi_mode = SPI_MODE_3;
+    else if(spi->CPOL)spi_mode = SPI_MODE_2;
+    else if(spi->CPHA)spi_mode = SPI_MODE_1;
+    luat_spi[spi_id].mode=spi->mode;
+//    LLOGD("SPI_MasterInit luat_spi%d:%d dataw:%d spi_mode:%d bandrate:%d ",spi_id,luat_spi[spi_id].id, spi->dataw, spi_mode, spi->bandrate);
+    SPI_MasterInit(luat_spi[spi_id].id, spi->dataw, spi_mode, spi->bandrate, luat_spi_cb, NULL);
+    return 0;
+}
+
+int luat_spi_config_dma(int spi_id, uint32_t tx_channel, uint32_t rx_channel)
+{
+//	if (luat_spi[spi_id].id != HSPI_ID0) {
+//		SPI_DMATxInit(luat_spi[spi_id].id, (tx_channel >= 8)?ETH_SPI_TX_DMA_STREAM:tx_channel, 0);
+//		SPI_DMARxInit(luat_spi[spi_id].id, (rx_channel >= 8)?ETH_SPI_RX_DMA_STREAM:rx_channel, 0);
+//	}
+//	else
+//	{
+//		SPI_DMATxInit(luat_spi[spi_id].id, (tx_channel >= 8)?LCD_SPI_TX_DMA_STREAM:tx_channel, 0);
+//		SPI_DMARxInit(luat_spi[spi_id].id, (rx_channel >= 8)?LCD_SPI_RX_DMA_STREAM:rx_channel, 0);
+//	}
+}
+
+//关闭SPI,成功返回0
+int luat_spi_close(int spi_id) {
+    return 0;
+}
+//收发SPI数据,返回接收字节数
+int luat_spi_transfer(int spi_id, const char* send_buf, size_t send_length, char* recv_buf, size_t recv_length) {
+    // LLOGD("SPI_MasterInit luat_spi%d:%d send_buf:%x recv_buf:%x length:%d ",spi_id,luat_spi[spi_id], *send_buf, *recv_buf, length);
+    // while(luat_spi[spi_id].mark)
+//    luat_spi[spi_id].mark = 1;
+    int32_t result = 0;
+    if(luat_spi[spi_id].mode==0)
+        result = SPI_FlashBlockTransfer(luat_spi[spi_id].id, send_buf, send_length, recv_buf, recv_length);
+    else
+        result = SPI_BlockTransfer(luat_spi[spi_id].id, send_buf, recv_buf, recv_length);
+    if(result)
+        return 0;
+    return recv_length;
+}
+//收SPI数据,返回接收字节数
+int luat_spi_recv(int spi_id, char* recv_buf, size_t length) {
+    // LLOGD("SPI_MasterInit luat_spi%d:%d recv_buf:%x length:%d ",spi_id,luat_spi[spi_id], *recv_buf, length);
+    // while(luat_spi[spi_id].mark)
+//    luat_spi[spi_id].mark = 1;
+    if(SPI_BlockTransfer(luat_spi[spi_id].id, recv_buf, recv_buf, length))
+        return 0;
+    return length;
+}
+//发SPI数据,返回发送字节数
+int luat_spi_send(int spi_id, const char* send_buf, size_t length) {
+    // LLOGD("luat_spi_send luat_spi%d:%d send_buf:%x length:%d ",spi_id,luat_spi[spi_id], *send_buf, length);
+    // while(luat_spi[spi_id].mark)
+//    luat_spi[spi_id].mark = 1;
+    if(SPI_BlockTransfer(luat_spi[spi_id].id, send_buf, NULL, length))
+        return 0;
+    return length;
+}
+
+int luat_spi_change_speed(int spi_id, uint32_t speed)
+{
+	SPI_SetNewConfig(luat_spi[spi_id].id, speed, 0xff);
+	return 0;
+}
+
+int luat_spi_no_block_transfer(int spi_id, uint8_t *tx_buff, uint8_t *rx_buff, size_t len, void *CB, void *pParam)
+{
+	if (SPI_IsTransferBusy(luat_spi[spi_id].id)) return -1;
+	SPI_SetCallbackFun(luat_spi[spi_id].id, CB, pParam);
+	SPI_SetNoBlock(luat_spi[spi_id].id);
+	return SPI_Transfer(luat_spi[spi_id].id, tx_buff, rx_buff, len, 0);
+
+}
+
+int luat_lcd_draw_no_block(luat_lcd_conf_t* conf, int16_t x1, int16_t y1, int16_t x2, int16_t y2, luat_color_t* color, uint8_t last_flush)
+{
+	uint32_t retry_cnt = 0;
+	uint32_t cache_len = Core_LCDDrawCacheLen();
+//	if (last_flush)
+//	{
+//		LLOGD("lcd flush done!");
+//	}
+	if (x1 < 0 || y1 < 0 || x2 > conf->w || y2 > conf->h) {
+		// 暂不支持屏幕外绘制
+	}
+
+	if (conf->port == LUAT_LCD_SPI_DEVICE){
+		while (Core_LCDDrawCacheLen() > (conf->buffer_size))
+		{
+			retry_cnt++;
+			luat_timer_mdelay(1);
+		}
+		if (retry_cnt)
+		{
+			LLOGD("lcd flush delay %ums, status %u,%u,%u,%d", retry_cnt, cache_len, x2-x1+1, y2-y1+1, last_flush);
+		}
+		LCD_DrawStruct *draw = zalloc(sizeof(LCD_DrawStruct));
+		if (!draw)
+		{
+			LLOGE("lcd flush no memory");
+			return -1;
+		}
+		luat_spi_device_t* spi_dev = (luat_spi_device_t*)conf->lcd_spi_device;
+		int spi_id = spi_dev->bus_id;
+	    uint8_t spi_mode = SPI_MODE_0;
+	    if(spi_dev->spi_config.CPHA&&spi_dev->spi_config.CPOL)spi_mode = SPI_MODE_3;
+	    else if(spi_dev->spi_config.CPOL)spi_mode = SPI_MODE_2;
+	    else if(spi_dev->spi_config.CPHA)spi_mode = SPI_MODE_1;
+	    draw->DCDelay = conf->dc_delay_us;
+	    draw->Mode = spi_mode;
+	    draw->Speed = spi_dev->spi_config.bandrate;
+	    draw->SpiID = luat_spi[spi_id].id;
+	    draw->CSPin = spi_dev->spi_config.cs;
+	    draw->DCPin = conf->pin_dc;
+	    draw->x1 = x1;
+	    draw->x2 = x2;
+	    draw->y1 = y1;
+	    draw->y2 = y2;
+	    draw->xoffset = conf->xoffset;
+	    draw->yoffset = conf->yoffset;
+	    draw->Size = (draw->x2 - draw->x1 + 1) * (draw->y2 - draw->y1 + 1) * 2;
+	    draw->ColorMode = COLOR_MODE_RGB_565;
+	    draw->Data = malloc(draw->Size);
+		if (!draw->Data)
+		{
+			LLOGE("lcd flush data no memory");
+			free(draw);
+			return -1;
+		}
+	    memcpy(draw->Data, color, draw->Size);
+	    Core_LCDDraw(draw);
+	    return 0;
+	}
+	else
+	{
+		return -1;
+	}
+}
+
+int luat_spi_get_hw_bus(int spi_id)
+{
+	return luat_spi[spi_id].id;
+}
+
+void luat_lcd_draw_block(luat_lcd_conf_t* conf, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, luat_color_t* color, uint8_t last_flush)
+{
+	LCD_DrawStruct draw;
+	if (conf->port == LUAT_LCD_SPI_DEVICE){
+		luat_spi_device_t* spi_dev = (luat_spi_device_t*)conf->lcd_spi_device;
+		int spi_id = spi_dev->bus_id;
+	    uint8_t spi_mode = SPI_MODE_0;
+	    if(spi_dev->spi_config.CPHA&&spi_dev->spi_config.CPOL)spi_mode = SPI_MODE_3;
+	    else if(spi_dev->spi_config.CPOL)spi_mode = SPI_MODE_2;
+	    else if(spi_dev->spi_config.CPHA)spi_mode = SPI_MODE_1;
+	    draw.DCDelay = conf->dc_delay_us;
+	    draw.Mode = spi_mode;
+	    draw.Speed = spi_dev->spi_config.bandrate;
+	    draw.SpiID = luat_spi[spi_id].id;
+	    draw.CSPin = spi_dev->spi_config.cs;
+	    draw.DCPin = conf->pin_dc;
+	    draw.x1 = x1;
+	    draw.x2 = x2;
+	    draw.y1 = y1;
+	    draw.y2 = y2;
+	    draw.xoffset = conf->xoffset;
+	    draw.yoffset = conf->yoffset;
+	    draw.Size = (draw.x2 - draw.x1 + 1) * (draw.y2 - draw.y1 + 1) * 2;
+	    draw.ColorMode = COLOR_MODE_RGB_565;
+	    draw.Data = color;
+	    Core_LCDDrawBlock(&draw);
+	}
+}
+
+#ifdef LUAT_USE_LCD_CUSTOM_DRAW
+int luat_lcd_flush(luat_lcd_conf_t* conf) {
+    if (conf->buff == NULL) {
+        return 0;
+    }
+    //LLOGD("luat_lcd_flush range %d %d", conf->flush_y_min, conf->flush_y_max);
+    if (conf->flush_y_max < conf->flush_y_min) {
+        // 没有需要刷新的内容,直接跳过
+        //LLOGD("luat_lcd_flush no need");
+        return 0;
+    }
+    if (conf->is_init_done) {
+    	luat_lcd_draw_no_block(conf, 0, conf->flush_y_min, conf->w - 1, conf->flush_y_max, &conf->buff[conf->flush_y_min * conf->w], 0);
+    }
+    else {
+        uint32_t size = conf->w * (conf->flush_y_max - conf->flush_y_min + 1) * 2;
+        luat_lcd_set_address(conf, 0, conf->flush_y_min, conf->w - 1, conf->flush_y_max);
+        const char* tmp = (const char*)(conf->buff + conf->flush_y_min * conf->w);
+    	if (conf->port == LUAT_LCD_SPI_DEVICE){
+    		luat_spi_device_send((luat_spi_device_t*)(conf->lcd_spi_device), tmp, size);
+    	}else{
+    		luat_spi_send(conf->port, tmp, size);
+    	}
+    }
+    // 重置为不需要刷新的状态
+    conf->flush_y_max = 0;
+    conf->flush_y_min = conf->h;
+
+    return 0;
+}
+
+int luat_lcd_draw(luat_lcd_conf_t* conf, int16_t x1, int16_t y1, int16_t x2, int16_t y2, luat_color_t* color) {
+    if (x1 >= conf->w || y1 >= conf->h || x2 < 0 || y2 < 0 || x2 < x1 || y2 < y1) {
+        // LLOGE("out of lcd buff range %d %d %d %d", x1, y1, x2, y2);
+        // LLOGE("out of lcd buff range %d %d %d %d %d", x1 >= conf->w, y1 >= conf->h, y2 < 0, x2 < x1, y2 < y1);
+        return 0;
+    }
+    if (y2 >= conf->h) {
+        y2 = conf->h - 1;
+    }
+    // 直接刷屏模式
+    if (conf->buff == NULL) {
+        // 常规数据, 整体传输
+        if (x1 >= 0 && y1 >= 0 && x2 <= conf->w && y2 <= conf->h) {
+			if (conf->is_init_done) {
+				return luat_lcd_draw_no_block(conf, x1, y1, x2, y2, color, 0);
+			}
+            uint32_t size = (x2 - x1 + 1) * (y2 - y1 + 1);
+            // LLOGD("draw %dx%d %dx%d %d", x1, y1, x2, y2, size);
+            luat_lcd_set_address(conf, x1, y1, x2, y2);
+	        if (conf->port == LUAT_LCD_SPI_DEVICE){
+		        luat_spi_device_send((luat_spi_device_t*)(conf->lcd_spi_device), (const char*)color, size* sizeof(luat_color_t));
+	        }else{
+		        luat_spi_send(conf->port, (const char*)color, size * sizeof(luat_color_t));
+	        }
+        }
+        // 超出边界的数据, 按行传输
+        else {
+            int line_size = (x2 - x1 + 1);
+            // LLOGD("want draw %dx%d %dx%d %d", x1, y1, x2, y2, line_size);
+            luat_color_t* ptr = (luat_color_t*)color;
+            for (int i = y1; i <= y2; i++)
+            {
+                if (i < 0) {
+                    ptr += line_size;
+                    continue;
+                }
+                luat_color_t* line = ptr;
+                int lsize = line_size;
+                int tmp_x1 = x1;
+                int tmp_x2 = x2;
+                if (x1 < 0) {
+                    line += ( - x1);
+                    lsize += (x1);
+                    tmp_x1 = 0;
+                }
+                if (x2 > conf->w) {
+                    lsize -= (conf->w - x2);
+                    tmp_x2 = conf->w;
+                }
+				// LLOGD("action draw %dx%d %dx%d %d", tmp_x1, i, tmp_x2, i, lsize);
+				if (conf->is_init_done) {
+					luat_lcd_draw_no_block(conf, tmp_x1, i, tmp_x2, i, line, 0);
+				}
+				else {
+                	luat_lcd_set_address(conf, tmp_x1, i, tmp_x2, i);
+	            	if (conf->port == LUAT_LCD_SPI_DEVICE){
+		            	luat_spi_device_send((luat_spi_device_t*)(conf->lcd_spi_device), (const char*)line, lsize * sizeof(luat_color_t));
+	            	} else{
+		            	luat_spi_send(conf->port, (const char*)line, lsize * sizeof(luat_color_t));
+	            	}
+				}
+                ptr += line_size;
+            }
+        }
+        return 0;
+    }
+    // buff模式
+    luat_color_t* dst = (conf->buff);
+    size_t lsize = (x2 - x1 + 1);
+    for (int16_t x = x1; x <= x2; x++)
+    {
+        if (x < 0 || x >= conf->w)
+            continue;
+        for (int16_t y = y1; y <= y2; y++)
+        {
+            if (y < 0 || y >= conf->h)
+                continue;
+            memcpy((char*)(dst + (conf->w * y + x)), (char*)(color + (lsize * (y-y1) + (x-x1))), sizeof(luat_color_t));
+        }
+    }
+    // 存储需要刷新的区域
+    if (y1 < conf->flush_y_min) {
+        if (y1 >= 0)
+            conf->flush_y_min = y1;
+        else
+            conf->flush_y_min = 0;
+    }
+    if (y2 > conf->flush_y_max) {
+        conf->flush_y_max = y2;
+    }
+    return 0;
+}
+#endif
+
+#if 1
+static void *luat_fatfs_spi_ctrl;
+static HANDLE luat_fatfs_locker;
+static void sdhc_spi_check(luat_fatfs_spi_t* userdata)
+{
+	if (!luat_fatfs_spi_ctrl)
+	{
+		if(userdata->type == 1){
+			luat_fatfs_spi_ctrl = SDHC_SpiCreate(luat_spi[userdata->spi_device->bus_id].id, userdata->spi_device->spi_config.cs);
+			luat_spi_device_config(userdata->spi_device);
+		}else{
+			luat_fatfs_spi_ctrl = SDHC_SpiCreate(luat_spi[userdata->spi_id].id, userdata->spi_cs);
+		}
+	}
+}
+
+static DSTATUS sdhc_spi_initialize(luat_fatfs_spi_t* userdata)
+{
+	int i;
+	if (!luat_fatfs_locker)
+	{
+		luat_fatfs_locker = OS_MutexCreateUnlock();
+	}
+	OS_MutexLock(luat_fatfs_locker);
+	if (luat_fatfs_spi_ctrl)
+	{
+		for(i = 0; i < USB_MAX; i++)
+		{
+			Core_UDiskDetachSDHC(i, luat_fatfs_spi_ctrl);
+		}
+		SDHC_SpiRelease(luat_fatfs_spi_ctrl);
+		free(luat_fatfs_spi_ctrl);
+		luat_fatfs_spi_ctrl = NULL;
+	}
+	sdhc_spi_check(userdata);
+	SDHC_SpiInitCard(luat_fatfs_spi_ctrl);
+	if(userdata->type == 1){
+		userdata->spi_device->spi_config.bandrate = userdata->fast_speed;
+		luat_spi_device_config(userdata->spi_device);
+	}else{
+		SPI_SetNewConfig(luat_spi[userdata->spi_id].id, userdata->fast_speed, 0);
+	}
+	if (SDHC_IsReady(luat_fatfs_spi_ctrl))
+	{
+		for(i = 0; i < USB_MAX; i++)
+		{
+			Core_UDiskAttachSDHCRecovery(i, luat_fatfs_spi_ctrl);
+		}
+	}
+	OS_MutexRelease(luat_fatfs_locker);
+	return SDHC_IsReady(luat_fatfs_spi_ctrl)?0:STA_NOINIT;
+}
+
+static DSTATUS sdhc_spi_status(luat_fatfs_spi_t* userdata)
+{
+	OS_MutexLock(luat_fatfs_locker);
+	sdhc_spi_check(userdata);
+	OS_MutexRelease(luat_fatfs_locker);
+	return SDHC_IsReady(luat_fatfs_spi_ctrl)?0:STA_NOINIT;
+}
+
+static DRESULT sdhc_spi_read(luat_fatfs_spi_t* userdata, uint8_t* buff, uint32_t sector, uint32_t count)
+{
+	OS_MutexLock(luat_fatfs_locker);
+	sdhc_spi_check(userdata);
+	if (!SDHC_IsReady(luat_fatfs_spi_ctrl))
+	{
+		OS_MutexRelease(luat_fatfs_locker);
+		return RES_NOTRDY;
+	}
+	SDHC_SpiReadBlocks(luat_fatfs_spi_ctrl, buff, sector, count);
+	OS_MutexRelease(luat_fatfs_locker);
+	return SDHC_IsReady(luat_fatfs_spi_ctrl)?RES_OK:RES_ERROR;
+}
+
+static DRESULT sdhc_spi_write(luat_fatfs_spi_t* userdata, const uint8_t* buff, uint32_t sector, uint32_t count)
+{
+	OS_MutexLock(luat_fatfs_locker);
+	sdhc_spi_check(userdata);
+	if (!SDHC_IsReady(luat_fatfs_spi_ctrl))
+	{
+		OS_MutexRelease(luat_fatfs_locker);
+		return RES_NOTRDY;
+	}
+	SDHC_SpiWriteBlocks(luat_fatfs_spi_ctrl, buff, sector, count);
+	OS_MutexRelease(luat_fatfs_locker);
+	return SDHC_IsReady(luat_fatfs_spi_ctrl)?RES_OK:RES_ERROR;
+}
+
+static DRESULT sdhc_spi_ioctl(luat_fatfs_spi_t* userdata, uint8_t ctrl, void* buff)
+{
+	OS_MutexLock(luat_fatfs_locker);
+	sdhc_spi_check(userdata);
+	if (!SDHC_IsReady(luat_fatfs_spi_ctrl))
+	{
+		OS_MutexRelease(luat_fatfs_locker);
+		return RES_NOTRDY;
+	}
+	SDHC_SpiReadCardConfig(luat_fatfs_spi_ctrl);
+	OS_MutexRelease(luat_fatfs_locker);
+	switch (ctrl) {
+		case CTRL_SYNC :		/* Make sure that no pending write process */
+			return RES_OK;
+			break;
+
+		case GET_SECTOR_COUNT :	/* Get number of sectors on the disk (DWORD) */
+			*(uint32_t*)buff = SDHC_GetLogBlockNbr(luat_fatfs_spi_ctrl);
+			return RES_OK;
+			break;
+
+		case GET_BLOCK_SIZE :	/* Get erase block size in unit of sector (DWORD) */
+			*(uint32_t*)buff = 128;
+			return RES_OK;
+			break;
+
+		default:
+			return RES_PARERR;
+	}
+	return RES_PARERR;
+}
+
+static const block_disk_opts_t sdhc_spi_disk_opts = {
+    .initialize = sdhc_spi_initialize,
+    .status = sdhc_spi_status,
+    .read = sdhc_spi_read,
+    .write = sdhc_spi_write,
+    .ioctl = sdhc_spi_ioctl,
+};
+
+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;
+}
+
+#else
+void *luat_spi_get_sdhc_ctrl(void)
+{
+	return NULL;
+}
+#endif